30 类的 LSTM,严重过拟合,不能超过 76% 的测试准确率
Posted
技术标签:
【中文标题】30 类的 LSTM,严重过拟合,不能超过 76% 的测试准确率【英文标题】:LSTM for 30 classes, badly overfitting, cannot go over 76% test accuracy 【发布时间】:2021-03-07 08:57:11 【问题描述】:如何将职位描述分类到各自的行业?
我正在尝试使用 LSTM 对文本进行分类,尤其是转换职位描述 进入行业类别,不幸的是我到目前为止尝试过的东西 仅导致 76% 的准确率。
使用 LSTM 对 30 多个类的文本进行分类的有效方法是什么?
我尝试了三种选择
模型_1
Model_1 的测试准确率达到 65%
embedding_dimension = 80
max_sequence_length = 3000
历元 = 50
batch_size = 100
model = Sequential()
model.add(Embedding(max_words, embedding_dimension, input_length=x_shape))
model.add(SpatialDropout1D(0.2))
model.add(LSTM(100, dropout=0.2, recurrent_dropout=0.2))
model.add(Dense(output_dim, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
模型_2
Model_2 的测试准确率达到 64%
model = Sequential()
model.add(Embedding(max_words, embedding_dimension, input_length=x_shape))
model.add(LSTM(100))
model.add(Dropout(rate=0.5))
model.add(Dense(128, activation='relu', kernel_initializer='he_uniform'))
model.add(Dropout(rate=0.5))
model.add(Dense(64, activation='relu', kernel_initializer='he_uniform'))
model.add(Dropout(rate=0.5))
model.add(Dense(output_dim, activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['acc'])
模型_3
Model_3 的测试准确率达到 76%
model.add(Embedding(max_words, embedding_dimension, input_length= x_shape, trainable=False))
model.add(SpatialDropout1D(0.4))
model.add(LSTM(100, dropout=0.4, recurrent_dropout=0.4))
model.add(Dense(128, activation='sigmoid', kernel_initializer=RandomNormal(mean=0.0, stddev=0.039, seed=None)))
model.add(BatchNormalization())
model.add(Dense(64, activation='sigmoid', kernel_initializer=RandomNormal(mean=0.0, stddev=0.55, seed=None)) )
model.add(BatchNormalization())
model.add(Dense(32, activation='sigmoid', kernel_initializer=RandomNormal(mean=0.0, stddev=0.55, seed=None)) )
model.add(BatchNormalization())
model.add(Dense(output_dim, activation='softmax'))
model.compile(optimizer= "adam" , loss='categorical_crossentropy', metrics=['acc'])
我想知道如何提高网络的准确性。
【问题讨论】:
你尝试过不同的时代*吗? 你有多少条记录 请记住,“十万”是印度以外的任何人都不知道的数字前缀。 数据集有195k行,感谢@Scotty1-的建议 【参考方案1】:从最小的基线开始
您的代码顶部有一个简单的网络,但请尝试将其作为您的基线
model = Sequential()
model.add(Embedding(max_words, embedding_dimension, input_length=x_shape))
model.add(LSTM(output_dim//4)),
model.add(Dense(output_dim, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
这里的直觉是看 LSTM 能做多少工作。我们不需要它来输出完整的 30 个 output_dims(类的数量),而是需要一组较小的特征来决定类。
您的大型网络具有像 Dense(128) 这样的层,具有 100 个输入。那就是 100x128 = 12,800 个连接来学习。
立即改善不平衡
您的数据可能存在很多不平衡,因此对于下一步,让我们使用称为 top_k_loss 的损失函数来解决这个问题。此损失函数将使您的网络仅在遇到最大问题的训练示例上进行训练。这可以很好地处理类不平衡而无需任何其他管道
def top_k_loss(k=16):
@tf.function
def loss(y_true, y_pred):
y_error_of_true = tf.keras.losses.categorical_crossentropy(y_true=y_true,y_pred=y_pred)
topk, indexs = tf.math.top_k( y_error_of_true, k=tf.minimum(k, y_true.shape[0]) )
return topk
return loss
将其与 128 到 512 的批量大小一起使用。您可以像这样将它添加到您的模型编译中
model.compile(loss=top_k_loss(16), optimizer='adam', metrics=['accuracy']
现在,您将看到在此使用model.fit
将返回一些令人失望的数字。那是因为它只报告每个训练批次中最差的 16 个。使用您的常规损失重新编译并运行 model.evaluate
以了解它在训练和测试中的表现。
训练 100 个 epoch,此时您应该已经看到了一些不错的结果。
后续步骤
让整个模型生成并测试成这样的函数
def run_experiment(lstm_layers=1, lstm_size=output_dim//4, dense_layers=0, dense_size=output_dim//4):
model = Sequential()
model.add(Embedding(max_words, embedding_dimension, input_length=x_shape))
for i in range(lstm_layers-1):
model.add(LSTM(lstm_size, return_sequences=True)),
model.add(LSTM(lstm_size)),
for i in range(dense_layers):
model.add(Dense(dense_size, activation='tanh'))
model.add(Dense(output_dim, activation='softmax'))
model.compile(loss=top_k_loss(16), optimizer='adam', metrics=['accuracy'])
model.fit(x=x,y=y,epochs=100)
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
loss, accuracy = model.evaluate(x=x_test, y=y_test)
return loss
它可以为您运行整个实验。现在是通过搜索找到更好的架构的问题。一种搜索方式是随机的。随机其实真的很好。如果你想变得花哨,我推荐 hyperopt。不要为网格搜索而烦恼,对于大型搜索空间,随机通常会胜过它。
best_loss = 10**10
best_config = []
for trial in range(100):
config = [
randint(1,4), # lstm layers
randint(8,64), # lstm_size
randint(0,8), # dense_layers
randint(8,64) # dense_size
]
result = run_experiment(*config)
if result < best_loss:
best_config = config
print('Found a better loss ',result,' from config ',config)
【讨论】:
以上是关于30 类的 LSTM,严重过拟合,不能超过 76% 的测试准确率的主要内容,如果未能解决你的问题,请参考以下文章
Scikit-Learn 逻辑回归严重过拟合数字分类训练数据