【问题标题】:Keras Single Input Multiple Outputs - why losses are so high comparing with Single Output?Keras 单输入多输出 - 为什么与单输出相比损耗如此之高?
【发布时间】:2021-01-26 18:17:33
【问题描述】:

我认为我的 Keras 多输出编码有问题,与 Sequential 模型相比,这会导致高损失。请帮我看看哪里错了。

import os, random, string, pandas, math, numpy
import tensorflow as tf
from tensorflow import keras

训练数据:

feature_data = [] # common feature data
label_data = [] # for multiple outputs
single_data = [] # for single output
size = 10000
features = ['x1', 'x2']
labels = ['y1', 'y2']
for i in range(size):
    a = random.random()
    b = random.random()
    c = math.sin(a)
    d = math.cos(b)
    feature = [a, b]
    label = [c, d]
    feature_data.append(feature)
    label_data.append(label)
    single_data.append(c)

这是我的单输出模型,效果很好:loss

single = keras.Sequential([
    keras.layers.Dense(2, input_shape=(2,), activation=tf.nn.softmax),
    keras.layers.Dense(4, activation=tf.nn.softmax),
    keras.layers.Dense(1)])
optimizer = tf.optimizers.RMSprop(learning_rate=0.001)
single.compile(loss='mse', optimizer=optimizer, metrics=['mae'])
single.fit(x=feature_data, y=single_data, epochs=100, batch_size=100)

这应该是相同的多输出模型,但是损失真的很高:0.1

def build_model():
    input_shape=(2, )
    inputs = keras.Input(shape=input_shape)
    outputs = []
    for label in labels:
        u = keras.layers.Dense(2, input_shape=input_shape, activation=tf.nn.softmax)(inputs)
        v = keras.layers.Dense(4, activation=tf.nn.softmax)(u)
        w = keras.layers.Dense(1, name=label)(v)
        outputs.append(w)
    model = keras.Model(inputs = inputs, outputs = outputs)
    optimizer = tf.optimizers.RMSprop(learning_rate=0.001)
    model.compile(loss='mse', optimizer=optimizer, metrics=['mae'])
    return model

model = build_model()
model.fit(x=feature_data, y=label_data, epochs=100, batch_size=100)

我猜输入层或标签数据格式有问题,但仍然不知道如何修复它。请帮忙。

【问题讨论】:

    标签: keras multipleoutputs


    【解决方案1】:

    我没注意。

    Softmax 用于从几个可能的输出中选择一个。您正在执行连续级别输出,而不是 one-hot 编码。

    我认为,如果您在正确的 Dense 层选择正确的激活函数,您的第二个模型应该可以工作。

    查看您的数据,您正在预测 (0->1) 的 sin 和 (0->1) 的 cos。从图表中可以看出,这些都是在 sin & cos 范围内的非常平坦的线。这是一个如此小的模型,可能任何或所有 Dense 层上的 tanh 或 sigmoid 都可以完成这项工作。

    【讨论】:

    • 对不起,我的错,我没有澄清输入只是为了演示,我面临的问题是,如果一个模型只有一个数值输出,丢失率会很好而且很低,但是如果我像这样加入多个模型,损失率会很疯狂。我只是想弄清楚如何以正确的方式加入共享相同输入的模型。
    • 我尝试了几种方法,在最后的 Dense 层中使用“swish”(并且在任何地方都没有其他激活函数)对我有用。 “swish”是“relu”的变体。它是 Keras 内置的。
    【解决方案2】:

    [忽略这个] 第二个模型与第一个模型不同:它在开始时使用了不同的 Dense 层。

    这个结构匹配第一个模型:

    def build_model():
        input_shape=(2, )
        inputs = keras.Input(shape=input_shape)
        outputs = []
        d = keras.layers.Dense(2, input_shape=input_shape, activation=tf.nn.softmax)
        for label in labels:
            u = d(inputs)
            v = keras.layers.Dense(4, activation=tf.nn.softmax)(u)
            w = keras.layers.Dense(1, name=label)(v)
            outputs.append(w)
        model = keras.Model(inputs = inputs, outputs = outputs)
        optimizer = tf.optimizers.RMSprop(learning_rate=0.001)
        model.compile(loss='mse', optimizer=optimizer, metrics=['mae'])
        return model
    

    该结构与第一个模型匹配,因为它使用相同的密集层(完全相同的权重)来解释两条链中的输入。

    尝试绘制第二个网络的损失历史。您可能会看到双重振荡值:一个变好,另一个变坏,然后他们交换位置。

    【讨论】:

    • 感谢您的回答!不过,变化不大。我觉得输出层有问题,我感到困惑,最初的想法是reshape每个输出元素并通过标签与训练标签匹配,但老实说,我不知道该怎么做:-(
    猜你喜欢
    • 2020-03-09
    • 2016-09-16
    • 2013-11-04
    • 1970-01-01
    • 2018-09-14
    • 2018-04-08
    • 1970-01-01
    • 1970-01-01
    • 2017-03-01
    相关资源
    最近更新 更多