Как вы тренируете модель Keras с единичным выводом, чья форма y_pred не соответствует форме y_true? - PullRequest
1 голос
/ 28 апреля 2020

Рассмотрим простую сеть Keras, подобную этой:

def custom_loss(y_true,y_pred):
    return K.abs(y_true[0]-y_pred)+K.abs(y_true[1]-y_pred)

def gen():
    while True:
        a = np.random.random()
        b = 2*a
        c = 3*a
        yield (np.array([a]),np.array([b,c]))

model = Sequential()
model.add(Dense(1,input_dim=1))

model.compile(Adam(lr= 0.01),custom_loss)

model.fit_generator(gen(),steps_per_epoch=20)

В этом случае предполагается научиться прогнозировать среднее между двойным и тройным значением входного сигнала. y_true имеет форму [1], а y_pred имеет форму [2]. Поэтому keras выдает ошибку: «Входные массивы должны иметь то же количество выборок, что и целевые массивы. Найдено 1 входных образцов и 2 целевых образца. ' Хотя это сделано специально, как вы можете избежать большей цели, чем входной массив, если у вас есть несколько целей?

1 Ответ

2 голосов
/ 28 апреля 2020

Итак, я вижу, что в вашем генераторе у вас один дим-вход и 2-дим-выход.

В вашей функции потерь вы индексируете неверным образом. Первый индекс обычно представляет собой индекс пакета, поэтому вам нужно указать, что вы пытаетесь рассчитать потери по всем пакетам.

Правильная реализация потерь будет выглядеть следующим образом:

return K.abs(y_true[:,:]-y_pred[:,0])+K.abs(y_true[:,:]-y_pred[:,1])

Я полагаю, вы получили ошибку из-за неправильной индексации, если это то, что вы имели в виду, то это решит проблему.

Наконец, количество выходов определяется единицами в последний слой. [Посмотрите на сводку вашей модели, вы увидите, что последний слой имеет форму (None,1), но вам нужно (None, 2) там, поскольку у вас есть 2 выхода] Вы можете посмотреть сводку модели, вы передаете два значения b, c в вашем генераторе, но ваша модель имеет один выход (1 единица в конечном плотном слое). Чтобы исправить это, достаточно просто изменить единицы измерения в Dense (2).

from tensorflow.keras.layers import Input, Dense, Add, Activation, Flatten
from tensorflow.keras.models import Model, Sequential
import tensorflow as K

def custom_loss(y_true,y_pred):
    print(y_true.shape)
    print(y_pred.shape)
    return K.abs(y_true[:,:]-y_pred[:,0])+K.abs(y_true[:,:]-y_pred[:,1])
    return K.keras.losses.mse(y_true, y_pred) # this one works

def gen():
    while True:
        a = np.random.random()
        b = 2*a
        c = 3*a
        yield (np.array([a]),np.array([b,c]))

model = Sequential()
model.add(Dense(2,input_dim=1))

model.compile('adam',custom_loss)

model.summary()

model.fit_generator(gen(),steps_per_epoch=20)
Model: "sequential_17"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_17 (Dense)             (None, 2)                 4         
=================================================================
Total params: 4
Trainable params: 4
Non-trainable params: 0
_________________________________________________________________
(None, 1)
(None, 2)
(None, 1)
(None, 2)
20/20 [==============================] - 0s 2ms/step - loss: 2.8827

<tensorflow.python.keras.callbacks.History at 0x7f48e64f1d68>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...