Python 如何使用lstm执行多类多输出分类

Python 如何使用lstm执行多类多输出分类,python,keras,scikit-learn,classification,lstm,Python,Keras,Scikit Learn,Classification,Lstm,我有多类多输出分类(有关详细信息,请参阅)。换句话说,我的数据集如下所示 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 ... ... ... def create_network(): model = S

我有
多类多输出分类
(有关详细信息,请参阅)。换句话说,我的数据集如下所示

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 
...
...
...
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
可以是
0
1
,而我的
label_2
可以是
0
1
2

我目前的代码如下

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 
...
...
...
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'))
我的问题如下

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 
...
...
...
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_category(label_1,2)
    keras.utils.to_category(label_2,3)
  • 如何更改模型以使其适用于
    多类多输出分类

如果需要,我很乐意提供更多细节。

如果我理解正确,标签1是二进制的,而标签2是一个多类问题,因此我们需要模型有两个输出,具有单独的损耗函数;二元交叉熵和分类交叉熵

但是,顺序API不允许多个输入/输出

顺序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加权


希望这有帮助:)

这是一个有点复杂的问题,因为用于多类多输出的Scikit Learn API和Keras API并不直接兼容。此外,TensorFlow v1和v2处理问题的方式甚至存在差异。现有的Keras包装器并不适用于更复杂的情况

我创建了一个扩展的
KerasClassifier
,它能够处理这些情况,包和文档是。完全披露:我是这个软件包的创建者,但我没有经济利益,它是开源的

使用这些扩展版本,您可以轻松处理多类多输出问题。我认为对于您的情况,它应该是开箱即用的,但如果不是这样,您可以从
KerasClassifier
继承并覆盖
target\u encoder
,从Scikit Learn数据格式转换为您的Keras模型使用的任何格式。更多细节


希望这有帮助

非常感谢你的回答。这正是我想要的。不过,我还有一个问题。既然
kerasclassifier
不支持功能API,我们如何使用您的方法执行10倍分层交叉验证。如果你有代码/或知道如何编码,请告诉我。期待您的来信。谢谢:)哦,不确定我是否有一个优雅的解决方案,但你可以使用sklearn StratifiedKFold生成拆分,然后手动循环拆分。谢谢。如果您有sklearn StratifiedKFold手动循环,请发布代码。如果没有,我将在其他SO问题中检查:)关于标签2的形状正确。标签_1是二进制的,保持不变,因此不需要任何转换。关于
l1
l2
权重,我认为将它们视为另一个超参数是公平的。因此,您可以先将两者都设置为1,然后尝试调整其中一个输出的性能是否太差。很抱歉,我手边找不到StratifiedKFold的代码,您可以查看官方的sklearn文档,或者另一个答案!)对于标签_1,假设阈值为0.5,则预测类为1,您可以调整阈值。标签_2预测类=2,请注意,它是一个softmax激活,因此将最大概率分配给其中一个类。