如何使用 lstm 执行多类多输出分类
Posted
技术标签:
【中文标题】如何使用 lstm 执行多类多输出分类【英文标题】:How to perform multiclass multioutput classification using lstm 【发布时间】:2020-09-16 12:15:00 【问题描述】:我有multiclass multioutput classification
(详情请参阅https://scikit-learn.org/stable/modules/multiclass.html)。换句话说,我的数据集如下所示。
node_name, timeseries_1, timeseries_2, label_1, label_2
node1, [1.2, ...], [1.8, ...], 0, 2
node2, [1.0, ...], [1.1, ...], 1, 1
node3, [1.9, ...], [1.2, ...], 0, 3
...
...
...
所以,我的label_1
可以是0
或1
,而我的label_2
可以是0
、1
或2
。
我目前的代码如下。
def create_network():
model = Sequential()
model.add(LSTM(200, input_shape=(16,2)))
model.add(Dense(100))
model.add(Dropout(0.2))
model.add(Dense(3, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
neural_network = KerasClassifier(build_fn=create_network, epochs=100, batch_size=100, verbose=0)
k_fold = StratifiedKFold(n_splits=10, shuffle=True, random_state=0)
scores = cross_validate(neural_network, my_features, label_data_encoded, cv=k_fold, scoring = ('accuracy', 'precision_weighted', 'recall_weighted', 'f1_weighted', 'roc_auc'))
我的问题如下。
由于我有两个标签(即label_1
和label_2
),如何将这些标签适合lstm 模型?我必须做keras.utils.to_categorical(label_1, 2)
和keras.utils.to_categorical(label_2, 3)
之类的事情吗?
如何更改模型以使其适合multiclass multioutput classification
?
如果需要,我很乐意提供更多详细信息。
【问题讨论】:
【参考方案1】:如果我理解正确的话,label_1 是二元的,而 label_2 是多类问题,所以我们需要模型有两个具有不同损失函数的输出;分别是二元交叉熵和分类交叉熵。
但是,Sequential API 不允许多个输入/输出。
Sequential API 允许您为大多数问题逐层创建模型。它的局限性在于它不允许您创建共享层或具有多个输入或输出的模型。
您可以使用函数式 API 创建两个输出层,并使用所需的损失函数编译模型。
X=Input(input_shape)
X=Layer(X)
'
'
'
'
out1=Dense(1, activation='sigmoid')(X)
out2=Dense(3, activation='softmax')(X)
model = Model(inputs = input, outputs = [out1,out2])
model.compile(loss = ['binary_crossentropy','categorical_crossentropy'], loss_weights = [l1,l2], ...)
model.fit(input,[label_1, label_2_toCategotical]
网络将最小化的损失将是 2 个损失的加权和,由 l1 和 l2 加权。
希望这会有所帮助:)
【讨论】:
非常感谢您的出色回答。这正是我一直在寻找的。但是,我还有一个问题。由于kerasclassifier
不支持函数式API,我们如何使用您的方法执行10 倍分层交叉验证。如果您有代码/或知道如何编码,请告诉我。期待您的回音。谢谢你:)
哦,好吧,我不确定我是否有一个优雅的解决方案,但您可以使用 sklearn StratifiedKFold 生成拆分,然后手动循环遍历拆分。
谢谢。如果您有 sklearn StratifiedKFold 手动循环,请发布代码。如果没有,我会在其他 SO 问题中检查它:)
更正了 label_2 的形状。 Label_1 是二进制的并且仍然如此,因此不需要任何转换。关于l1
和l2
权重,我相信将它们视为另一个超参数是公平的。因此,您可以先将两者都设置为 1,然后在其中一个输出表现太差时尝试调整。抱歉,我手头上找不到 StratifiedKFold 的代码,您可以查看官方 sklearn 文档,或者确实是其他答案! :)
对于label_1,假设阈值为0.5,预测类为1,您可以调整该阈值。 label_2 预测 class=2,请注意,它是一个 softmax 激活,因此它会将最大概率分配给其中一个类。【参考方案2】:
这是一个有点复杂的问题,因为用于多类多输出的 Scikit-Learn API 和 Keras API 不直接兼容。此外,TensorFlow v1 和 v2 处理事物的方式甚至存在差异。现有的 Keras 包装器不适用于更复杂的情况。
我创建了一个KerasClassifier
的扩展,它能够处理这些情况,包和文档是here (GitHub)。全面披露:我是包的创建者,但我没有经济利益,它是开源的。
使用这些扩展版本,您可以轻松处理多类多输出问题。我认为对于您的情况,它应该开箱即用,但如果不是,您可以从 KerasClassifier
继承并覆盖 target_encoder
以从 Scikit-Learn 数据格式转换为您的 Keras 模型使用的任何格式。更多详情here (docs).
希望这会有所帮助!
【讨论】:
以上是关于如何使用 lstm 执行多类多输出分类的主要内容,如果未能解决你的问题,请参考以下文章
具有分类和连续属性的多类多输出分类,无需在 python 中编码 [关闭]
如何使用 keras 堆叠 LSTM 模型正确塑造多类分类的输入
Python Sklearn“ValueError:分类指标无法处理多类多输出和二进制目标的混合”错误