使用 keras 进行文档分类 - 数字的分层序列
Posted
技术标签:
【中文标题】使用 keras 进行文档分类 - 数字的分层序列【英文标题】:document classification using keras - hierarchical sequence of digits 【发布时间】:2019-05-20 00:59:03 【问题描述】:我目前正在处理以下情况的分类问题:
标签的长度总是 5 位,例如:
99923 this is sample document one
56743 this is sample document two
...
第一个数字代表某个类别,后面的每个数字代表一个子类别,依此类推。
目前我正在使用具有以下设置的 Keras:
model = Sequential()
model.add(Dense(512, input_shape=(vocab_size,)))
model.add(Activation('relu'))
model.add(Dropout(0.3))
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.3))
model.add(Dense(num_labels))
model.add(Activation('softmax'))
model.summary()
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
由于我的训练数据有限(总共大约 8 万个样本),我决定只使用第一个数字来估计主类别,我得到了相当不错的结果,准确率约为 90%,无需任何预处理.
5 - this is sample of maincategory 5
9 - this is sample of maincategory 9
...
现在我想进一步接近一个级别,并使用两位数来预测主类别和第一个子类别。这给我带来了一个问题,例如,通常没有一个样本。 “12”的组合。
51 - this is sample of maincategory 51
95 - this is sample of maincategory 95
...
我告诉 Keras 只使用包含至少 1 个样本的标签(知道这是废话),并获得了大约 40 个标签,总体准确率为 85%,考虑到我已经丢失了很多,这似乎相当不错样本。
我的问题是:
这种预测可以更容易/更有效地完成吗?如果我让我的“两位数”模型从未经训练的类别中预测出一个看不见的样本,我会遇到将样本拟合到错误类别中的问题......
我可以使用 Keras 解决这个预测问题吗?
【问题讨论】:
您是否尝试过为每个类别级别使用一个 softmax 层,即一层预测类别,另一层预测子类别,等等? 因为我不知道如何实现这一点 - 不,但这似乎是个好主意。我尝试实现以下目标:如果我知道我的主类别是 9,则必须根据该类别进行下一个预测,因此:基于 mc 9,这是可能的子类别。关于代码级别的任何想法?提前致谢! @今天 【参考方案1】:好吧,正如我在 cmets 部分中提到的,我想到的一个想法是为层次结构中的每个类别级别使用一个 softmax 层。例如,对于三个分类级别,我们有三个分类器层:
from keras.models import Model
inp = Input(shape=(vocab_size,))
x = Dense(512, activation='relu', input_shape=(vocab_size,))(inp)
x = Dropout(0.3))(x)
x = Dense(128, activation='relu'))(x)
cat_1 = Dense(num_labels_cat1, activation='softmax')(x)
cat_2 = Dense(num_labels_cat2, activation='softmax')(x)
cat_3 = Dense(num_labels_cat3, activation='softmax')(x)
model = Model(inp, [cat_1, cat_2, cat_3])
就好像所有分类级别的信息都被编码在最后一个非分类层的输出中。因此,将其传递给专门的分类器层使模型能够提取有关相应分类级别的信息。
请注意,这可能有也可能没有良好的性能。你必须尝试找出答案。不过,仍有改进的余地。例如,您可以使用 Embedding
层并在模型中包含 Conv1D 或 LSTM 层。
如果您不熟悉 Keras 功能 API,您可能需要阅读 official guide。
【讨论】:
谢谢 - 我会尝试并回复反馈。 您好,我对您的解决方案有一些疑问。我已经阅读了 Keras 的指南——我绝对不是专家用户,但愿意学习。我可以从您的代码中得出您的总体想法 - 但是:您是否假设num_labels_cat1 = 10
因为可以出现从 0 到 9 的数字,而 num_labels_cat2 = 10
因为第一个子类别因此是相等的等等,或者是 num_labels_cat2 = 两位数字的每个组合?模型从哪些信息中理解数字的依赖关系?如果您能进一步解释一下,我会很高兴。我将在此处留下任何评估以供学习。
@JulianGerhard 好吧,一种思考方式是这样的:假设我们有 3 个类别,所以 num_labels_cat1=3
,类别 #1 有 4 个子类别,类别 #2 有 8 个子类别,类别#3 有 2 个子类别。我们可以将第一个子类别的标签数量设置为最大数量,即num_labels_cat2=8
。学习过程可能在最后一个非分类层的输出中编码所有分类信息。此外,您可以定义自定义损失函数来进一步惩罚错误分类(例如子类别正确,但类别不正确)。
@JulianGerhard 此外,请注意,在最简单的情况下,当您将损失函数设置为 categorical_crossentropy
时,每个输出层的损失值(例如,在上面的示例中,我们有 3 个输出层)将为加在一起,模型试图最小化这个总和,这对应于正确预测所有分类级别。但是,正如我在回答中提到的,您必须对网络进行适当的试验和调整(即调整层数、单元数、学习率的初始值、使用的层数、使用的优化器等),以了解这种方法是否工作与否。
嗨,最近几天我已经考虑过你的建议,并对你的方法进行了一些尝试。看起来网络似乎并没有摆脱它,但我想到了另一个想法——也许你对帽子有一个想法。如果执行以下操作怎么办:我训练了一个“主要”模型来预测第一个/主要类别(效果很好)。例如,我现在只跟踪 mc “9”。我现在只使用我为“9 + 子类别”拥有的训练数据并为每个可能的组合继续训练,为 9 之后的每个子类别训练一个模型【参考方案2】:
如果您的每个级别的标签都是相互关联的(甚至具有高度依赖性),那么以下方法可能有助于改进您的模型。
将第一级分类器输出的输出添加为下一级分类器的输入。
这有助于您的模型将较高级别的预测用于较低级别的分类。
【讨论】:
训练后如何实现? 因为我们要对序列模型使用预测,所以在测试过程中也应该是一样的 对不起,虽然我知道你的意思,但我目前不明白。您有解决方案的示例吗?以上是关于使用 keras 进行文档分类 - 数字的分层序列的主要内容,如果未能解决你的问题,请参考以下文章
在 keras 中使用 CNN-LSTM 模型进行序列到序列分类