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

【NLP】自然语言项目设计03

目录

03模型构建

代码架构核心设计说明

初步构建模型并进行训练时遇到的一些问题

问题一:模型欠拟合

使用1 model - lstm

解释使用lstm时无法正常的进行cudnn加速

使用2 model - transformer


项目简介
训练一个模型,实现歌词仿写生成

任务类型:文本生成;

数据集是一份歌词语料,训练一个模型仿写歌词。

要求
1.清洗数据。歌词语料中包含韩文等非中英文符号,可对语料做预处理,仅保留中英文与标点符号;

2.训练模型、生成歌词;

3.用Gradio网页展示生成的歌词;

需要考虑的问题
1.使用语料数据集csv:lyric.csv,不用到数据库;

2.硬件使用的gpu是5g的n卡,比较有限,项目本身数据量和模型参数规模都不是特别大;

3.使用tensorflow2.9.1gpu版本的框架进行构建;

4.使用的网络架构,以及每个部分的组件网络、骨干网络等,优先在各个环节选用目前的sota模型;

5.在模型训练过程中要使用tensorboard可视化训练过程;6.对于数据的处理,先对csv进行必要的可视化,然后进行多语言歌词清洗(可参考的步骤:多语言过滤、特殊格式处理、分词策略、序列对齐、同义词替换、句式重组等);7.项目构建严格规范文件架构,做到一个脚本做一个环节(数据预处理脚本、模型构建脚本、训练、测试、推理等等);

03模型构建

终端运行(建议使用)

python scripts/optimized_lyric_training.py

代码架构核心设计说明

脚本运行架构

模块化分工:OptimizedLyricModelV2 负责模型构建、数据处理和训练逻辑EnhancedTrainer 作为高层接口,封装训练流程并提供交互界面各模块通过数据流向连接:配置加载 → 数据处理 → 模型构建 → 训练 → 评估
模型优化策略:LSTM 模型:多层正则化(L2、Dropout、recurrent_dropout)防止过拟合Transformer 模型:轻量化设计(单层注意力块、减少头数)适配小规模数据统一使用 Adam 优化器和早停策略,平衡训练效率与泛化能力
训练流程控制:数据处理阶段限制样本量(≤30000 训练序列)动态调整学习率(因子 0.5,耐心 3 轮)严格监控验证损失,超过 8 轮无改善则早停同时记录多种评估指标(accuracy、top-k accuracy)
可视化与分析:训练历史多维度可视化(损失、准确率、学习率)过拟合量化分析(验证损失 / 训练损失比值)自动生成训练总结报告,提供优化建议

# 歌词生成模型训练系统架构(优化版)

# 1. 核心模型类:OptimizedLyricModelV2

class OptimizedLyricModelV2:

成员变量:

- config_path: 配置文件路径

- vocab_size: 词汇表大小

- max_length: 最大序列长度

- model: 构建的Keras模型

- history: 训练历史记录

- tokenizer: 分词器

# 初始化与环境配置

方法 __init__(config_path):

加载配置文件(vocab_size, max_sequence_length等)

设置GPU内存增长模式

初始化模型和历史记录为None

# GPU资源管理

方法 setup_gpu():

检测GPU设备

启用GPU内存动态分配

处理可能的GPU配置错误

# 数据加载与预处理

方法 load_data():

从npy文件加载训练和验证文本

限制数据量(训练≤10000,验证≤2000)

返回处理后的文本数据

方法 create_sequences_fixed(texts, max_samples):

将文本转换为token序列

生成输入-目标序列对(滑动窗口)

填充序列到固定长度

过滤无效序列(长度、词汇表范围)

返回X和y的numpy数组

# 模型构建(核心模块)

方法 build_regularized_lstm(embed_dim, lstm_units, dropout_rate):

定义输入层(max_length)

词嵌入层(带L2正则化)

Dropout层(减少过拟合)

LSTM层(带dropout和recurrent_dropout)

多层全连接层(带正则化和Dropout)

输出层(softmax,词汇表大小)

返回编译前的Model对象

方法 build_ultra_light_transformer(embed_dim, num_heads, ff_dim, dropout_rate):

定义输入层

词嵌入+简化位置编码

单层Transformer块(MultiHeadAttention)

Feed Forward网络(带残差连接和LayerNorm)

全局平均池化和输出层

返回编译前的Model对象

# 模型训练与评估

方法 compile_model_optimized(model, learning_rate):

配置Adam优化器(带学习率和梯度裁剪)

编译模型(损失函数、评估指标)

返回编译后的模型

方法 setup_callbacks_enhanced():

配置模型检查点(保存最佳验证loss模型)

早停策略(patience=8,监控val_loss)

学习率衰减(factor=0.5,patience=3)

