3

如何将职位描述分类到各自的行业?

我正在尝试使用 LSTM 对文本进行分类,特别是将职位描述转换为行业类别,不幸的是,到目前为止我尝试过的事情只产生了 76% 的准确率。

使用 LSTM 对 30 多个类别的文本进行分类的有效方法是什么?

我尝试了三种选择

型号_1

Model_1 的测试准确率达到 65%

  • 嵌入维度 = 80

  • 最大序列长度 = 3000

  • 纪元 = 50

  • 批量大小 = 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'])

用于多类分类的 LSTM 架构

图像表示模型_1的测试列车损失图


型号_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'])

图片代表Model_2的LSTM架构

模型_2的Test-Train损失图


型号_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'])

图片代表model_3的LSTM架构

我想知道如何提高网络的准确性。

4

1 回答 1

2

从最小的基线开始

您的代码顶部有一个简单的网络,但请尝试将其作为您的基线

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)
于 2020-11-26T06:20:45.560 回答