关于lstm下分类模型中,loss持续减少,而acc和val_acc始终不变的分析

项目场景:

最近在做一个用简单的lstm预测时序数据分类的模型,在训练过程中,出现了loss在持续减小,而acc和val_acc始终不变的情况,经过不断的调参,找到了其中的问题,在此记录下:

问题描述:

具体情况如下:
Epoch 00002: val_acc did not improve from 0.44288
Epoch 3/60
94790/94790 [==============================] - 26s 272us/step - loss: 1.0569 - acc: 0.4529 - val_loss: 1.0849 - val_acc: 0.4429

Epoch 00003: val_acc did not improve from 0.44288
Epoch 4/60
94790/94790 [==============================] - 26s 273us/step - loss: 1.0550 - acc: 0.4520 - val_loss: 1.0843 - val_acc: 0.4429

Epoch 00004: val_acc did not improve from 0.44288
Epoch 5/60
94790/94790 [==============================] - 26s 273us/step - loss: 1.0530 - acc: 0.4514 - val_loss: 1.0838 - val_acc: 0.4429

Epoch 00005: val_acc did not improve from 0.44288
Epoch 6/60
94790/94790 [==============================] - 26s 272us/step - loss: 1.0520 - acc: 0.4530 - val_loss: 1.0840 - val_acc: 0.4429

Epoch 00006: val_acc did not improve from 0.44288
Epoch 7/60
94790/94790 [==============================] - 26s 275us/step - loss: 1.0520 - acc: 0.4533 - val_loss: 1.0834 - val_acc: 0.4429
loss和acc实在是恢复不出当时的效果了,大家请以val_loss和val_acc的变化为参考(打脸嫌疑...)

原因分析:

遇到loss减小,而acc不变的情况,基本上就是因为梯度减小方向是局部极小值造成的。 例如:对于一个2分类问题来讲。真实值是(0,1),而预测值1是(0.7, 0)、预测值2是(0.5,0),显然预测值2要比预测值1的loss小,因为预测值2与真实值更接近。可是对于acc的计算来讲,这两个预测值都是错的(两个预测值的最终分类相同),因此他们的准确率都是0。 所以我们的目标不是希望在错误的维度上越来越小,而是应该在正确的维度上越来越大。比如预测值(0.5, 0)和(0, 0.5),同样的loss,但是acc却不一样。

解决方案:

1.调整学习率,这种情况下一般都是学习率太小造成的,可以适当的增加学习率。一个好的学习率,在前几个epoch时是可以看到loss和acc明显的改善的。 2.选择适当的激活函数。在我的实验中,对于Keras中的Dense层activation,当我把relu改成sigmoid后,有了一些好转。 3.选择适当的优化函数,并做好调参工作。在优化函数中,除了学习率还有很多其他参数可调,并且不是默认参数就是最好的,所以建议多尝试不同的参数值。 4.这里是个小建议:如果再遇到这类问题,就把预测值全部打印出来,就可以更直观的看出问题出在哪里了。
构建一个LSTM(Long Short-Term Memory)网络模型用于分类任务通常包含以下几个步骤: 1. **导入库模块**: ```python import numpy as np from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Embedding (如果需要输入序列) from tensorflow.keras.preprocessing.text import Tokenizer from tensorflow.keras.preprocessing.sequence import pad_sequences ``` 2. **数据预处理**: - 将文本数据转换为数字序列(如有必要使用Tokenizer) - 对序列进行填充或截断(pad_sequences) 3. **定义模型结构**: ```python model = Sequential() model.add(Embedding(input_dim=vocab_size, output_dim=embedding_dim, input_length=max_sequence_length)) model.add(LSTM(units=lstm_units, return_sequences=True if use_bidirectional else False)) # 使用双向LSTM可以增强学习 model.add(LSTM(units=lstm_units, return_sequences=False) if use_bidirectional else None) model.add(Dense(units=num_classes, activation='softmax')) # 输出层,num_classes代表类别数 ``` 4. **编译模型**: ```python model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) ``` 5. **训练模型**: ```python model.fit(X_train, y_train, epochs=num_epochs, validation_data=(X_val, y_val)) ``` 6. **评估预测**: ```python test_loss, test_acc = model.evaluate(X_test, y_test) predictions = model.predict(X_test) ``` 注意:这里的`vocab_size`是词汇表大小,`embedding_dim`是嵌入维度,`max_sequence_length`是最大序列长度,`lstm_units`是LSTM单元的数量,`use_bidirectional`是一个布尔值表示是否启用双向LSTM,`num_classes`是分类的类别数量。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值