TensorBoard和CSV日志记录

返回回调函数列表

方法 train_model_enhanced(model_type, epochs, batch_size):

加载并处理训练数据

根据model_type构建LSTM或Transformer模型

编译模型(优化参数)

执行模型训练(带验证集和回调)

保存最终模型

返回训练历史

方法 plot_training_history_fixed():

绘制损失、准确率、Top-k准确率曲线

显示学习率变化趋势

分析过拟合情况(损失比)

保存并显示图表

# 2. 训练控制类:EnhancedTrainer

class EnhancedTrainer:

成员变量:

- model_generator: OptimizedLyricModelV2实例

方法 __init__():

初始化模型生成器实例

方法 train_regularized_lstm(epochs, batch_size):

打印训练开始信息

调用model_generator训练LSTM模型

绘制训练历史图表

返回训练历史

方法 train_ultra_light_transformer(epochs, batch_size):

打印训练开始信息

调用model_generator训练Transformer模型

绘制训练历史图表

返回训练历史

# 3. 程序入口

if __name__ == "__main__":

创建必要的输出目录

初始化EnhancedTrainer实例

提供模型类型选择界面(LSTM或Transformer)

根据用户选择调用对应训练方法

打印训练完成信息及结果查看指引

如果电脑先前没配cudnn,还需要下载,前文已做对应说明

选择transfomer开始训练(自行选择,两个都可以用)

正常训练由于数据量很大,时间很久

demo版本快很多(但是只保留了不到10%的数据量,可以进行较快速的项目流程验证)

GPU加速下

GPU下跑30轮

资源管理器下可以看到专用显存利用率开始提高

训练过程的可视化

每一幅图对应不同次的训练(注意这里指的不是不同epoch,而是不同的整轮训练)

模型还需要优化参数,明显验证上效果不佳

也可以到tenserboard上查看更多的一些训练过程的记录

tensorboard --logdir="C:\Users\user\Desktop\nlp\logs\tensorboard\train"

请使用保存board文件的文件夹的绝对路径访问,减少一些类似‘文件找不到’的问题

初步构建模型并进行训练时遇到的一些问题
问题一:模型欠拟合

ps:我们对数据的处理、可视化,以及在模型训练过程中大费周章地进行记录,目的就是为了利用这些反馈进行反推,来找到优化模型的一些可行策略。同时,保存下来的图片数据可以结合大模型使用,让大模型帮助分析问题所在,或者可以更方便于请教更厉害的人帮忙通过建议!

可以配套的使用data_diagnostic_tool.py脚本对训练数据集做数据分布、序列长度、训练数据集和验证数据集的离群点数据分析,如下图

python scripts/data_diagnostic_tool.py

运行脚本后,图片都会对应保存到项目的文件目录下

终端反馈

Empty texts: Train=0, Val=0Sample texts:
Train 1: 满天 的 星星 绽放 着 光明 满天 的 星星 喔 喔 那么 温柔 宁静 是 无声 的 歌 是 闪烁 的 光芒 是 喜悦 的 满天 的 星星 绽放 着 光明 满天 的 星星 喔
喔 那么 温柔 宁静 ...
Train 2: 你 总是 相信 除了 我 的 心 你 总是 在乎 除了 我 的 言语 但是 就算 让 你 看清 我 的 心 也 不能 用 我 的 心 来 你 的 心 我 对 自己 说 你 是 我 用
 生命 的 酒 而...
Train 3: 别 再 想 他 好 吗 他 不 值得 你 牵挂 说话 不算 话 他 没 眼光 好 吗 不 懂 欣赏 你 的 美 温柔 别 再 想 他 好 吗 男人 不是 只有 他 机会 去 爱 的
请 有点 自信 好...=== Tokenized Data Diagnosis ===
Sequence Length Statistics:
Mean: 135.00, Std: 62.18
Min: 13, Max: 365Vocabulary Usage:
Unique tokens in sample: 2972
Configured vocab size: 3000
Max token id: 2999
✅ All tokens within vocabulary rangeMost common tokens: [(2, 8176), (3, 6953), (4, 6578), (5, 2083), (6, 1938), (7, 1624), (8, 1517), (9, 1092), (10, 1003), (12, 938)]
Least common tokens: [(2238, 1), (2948, 1), (1786, 1), (2088, 1), (2743, 1), (2108, 1), (2107, 1), (2801, 1), (2947, 1), (1872, 1)]Special tokens check:
PAD (id=0): 0 occurrences
UNK (id=1): 7 occurrences=== Training Sequences Diagnosis ===
Generated sequences: 67142
Input shape: (67142, 80)
Output shape: (67142,)Input sequences check:
X min: 0, max: 2999
Unique values in X: 2838Target labels check:
y min: 1, max: 2999
Unique labels: 2834
Labels within vocab range: TrueLabel distribution (top 10): [(2, 3964), (3, 3537), (4, 3288), (5, 1026), (6, 980), (7, 815), (8, 767), (9, 511), (10, 506), (12, 458)]
Label balance - Mean: 23.69, Std: 127.47
Most frequent label appears 3964 times
Least frequent label appears 1 times=== Optimization Suggestions ===
1. **Learning Rate**: 使用 0.0001 或更低的学习率
2. **Batch Size**: 尝试 16-64 之间的批次大小
3. **Model Architecture**: 从简单的单层 LSTM 开始
4. **Sequence Length**: 考虑将最大序列长度限制在 32-64
5. **Vocabulary**: 检查是否有超出词汇表的标签
6. **Data Quality**: 移除空文本和异常长的文本
7. **Regularization**: 增加 dropout (0.3-0.5)
8. **Gradient Clipping**: 添加梯度裁剪 (clipnorm=1.0)
9. **Early Stopping**: 使用更大的耐心值 (15-20)
10. **Data Augmentation**: 考虑数据增强技术=== Diagnosis Complete ===
Check logs/ directory for generated plots

