文本分类问题

Posted

技术标签:

【中文标题】文本分类问题【英文标题】:Text classification issue 【发布时间】:2019-09-27 07:50:32 【问题描述】:

我是 ML 的新手,我尝试将文本分为两类。我的数据集是用医学文本中的 Tokenizer 制作的,它是不平衡的,有 572 条记录用于训练,471 条用于测试。

我真的很难制作具有不同预测输出的模型,几乎所有值都相同。我已经厌倦了使用 this 等示例中的模型并自己调整参数,但输出总是没有意义

这里是标记化和准备的data

这里是脚本:Gist

我使用的示例模型

    sequential_model = keras.Sequential([
        layers.Dense(15, activation='tanh',input_dim=vocab_size),
        layers.BatchNormalization(),
        layers.Dense(8, activation='relu'),
        layers.BatchNormalization(),
        layers.Dense(1, activation='sigmoid')
    ])

    sequential_model.summary()
    sequential_model.compile(optimizer='adam',
                             loss='binary_crossentropy',
                             metrics=['acc'])

    train_history = sequential_model.fit(train_data,
                                         train_labels,
                                         epochs=15,
                                         batch_size=16,
                                         validation_data=(test_data, test_labels),
                                         class_weight=1: 1, 0: 0.2,
                                         verbose=1)

很遗憾,我无法共享数据集。 我也厌倦了将 keras.utils.to_categorical 与类标签一起使用,但它没有帮助

【问题讨论】:

嗨雅罗斯拉夫,你到底有什么问题?我运行了你的代码,你已经获得了 82-84% 的不错的验证/训练准确率。您的损失曲线是有道理的,因为我们看到网络过度拟合训练集,而我们看到通常的碗形验证曲线。为了让你的网络表现更好,你总是可以加深它(更多的层),加宽它(每个隐藏层更多的单元)和/或为你的层添加更多的非线性激活函数,以便能够映射到更广泛的值。例如,我将第 2 层的激活更改为 sigmoid,并且看到准确度提高了 2-3% @SachinRaghavendran 准确度很高,但如果您看一下预测输出,您会发现所有记录都归为一类。我认为这是因为数据集中有更多标签“0”的样本。我试图调整层数和参数,但预测结果总是在一个数字左右,偏差很小。这是您更改后的输出: [[0.421591] [0.395864] [0.395864] [0.421591] [0.395864] [0.395864] ... ] 这些是火车标签: [0 1 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 ... ] 不幸的是,没有意义,即使它是火车数据 你说的输出是“[[0.421591] [0.395864] [0.395864] [0.421591] [0.395864] [0.395864] ... ]”;这是 sigmoid 层的预期结果。 sigmoid 激活函数会将前向传递的所有输出值压缩到 0 和 1 之间(这就是你看到废话的原因)。现在,当生成标签时,如果输出低于 0.5,则模型将分类为 0,而上述 0.5 将分类为 1(根据我查看源代码,这是在 model.evaluate 中处理的)。 另外,我相信你最初得到这么多重复值的原因是由于你的网络规模。显然,每个数据点大约有 20,000 个特征(相当大的特征空间);您的网络规模太小,因此可以映射到的输出值的可能空间更小。我对一些较大的隐藏单元层进行了一些测试(并增加了层数),并且能够看到预测值确实有所不同:[0.519]、[0.41]、[0.37]...(这些将被映射基于上述注释的二进制值) 您的网络性能变化也是可以理解的,因为您拥有的特征数量大约是训练规模的 50 倍(通常您希望比例更小)。请记住,对于如此小的训练和测试数据集进行太多 epoch(例如超过 10 个)的训练以查看损失的改进并不是很好的做法,因为您可能会严重过度拟合,并且可能表明您的网络需要更宽/更深. 【参考方案1】:

您的损失曲线是有道理的,因为我们看到了网络对训练集的过度拟合,而我们看到了通常的碗形验证曲线。

为了使您的网络表现更好,您可以随时加深它(更多层)、加宽它(每个隐藏层更多单元)和/或为您的层添加更多非线性激活函数,以便能够映射到更广泛的价值观。

另外,我认为您最初获得如此多重复值的原因是由于您的网络规模。显然,每个数据点大约有 20,000 个特征(相当大的特征空间);您的网络规模太小,因此可以映射到的输出值的可能空间更小。我对一些较大的隐藏单元层进行了一些测试(并增加了层数),并且能够看到预测值确实有所不同:[0.519]、[0.41]、[0.37]...

您的网络性能变化也是可以理解的,因为您拥有的特征数量大约是训练规模的 50 倍(通常您希望比例更小)。请记住,对于如此小的训练和测试数据集进行太多 epoch(例如超过 10 个)的训练以查看损失的改进并不是很好的做法,因为您可能会严重过度拟合,并且可能表明您的网络需要更宽/更深.

所有这些因素,例如层大小、隐藏单元大小甚至 epoch 数都可以视为超参数。换句话说,保留一定百分比的训练数据作为验证拆分的一部分,逐一检查每个类别的因素并进行优化以获得最高的验证准确度。公平地说,你的训练集不是太高,但我相信你应该保留大约 10-20% 的训练作为一种验证集来调整这些超参数,因为每个数据点都有如此大量的特征.在此过程结束时,您应该能够确定您的真实测试准确性。这就是我将如何优化以获得该网络的最佳性能。希望这可以帮助。

More about training, test, val split

【讨论】:

以上是关于文本分类问题的主要内容,如果未能解决你的问题,请参考以下文章

NLP之文本分类

文本分类与句子分类[重复]

中文文本分类大概的步骤

论述性文本分类

文本分类/分类算法[关闭]

CNN文本分类