为复杂文本分类微调 CNN 超参数

Fine tuning CNN hyperparameters for complex text classification

我正在研究用于复杂文本分类(主要是电子邮件和消息)的 CNN 模型。该数据集包含分布在 10 个不同 类 上的大约 10 万个条目。我实际的 Keras 顺序模型具有以下结构:

model = Sequential(
        [
            Embedding(
                input_dim=10000,
                output_dim=150,
                input_length=400),
            Convolution1D(
                filters=128,
                kernel_size=4,
                padding='same',
                activation='relu'),
                BatchNormalization(),
            MaxPooling1D(),
            Flatten(),
            Dropout(0.4),
            Dense(
                100,
                activation='relu'),
            Dropout(0.4),
            Dense(
                len(y_train[0]),
                activation='softmax')])

在编译模型时,我使用 Nadam 优化器categorical_crossentropy 损失和 LabelSmoothing 设置为 0.2 。

在模型拟合中,我使用 30 个时期批量大小 设置为 512.我还使用 EarlyStopping 来监控 val_loss 并将耐心设置为 8 个时期。测试大小设置为数据集的 25%。

实际上训练在 16/18 个 epoch 后停止,值在 6/7 epoch 后开始稍微波动,然后继续直到被 EarlyStopping 停止。这些值平均如下:

损失:1.1673 - 精度:0.9674 - val_loss:1.2464 - val_accuracy:0.8964

测试准确率达到:

损失:1.2461 - 精度:0.8951

现在我想提高我的 CNN 的准确性,我尝试了不同的超参数,但就目前而言,我无法获得更高的值。因此我想弄清楚:

  1. 如果还有改进的余地(我敢打赌)
  2. 如果解决方案是微调我的超参数,如果是这样,我应该更改哪些?
  3. 如果通过向模型添加层来更深入可能有任何用处,如果是这样,如何改进我的模型
  4. 是否有任何其他 deep-learning/Neural 网络方法而不是 CNN 可以产生更好的结果?

非常感谢任何愿意提供帮助的人! :)

有很多库,但我发现这个非常灵活。 https://github.com/keras-team/keras-tuner

用pip安装即可。

您更新的模型,请随意选择搜索范围。

from tensorflow import keras
from tensorflow.keras import layers
from kerastuner.tuners import RandomSearch


def build_model(hp):
    model = keras.Sequential()
    model.add(layers.Embedding(input_dim=hp.Int('input_dim',
                                        min_value=5000,
                                        max_value=10000,
                                        step = 1000),
                              output_dim=hp.Int('output_dim',
                                        min_value=200,
                                        max_value=800,
                                        step = 100),
                              input_length = 400))
    model.add(layers.Convolution1D(
                filters=hp.Int('filters',
                                        min_value=32,
                                        max_value=512,
                                        step = 32),
                kernel_size=hp.Int('kernel_size',
                                        min_value=3,
                                        max_value=11,
                                        step = 2),
                padding='same',
                activation='relu')),
    model.add(layers.BatchNormalization())
    model.add(layers.MaxPooling1D())
    model.add(layers.Flatten())
    model.add(layers.Dropout(0.4))
    model.add(layers.Dense(units=hp.Int('units',
                                        min_value=64,
                                        max_value=256,
                                        step=32),
                           activation='relu'))
    model.add(layers.Dropout(0.4))
    model.add(layers.Dense(y_train[0], activation='softmax'))
    model.compile(
    optimizer=keras.optimizers.Adam(
        hp.Choice('learning_rate',
                  values=[1e-2, 1e-3, 1e-4])),
    loss='categorical_crossentropy',
    metrics=['accuracy'])
    return model


tuner = RandomSearch(
    build_model,
    objective='val_accuracy',
    max_trials=5,
    executions_per_trial=3,
    directory='my_dir',
    project_name='helloworld')
tuner.search_space_summary()

## The following lines are based on your model


tuner.search(x, y,
             epochs=5,
             validation_data=(val_x, val_y))

models = tuner.get_best_models(num_models=2)

您可以尝试将 Conv1D 层替换为 LSTM 层并观察是否获得更好的性能。

LSTM(units = 512) https://keras.io/layers/recurrent/

如果您想提取更有意义的特征,我发现一种很有前途的方法是提取预训练的 BERT 特征,然后使用 CNN/LSTM.

进行训练

这是一个很好的入门知识库 - https://github.com/UKPLab/sentence-transformers

一旦你从 BERT/XLNet 中得到句子嵌入,你就可以使用这些特征来训练另一个与你正在使用的 CNN 相似的 CNN,除了可能会去掉嵌入层,因为它很昂贵。