使用1 model - lstm

lstm的参数量会比transformer少很多,可以更快的跑出h5模型,但是生成效果也肯定会对应下降,鱼和熊掌不可兼得

解释使用lstm时无法正常的进行cudnn加速

LSTM 无法使用 CuDNN 加速的直接原因:recurrent_dropout参数非零

optimized_lyric_training.py脚本的build_regularized_lstm 方法中,LSTM 层的配置为:

x = LSTM(
    lstm_units,
    dropout=dropout_rate,  # 默认0.5
    recurrent_dropout=dropout_rate,  # 默认0.5(关键问题)
    kernel_regularizer=tf.keras.regularizers.l2(1e-5),
    recurrent_regularizer=tf.keras.regularizers.l2(1e-5),
    name='lstm'
)(x)

CuDNN 对 LSTM 加速的硬性限制:

CuDNN 仅支持 recurrent_dropout=0(循环状态的 dropout 必须为 0)。当 recurrent_dropout>0 时,TensorFlow 会自动放弃 CuDNN 优化,退回到基于普通 GPU/CPU 的 LSTM 实现(性能显著下降)。

这是导致 LSTM 无法使用 CuDNN 加速的最直接原因,而 Transformer 不受此限制(其注意力机制的 dropout 与 CuDNN 兼容)。

在使用时可以根据需求对lstm训练时的参数进行修改来提高效率

使用2 model - transformer

可以使用cudnn加速

一次train的结果

(crawler) C:\Users\user\Desktop\nlp>python scripts/optimized_lyric_training.py
Config: vocab_size=3000, max_length=64
Found 1 GPU(s)
Choose optimized model type:
1. simple_lstm - Simplified LSTM model (recommended)
2. lightweight_transformer - Lightweight Transformer model
Enter choice (1 or 2): 1
Training simplified LSTM model...
=== Training Simple LSTM Model ===
Starting optimized training with simple_lstm...
Loading processed data...
Train texts: 1050
Validation texts: 225
Creating training sequences (fixed version)...
Tokenizer loaded
Created 50000 training sequences
Input shape: (50000, 64), Output shape: (50000,)
Target min: 2, max: 2999
Vocab size check: True
Creating training sequences (fixed version)...
Created 10000 training sequences
Input shape: (10000, 64), Output shape: (10000,)
Target min: 2, max: 2996
Vocab size check: True
Data validation:
  X_train range: [0, 2999]
  y_train range: [2, 2999]
  Vocab size: 3000
Building simplified LSTM model...
2025-06-23 15:08:15.202781: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX AVX2
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2025-06-23 15:08:15.555054: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1532] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 3610 MB memory:  -> device: 0, name: Quadro P2200, pci bus id: 0000:01:00.0, compute capability: 6.1
WARNING:tensorflow:Layer lstm will not use cuDNN kernels since it doesn't meet the criteria. It will use a generic GPU kernel as fallback when running on GPU.
Model compiled with learning rate: 0.0001
Model: "simple_lyric_generator"
_________________________________________________________________
 Layer (type)                Output Shape              Param #
=================================================================
 input (InputLayer)          [(None, 64)]              0 embedding (Embedding)       (None, 64, 128)           384000 lstm (LSTM)                 (None, 256)               394240 dense1 (Dense)              (None, 128)               32896 dropout (Dropout)           (None, 128)               0 dense2 (Dense)              (None, 64)                8256 dropout_1 (Dropout)         (None, 64)                0 output (Dense)              (None, 3000)              195000=================================================================
