Keras 中的多个输出

问题描述 投票:0回答:3

我有一个问题,涉及在给定预测变量向量时预测两个输出。 假设预测向量看起来像

x1, y1, att1, att2, ..., attn
,这表示
x1, y1
是坐标,
att's 
是附加到
x1, y1
坐标出现的其他属性。基于这个预测器集,我想预测
x2, y2
。这是一个时间序列问题,我试图使用多重回归来解决。 我的问题是如何设置 keras,它可以在最后一层为我提供 2 个输出。

python tensorflow keras deep-learning neural-network
3个回答
64
投票
from keras.models import Model
from keras.layers import *    

#inp is a "tensor", that can be passed when calling other layers to produce an output 
inp = Input((10,)) #supposing you have ten numeric values as input 


#here, SomeLayer() is defining a layer, 
#and calling it with (inp) produces the output tensor x
x = SomeLayer(blablabla)(inp) 
x = SomeOtherLayer(blablabla)(x) #here, I just replace x, because this intermediate output is not interesting to keep


#here, I want to keep the two different outputs for defining the model
#notice that both left and right are called with the same input x, creating a fork
out1 = LeftSideLastLayer(balbalba)(x)    
out2 = RightSideLastLayer(banblabala)(x)


#here, you define which path you will follow in the graph you've drawn with layers
#notice the two outputs passed in a list, telling the model I want it to have two outputs.
model = Model(inp, [out1,out2])
model.compile(optimizer = ...., loss = ....) #loss can be one for both sides or a list with different loss functions for out1 and out2    

model.fit(inputData,[outputYLeft, outputYRight], epochs=..., batch_size=...)

23
投票

您可以使用

制作具有多个输出的模型
  1. 函数式API

  2. 通过子类化

    tf.keras.Model

这是使用功能 API 在 Iris 数据集上进行双输出(回归和分类)的示例:

from sklearn.datasets import load_iris
from tensorflow.keras.layers import Dense
from tensorflow.keras import Input, Model
import tensorflow as tf

data, target = load_iris(return_X_y=True)
X = data[:, (0, 1, 2)]
Y = data[:, 3]
Z = target

inputs = Input(shape=(3,), name='input')
x = Dense(16, activation='relu', name='16')(inputs)
x = Dense(32, activation='relu', name='32')(x)
output1 = Dense(1, name='cont_out')(x)
output2 = Dense(3, activation='softmax', name='cat_out')(x)

model = Model(inputs=inputs, outputs=[output1, output2])

model.compile(loss={'cont_out': 'mean_absolute_error', 
                    'cat_out': 'sparse_categorical_crossentropy'},
              optimizer='adam',
              metrics={'cat_out': tf.metrics.SparseCategoricalAccuracy(name='acc')})

history = model.fit(X, {'cont_out': Y, 'cat_out': Z}, epochs=10, batch_size=8)

这是一个简化版本:

from sklearn.datasets import load_iris
from tensorflow.keras.layers import Dense
from tensorflow.keras import Input, Model

data, target = load_iris(return_X_y=True)
X = data[:, (0, 1, 2)]
Y = data[:, 3]
Z = target

inputs = Input(shape=(3,))
x = Dense(16, activation='relu')(inputs)
x = Dense(32, activation='relu')(x)
output1 = Dense(1)(x)
output2 = Dense(3, activation='softmax')(x)

model = Model(inputs=inputs, outputs=[output1, output2])

model.compile(loss=['mae', 'sparse_categorical_crossentropy'], optimizer='adam')

history = model.fit(X, [Y, Z], epochs=10, batch_size=8)

这是同一个示例,子类化

tf.keras.Model
并使用自定义训练循环:

import tensorflow as tf
from tensorflow.keras.layers import Dense
from tensorflow.keras import Model
from sklearn.datasets import load_iris
tf.keras.backend.set_floatx('float64')
iris, target = load_iris(return_X_y=True)

X = iris[:, :3]
y = iris[:, 3]
z = target

ds = tf.data.Dataset.from_tensor_slices((X, y, z)).shuffle(150).batch(8)

class MyModel(Model):
    def __init__(self):
        super(MyModel, self).__init__()
        self.d0 = Dense(16, activation='relu')
        self.d1 = Dense(32, activation='relu')
        self.d2 = Dense(1)
        self.d3 = Dense(3, activation='softmax')

    def call(self, x, training=None, **kwargs):
        x = self.d0(x)
        x = self.d1(x)
        a = self.d2(x)
        b = self.d3(x)
        return a, b

model = MyModel()

loss_obj_reg = tf.keras.losses.MeanAbsoluteError()
loss_obj_cat = tf.keras.losses.SparseCategoricalCrossentropy()

optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3)

loss_reg = tf.keras.metrics.Mean(name='regression loss')
loss_cat = tf.keras.metrics.Mean(name='categorical loss')

error_reg = tf.keras.metrics.MeanAbsoluteError()
error_cat = tf.keras.metrics.SparseCategoricalAccuracy()

@tf.function
def train_step(inputs, y_reg, y_cat):
    with tf.GradientTape() as tape:
        pred_reg, pred_cat = model(inputs)
        reg_loss = loss_obj_reg(y_reg, pred_reg)
        cat_loss = loss_obj_cat(y_cat, pred_cat)

    gradients = tape.gradient([reg_loss, cat_loss], model.trainable_variables)
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))
    loss_reg(reg_loss)
    loss_cat(cat_loss)

    error_reg(y_reg, pred_reg)
    error_cat(y_cat, pred_cat)


for epoch in range(50):
    for xx, yy, zz in ds:
        train_step(xx, yy, zz)

    template = 'Epoch {:>2}, SCCE: {:>5.2f},' \
               ' MAE: {:>4.2f}, SAcc: {:>5.1%}'
    print(template.format(epoch+1,
                        loss_cat.result(),
                        error_reg.result(),
                        error_cat.result()))

    loss_reg.reset_states()
    loss_cat.reset_states()

    error_reg.reset_states()
    error_cat.reset_states()

0
投票

例如:

inputs = Input(shape=(128, 128, 1)) 

x = Conv2D(64, (3, 3), activation='relu', padding='same')(inputs)
x = MaxPooling2D((2, 2))(x)
x = Flatten()(x)
x = Dense(128, activation='relu')(x)

output_1 = Dense(4, activation='softmax', name='name_1')(x)
output_2 = Dense(4, activation='relu', name='name_2')(x) 

model = Model(inputs=inputs, outputs=[output_1, output_2])

model.compile(optimizer='adam',
              loss={'name_1': 'categorical_crossentropy', 'name_2': 'mse'},
              metrics={'name_1': 'categorical_accuracy', 'name_2': 'mse'})

以及如何安装:

history = model.fit(
    X_train,
    {'output_1': y_train_output_1, 'output_2': y_train_output_2},
    validation_data=(X_test, {'output_1': y_test_output_1, 'output_2': y_test_output_2}),
© www.soinside.com 2019 - 2024. All rights reserved.