Total params: 1,014,392
Trainable params: 1,014,392
Non-trainable params: 0
_________________________________________________________________
None
Total parameters: 1,014,392
Starting training...
Epoch 1/30
 380/1563 [======>.......................] - ETA: 7:36 - loss: 7.2386 - accuracy: 0.0530 - sparse_top_k_categorical_accuracy: 0.1607Traceback (most recent call last):
  File "C:\Users\user\Desktop\nlp\scripts\optimized_lyric_training.py", line 503, in <module>
    trainer.train_simple_lstm(epochs=30, batch_size=32)
  File "C:\Users\user\Desktop\nlp\scripts\optimized_lyric_training.py", line 459, in train_simple_lstm
    history = self.model_generator.train_model_optimized(
  File "C:\Users\user\Desktop\nlp\scripts\optimized_lyric_training.py", line 353, in train_model_optimized
    self.history = self.model.fit(
  File "C:\ProgramData\Anaconda3\envs\crawler\lib\site-packages\keras\utils\traceback_utils.py", line 64, in error_handler
    return fn(*args, **kwargs)
  File "C:\ProgramData\Anaconda3\envs\crawler\lib\site-packages\keras\engine\training.py", line 1409, in fit
    tmp_logs = self.train_function(iterator)
  File "C:\ProgramData\Anaconda3\envs\crawler\lib\site-packages\tensorflow\python\util\traceback_utils.py", line 150, in error_handler
    return fn(*args, **kwargs)
  File "C:\ProgramData\Anaconda3\envs\crawler\lib\site-packages\tensorflow\python\eager\def_function.py", line 915, in __call__
    result = self._call(*args, **kwds)
  File "C:\ProgramData\Anaconda3\envs\crawler\lib\site-packages\tensorflow\python\eager\def_function.py", line 947, in _call
    return self._stateless_fn(*args, **kwds)  # pylint: disable=not-callable
  File "C:\ProgramData\Anaconda3\envs\crawler\lib\site-packages\tensorflow\python\eager\function.py", line 2453, in __call__
    return graph_function._call_flat(
  File "C:\ProgramData\Anaconda3\envs\crawler\lib\site-packages\tensorflow\python\eager\function.py", line 1860, in _call_flat
    return self._build_call_outputs(self._inference_function.call(
  File "C:\ProgramData\Anaconda3\envs\crawler\lib\site-packages\tensorflow\python\eager\function.py", line 497, in call
    outputs = execute.execute(
  File "C:\ProgramData\Anaconda3\envs\crawler\lib\site-packages\tensorflow\python\eager\execute.py", line 54, in quick_execute
    tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name,
KeyboardInterrupt
^C
(crawler) C:\Users\user\Desktop\nlp>python scripts/optimized_lyric_training.py
Config: vocab_size=3000, max_length=64
Found 1 GPU(s)
Choose optimized model type:
1. simple_lstm - Simplified LSTM model (recommended)
2. lightweight_transformer - Lightweight Transformer model
Enter choice (1 or 2): 2
Training lightweight Transformer model...
=== Training Lightweight Transformer Model ===
Starting optimized training with lightweight_transformer...
Loading processed data...
Train texts: 1050
Validation texts: 225
Creating training sequences (fixed version)...
Tokenizer loaded
Created 50000 training sequences
Input shape: (50000, 64), Output shape: (50000,)
Target min: 2, max: 2999
Vocab size check: True
Creating training sequences (fixed version)...
Created 10000 training sequences
Input shape: (10000, 64), Output shape: (10000,)
Target min: 2, max: 2996
Vocab size check: True
Data validation:
  X_train range: [0, 2999]
  y_train range: [2, 2999]
  Vocab size: 3000
Building lightweight Transformer model...
2025-06-23 15:11:00.258642: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX AVX2
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2025-06-23 15:11:00.609699: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1532] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 3610 MB memory:  -> device: 0, name: Quadro P2200, pci bus id: 0000:01:00.0, compute capability: 6.1
Model compiled with learning rate: 0.0001
Model: "lightweight_transformer"
__________________________________________________________________________________________________
 Layer (type)                   Output Shape         Param #     Connected to
==================================================================================================
 input (InputLayer)             [(None, 64)]         0           [] embedding (Embedding)          (None, 64, 128)      384000      ['input[0][0]'] tf.__operators__.add (TFOpLamb  (None, 64, 128)     0           ['embedding[0][0]']
 da) attention (MultiHeadAttention)  (None, 64, 128)     66048       ['tf.__operators__.add[0][0]',
                                                                  'tf.__operators__.add[0][0]'] add (Add)                      (None, 64, 128)      0           ['tf.__operators__.add[0][0]',
                                                                  'attention[0][0]'] norm1 (LayerNormalization)     (None, 64, 128)      256         ['add[0][0]'] ffn1 (Dense)                   (None, 64, 256)      33024       ['norm1[0][0]'] dropout (Dropout)              (None, 64, 256)      0           ['ffn1[0][0]'] ffn2 (Dense)                   (None, 64, 128)      32896       ['dropout[0][0]'] add_1 (Add)                    (None, 64, 128)      0           ['norm1[0][0]',
                                                                  'ffn2[0][0]'] norm2 (LayerNormalization)     (None, 64, 128)      256         ['add_1[0][0]'] global_average_pooling1d (Glob  (None, 128)         0           ['norm2[0][0]']
 alAveragePooling1D) dense (Dense)                  (None, 256)          33024       ['global_average_pooling1d[0][0]'
                                                                 ] dropout_1 (Dropout)            (None, 256)          0           ['dense[0][0]'] dense_1 (Dense)                (None, 3000)         771000      ['dropout_1[0][0]']==================================================================================================
Total params: 1,320,504
Trainable params: 1,320,504
Non-trainable params: 0
__________________________________________________________________________________________________
None
Total parameters: 1,320,504
Starting training...
Epoch 1/30
2025-06-23 15:11:02.805240: I tensorflow/stream_executor/cuda/cuda_dnn.cc:384] Loaded cuDNN version 8902
3121/3125 [============================>.] - ETA: 0s - loss: 6.6326 - accuracy: 0.0616 - sparse_top_k_categorical_accuracy: 0.1853
Epoch 1: val_loss improved from inf to 6.46903, saving model to models/checkpoints\best_model.h5
3125/3125 [==============================] - 38s 11ms/step - loss: 6.6318 - accuracy: 0.0617 - sparse_top_k_categorical_accuracy: 0.1853 - val_loss: 6.4690 - val_accuracy: 0.0671 - val_sparse_top_k_categorical_accuracy: 0.2081 - lr: 1.0000e-04
Epoch 2/30
3124/3125 [============================>.] - ETA: 0s - loss: 6.3139 - accuracy: 0.0679 - sparse_top_k_categorical_accuracy: 0.1994
Epoch 2: val_loss improved from 6.46903 to 6.44410, saving model to models/checkpoints\best_model.h5
3125/3125 [==============================] - 36s 12ms/step - loss: 6.3138 - accuracy: 0.0679 - sparse_top_k_categorical_accuracy: 0.1994 - val_loss: 6.4441 - val_accuracy: 0.0727 - val_sparse_top_k_categorical_accuracy: 0.2118 - lr: 1.0000e-04
Epoch 3/30
3124/3125 [============================>.] - ETA: 0s - loss: 6.1834 - accuracy: 0.0746 - sparse_top_k_categorical_accuracy: 0.2072
Epoch 3: val_loss did not improve from 6.44410
3125/3125 [==============================] - 35s 11ms/step - loss: 6.1834 - accuracy: 0.0746 - sparse_top_k_categorical_accuracy: 0.2072 - val_loss: 6.4540 - val_accuracy: 0.0761 - val_sparse_top_k_categorical_accuracy: 0.2146 - lr: 1.0000e-04
Epoch 4/30
3123/3125 [============================>.] - ETA: 0s - loss: 6.0468 - accuracy: 0.0801 - sparse_top_k_categorical_accuracy: 0.2127
Epoch 4: val_loss did not improve from 6.44410
3125/3125 [==============================] - 34s 11ms/step - loss: 6.0468 - accuracy: 0.0801 - sparse_top_k_categorical_accuracy: 0.2126 - val_loss: 6.4997 - val_accuracy: 0.0765 - val_sparse_top_k_categorical_accuracy: 0.2157 - lr: 1.0000e-04
Epoch 5/30
3124/3125 [============================>.] - ETA: 0s - loss: 5.9002 - accuracy: 0.0851 - sparse_top_k_categorical_accuracy: 0.2189
Epoch 5: val_loss did not improve from 6.44410
3125/3125 [==============================] - 34s 11ms/step - loss: 5.9004 - accuracy: 0.0851 - sparse_top_k_categorical_accuracy: 0.2189 - val_loss: 6.5466 - val_accuracy: 0.0778 - val_sparse_top_k_categorical_accuracy: 0.2155 - lr: 1.0000e-04
Epoch 6/30
3122/3125 [============================>.] - ETA: 0s - loss: 5.7502 - accuracy: 0.0888 - sparse_top_k_categorical_accuracy: 0.2264
Epoch 6: val_loss did not improve from 6.44410
3125/3125 [==============================] - 36s 11ms/step - loss: 5.7499 - accuracy: 0.0888 - sparse_top_k_categorical_accuracy: 0.2265 - val_loss: 6.6575 - val_accuracy: 0.0768 - val_sparse_top_k_categorical_accuracy: 0.2166 - lr: 1.0000e-04
Epoch 7/30
3124/3125 [============================>.] - ETA: 0s - loss: 5.5964 - accuracy: 0.0933 - sparse_top_k_categorical_accuracy: 0.2360
Epoch 7: val_loss did not improve from 6.44410Epoch 7: ReduceLROnPlateau reducing learning rate to 6.999999823165126e-05.
3125/3125 [==============================] - 35s 11ms/step - loss: 5.5964 - accuracy: 0.0933 - sparse_top_k_categorical_accuracy: 0.2359 - val_loss: 6.7108 - val_accuracy: 0.0758 - val_sparse_top_k_categorical_accuracy: 0.2171 - lr: 1.0000e-04
Epoch 8/30
3124/3125 [============================>.] - ETA: 0s - loss: 5.4345 - accuracy: 0.0969 - sparse_top_k_categorical_accuracy: 0.2455
Epoch 8: val_loss did not improve from 6.44410
3125/3125 [==============================] - 35s 11ms/step - loss: 5.4344 - accuracy: 0.0969 - sparse_top_k_categorical_accuracy: 0.2455 - val_loss: 6.8397 - val_accuracy: 0.0788 - val_sparse_top_k_categorical_accuracy: 0.2169 - lr: 7.0000e-05
Epoch 9/30
3121/3125 [============================>.] - ETA: 0s - loss: 5.3144 - accuracy: 0.0989 - sparse_top_k_categorical_accuracy: 0.2524
Epoch 9: val_loss did not improve from 6.44410
3125/3125 [==============================] - 35s 11ms/step - loss: 5.3149 - accuracy: 0.0988 - sparse_top_k_categorical_accuracy: 0.2523 - val_loss: 6.9841 - val_accuracy: 0.0782 - val_sparse_top_k_categorical_accuracy: 0.2164 - lr: 7.0000e-05
Epoch 10/30
3123/3125 [============================>.] - ETA: 0s - loss: 5.1961 - accuracy: 0.1014 - sparse_top_k_categorical_accuracy: 0.2591
Epoch 10: val_loss did not improve from 6.44410
3125/3125 [==============================] - 35s 11ms/step - loss: 5.1958 - accuracy: 0.1014 - sparse_top_k_categorical_accuracy: 0.2592 - val_loss: 7.1431 - val_accuracy: 0.0778 - val_sparse_top_k_categorical_accuracy: 0.2166 - lr: 7.0000e-05
Epoch 11/30
3124/3125 [============================>.] - ETA: 0s - loss: 5.0766 - accuracy: 0.1041 - sparse_top_k_categorical_accuracy: 0.2690
Epoch 11: val_loss did not improve from 6.44410
3125/3125 [==============================] - 35s 11ms/step - loss: 5.0764 - accuracy: 0.1041 - sparse_top_k_categorical_accuracy: 0.2691 - val_loss: 7.3413 - val_accuracy: 0.0797 - val_sparse_top_k_categorical_accuracy: 0.2108 - lr: 7.0000e-05
Epoch 12/30
3123/3125 [============================>.] - ETA: 0s - loss: 4.9588 - accuracy: 0.1083 - sparse_top_k_categorical_accuracy: 0.2783
Epoch 12: val_loss did not improve from 6.44410Epoch 12: ReduceLROnPlateau reducing learning rate to 4.899999621557071e-05.
3125/3125 [==============================] - 35s 11ms/step - loss: 4.9589 - accuracy: 0.1083 - sparse_top_k_categorical_accuracy: 0.2783 - val_loss: 7.4957 - val_accuracy: 0.0788 - val_sparse_top_k_categorical_accuracy: 0.2109 - lr: 7.0000e-05
Epoch 13/30
3121/3125 [============================>.] - ETA: 0s - loss: 4.8287 - accuracy: 0.1122 - sparse_top_k_categorical_accuracy: 0.2897
Epoch 13: val_loss did not improve from 6.44410
3125/3125 [==============================] - 35s 11ms/step - loss: 4.8284 - accuracy: 0.1123 - sparse_top_k_categorical_accuracy: 0.2898 - val_loss: 7.7862 - val_accuracy: 0.0765 - val_sparse_top_k_categorical_accuracy: 0.2070 - lr: 4.9000e-05
Epoch 14/30
3124/3125 [============================>.] - ETA: 0s - loss: 4.7442 - accuracy: 0.1173 - sparse_top_k_categorical_accuracy: 0.2986
Epoch 14: val_loss did not improve from 6.44410
3125/3125 [==============================] - 35s 11ms/step - loss: 4.7441 - accuracy: 0.1173 - sparse_top_k_categorical_accuracy: 0.2986 - val_loss: 7.8797 - val_accuracy: 0.0762 - val_sparse_top_k_categorical_accuracy: 0.2032 - lr: 4.9000e-05
Epoch 15/30
3125/3125 [==============================] - ETA: 0s - loss: 4.6604 - accuracy: 0.1197 - sparse_top_k_categorical_accuracy: 0.3073
Epoch 15: val_loss did not improve from 6.44410
3125/3125 [==============================] - 36s 11ms/step - loss: 4.6604 - accuracy: 0.1197 - sparse_top_k_categorical_accuracy: 0.3073 - val_loss: 8.0960 - val_accuracy: 0.0747 - val_sparse_top_k_categorical_accuracy: 0.1988 - lr: 4.9000e-05
Epoch 16/30
3121/3125 [============================>.] - ETA: 0s - loss: 4.5779 - accuracy: 0.1244 - sparse_top_k_categorical_accuracy: 0.3163
Epoch 16: val_loss did not improve from 6.44410
3125/3125 [==============================] - 35s 11ms/step - loss: 4.5777 - accuracy: 0.1244 - sparse_top_k_categorical_accuracy: 0.3163 - val_loss: 8.2994 - val_accuracy: 0.0738 - val_sparse_top_k_categorical_accuracy: 0.1951 - lr: 4.9000e-05
Epoch 17/30
3123/3125 [============================>.] - ETA: 0s - loss: 4.4975 - accuracy: 0.1293 - sparse_top_k_categorical_accuracy: 0.3269
Epoch 17: val_loss did not improve from 6.44410
Restoring model weights from the end of the best epoch: 2.Epoch 17: ReduceLROnPlateau reducing learning rate to 3.4299996332265434e-05.
3125/3125 [==============================] - 35s 11ms/step - loss: 4.4975 - accuracy: 0.1293 - sparse_top_k_categorical_accuracy: 0.3269 - val_loss: 8.4332 - val_accuracy: 0.0716 - val_sparse_top_k_categorical_accuracy: 0.1891 - lr: 4.9000e-05
Epoch 17: early stopping
Training completed!
Traceback (most recent call last):
  File "C:\Users\user\Desktop\nlp\scripts\optimized_lyric_training.py", line 506, in <module>
    trainer.train_lightweight_transformer(epochs=30, batch_size=16)
  File "C:\Users\user\Desktop\nlp\scripts\optimized_lyric_training.py", line 481, in train_lightweight_transformer
    self.model_generator.plot_training_history_detailed()
  File "C:\Users\user\Desktop\nlp\scripts\optimized_lyric_training.py", line 410, in plot_training_history_detailed
    for callback in self.model.history.callbacks if hasattr(self.model, 'history') else []:
AttributeError: 'History' object has no attribute 'callbacks'

分析

✅ 主要改善

Loss正常下降: 6.63 → 4.50 (训练loss)

准确率提升: 6.17% → 12.93%

Top-k准确率: 18.53% → 32.69%

Early Stopping生效: 第17个epoch合理停止

⚠️ 发现的问题

过拟合现象

验证loss: 6.47 → 8.43 (持续上升)

训练loss和验证loss差距越来越大

对于这种情况,比较好的现象就是模型欠拟合问题得到了一些改善,我们针对模型训练中出现的过拟合现象(训练 loss 持续下降但验证 loss 持续上升,两者差距扩大),后续调优可从「数据增强」「模型正则化」「结构简化」「训练策略调整」四个核心方向入手

数据层面:提升数据多样性,减少过拟合土壤

过拟合的本质是模型 “记住” 了训练数据的细节而非通用规律,数据量不足或多样性不够是常见诱因。

强化数据增强

对于demo版本的数据量进行添加,建议提升到原数据集的20%,根据设备的算力情况和可以等待的时间成本进行有进步增加,同时对分词器的分词策略也可以适当调整,

模型层面:增加正则化约束,降低过拟合风险

通过限制模型的 “拟合能力”,避免其过度捕捉训练数据中的噪声。

添加正则化项

L2 正则化(权重衰减,Weight Decay):在损失函数中加入参数的平方和惩罚(loss = 原始loss + λ*Σ(w²)),限制权重过大,默认可尝试 λ=1e-4~1e-2,根据验证效果调整。

L1 正则化:加入参数的绝对值惩罚(loss = 原始loss + λ*Σ(|w|)),会使部分权重趋于 0,实现特征选择,适合高维稀疏数据,λ 需更小(如 1e-5~1e-3)。

引入 Dropout 层

在模型的隐藏层之间添加 Dropout,训练时随机 “丢弃” 一部分神经元(如 50% 概率),强制模型不依赖特定神经元,学习更鲁棒的特征:建议在全连接层后添加Dropout(p=0.3~0.5),卷积层后可适当降低(如 p=0.1~0.3),避免过度削弱特征提取能力;

注意:Dropout 仅在训练时生效,推理时需关闭。

使用 Batch Normalization

这是从数据分布的角度进行优化,对每一层的输入进行标准化(使均值为 0、方差为 1),减少 “内部协变量偏移”,同时隐含一定的正则化效果(类似轻微的噪声注入),尤其适合深层网络,可缓解过拟合。

结构层面:简化模型复杂度,匹配数据规模

若模型参数过多、复杂度远超数据量,会导致 “能力过剩” 而过拟合,需适当简化结构。

减少模型参数

对于神经网络:减少隐藏层数量(如从 5 层减至 3 层)、降低隐藏层维度(如从 1024 维减至 512 维);

对于卷积网络:减少卷积核数量(如从 64 个减至 32 个)、移除不必要的分支结构;

对于树模型:降低树深度、减少叶子节点数量,增加正则化参数(如 XGBoost 的gamma、reg_alpha)。

采用轻量级结构

若原始模型过于复杂(如大语言模型、深层 ResNet),可替换为更简单的架构(如用 MobileNet 替代 ResNet,用 Logistic 回归替代复杂的 Transformer),优先保证泛化能力。

ps:并不是模型越复杂、参数越多训练效果就就越好,模型网络结构的复杂程度和数据集的量级应该是类似‘协同进化’的关系,如果用参数量很大的模型(比如1B的transformer)去拟合几百条、几千条这样的小数据集就小题大做了,效果也很可能不尽人意,容易过拟合(对于神经网络,随机性是很重要的,过拟合就是过分拟合数据,将随机性大大降低,使得模型失去对未知的探索、思考能力,盲目自信)

训练策略:优化训练过程,及时 “止损”

通过调整训练参数,让模型在 “拟合” 与 “泛化” 之间找到平衡。

调整早停策略(Early Stopping)

目前早停在 17epoch 生效,但验证 loss 已持续上升,可能停得太晚。可优化:监控指标:除验证 loss 外,可结合验证准确率(若验证准确率开始下降时停止);

减小patience参数(如从默认 5 调整为 3):当验证 loss 连续 3 个 epoch 未下降时立即停止,避免模型在过拟合方向继续优化。

调整 batch size 与学习率

增大 batch size:若当前 batch size 较小(如 16),可尝试增大至 32/64,使梯度估计更稳定,减少噪声影响(但需注意显存限制);

学习率衰减:训练后期采用学习率衰减(如每 3 个 epoch 衰减为原来的 0.5),避免模型在过拟合的局部最优附近震荡,增强泛化能力。

ps:对于生成式的模型训练,初始的学习率要比分类、回归等类别的模型设置得更低一点,因为生成的不确定更大,模型需要的训练成本是更多的,所以学习的过程也会更加‘曲折’!

使用标签平滑(Label Smoothing)

对训练标签添加微小噪声(如将独热编码的 1 替换为 0.9,0 替换为 0.1),避免模型对 “绝对正确” 的标签过度自信,迫使学习更鲁棒的特征,尤其适合分类任务。

进阶方案:借助外部信息提升泛化

迁移学习(Transfer Learning)

若数据量较小,可基于预训练模型(如 ImageNet 预训练的 ResNet、BERT 等)微调:冻结预训练模型的底层(学习通用特征),仅训练顶层分类器,利用大数据学到的规律提升泛化能力。集成学习(Ensemble)

训练多个不同结构的模型(如一个简化版 + 一个带 Dropout 的模型),通过投票或加权平均融合预测结果,减少单个模型的过拟合风险

相关文章:

  • 关于ubuntu 20.04系统安装分区和重复登录无法加载桌面的问题解决
  • 【数据标注】事件标注1
  • Vue工程化实现约定式路由自动注册
  • Go开发工程师-Golang基础知识篇
  • 数据结构:最小生成树—Prim(普里姆)与Kruskal(克鲁斯卡尔)算法
  • 什么是哈希链(Hash Chain)?
  • Redis 实现分布式锁
  • 分布式集群压测
  • 第8章-财务数据
  • VR训练美国服务器:高性能解决方案与优化指南
  • 培养你的眼力 - 摄影构图
  • Python 中 `for` 循环与 `while` 循环的性能差异:深度剖析
  • 思维提升篇-数学抽象与计算机实现
  • 从零开始构建RAG(检索增强生成)
  • C# 委托(为委托添加方法和从委托移除方法)
  • Excel限制编辑:保护表格的实用功能
  • 【C#】使用电脑的GPU与CPU的区别
  • 鸿蒙5:其他布局容器
  • 【Redis原理】Redis分布式缓存——主从复制、哨兵机制与Redis Cluster
  • deepin 25 交换 caps lctl