Вопрос или проблема
Я пытаюсь обучить свою дискриминаторную сеть, используя Keras с задним планом TensorFlow. Сеть предназначена для классификации входных данных на один из 9 выходных меток. Я передаю 2D вход (высота, ширина, без каналов) и вектор one-hot для вывода. Я смог обучить сеть независимо, используя fit(). Однако теперь, когда я перешел на train_on_batch, она выдает ошибку, упомянутую выше.
Вот мой код дискриминатора:
def build_discriminator(time_steps, feature_size, input_spectrogram=None):
spectrogram = Input(shape=(time_steps, feature_size))
# spectrogram = tf.placeholder(tf.float32, shape=(None, time_steps, feature_size))
layer0 = Reshape((time_steps, feature_size, 1))(spectrogram)
layer1 = Conv2D(32, kernel_size=(3,3), padding='same')(layer0)
#model.add(LeakyReLU(alpha=0.01))
layer2 = MaxPooling2D(pool_size=(4,4))(layer1)
layer3 = Conv2D(16, kernel_size=(3,3), padding='same')(layer2)
#model.add(LeakyReLU(alpha=0.05))
layer4 = MaxPooling2D(pool_size=(4,4))(layer3)
layer5 = Conv2D(16, kernel_size=(3,3), padding='same')(layer4)
#model.add(LeakyReLU(alpha=0.05))
layer6 = MaxPooling2D(pool_size=(4,4))(layer5)
layer7 = Flatten()(layer6)
layer8 = Dense(16)(layer7)
prediction = Dense(9, activation = 'softmax')(layer8)
# prediction = Dropout(0.1)(layer9)
model = Model(spectrogram, prediction)
opt = optimizers.Adam(lr=0.002, beta_1=0.5)
model.compile(loss="categorical_crossentropy", optimizer=opt, metrics=['accuracy'])
return model
Вот код, который обучает дискриминатор:
x_real = batch_x[:half_batch, :, :]
labels_real = batch_labels[:half_batch]
d_loss1, _ = discriminator.train_on_batch(x_real, to_categorical(labels_real, num_classes=9))
# генерируем 'фальшивые' примеры
x_fake, labels_fake = generate_fake_samples(batch_x[half_batch:, :, :], batch_labels[half_batch:], generator)
# обновляем веса модели дискриминатора
d_loss2, _ = discriminator.train_on_batch(x_fake, to_categorical(labels_fake, num_classes=9))
# обновляем генератор через ошибку дискриминатора
g_loss, acc = gan.train_on_batch([batch_x, batch_targets], to_categorical(batch_targets, num_classes=9))
Ошибка возникает на этой строке:
d_loss1, _ = discriminator.train_on_batch(x_real, to_categorical(labels_real, num_classes=9))
Трассировка ошибки:
File "gan.py", line 126, in train
d_loss1, _ = discriminator.train_on_batch(x_real, to_categorical(labels_real, num_classes=9))
File "/home/pallavi/anaconda3/lib/python3.7/site-packages/keras/engine/training.py", line 1513, in train_on_batch
self._make_train_function()
File "/home/pallavi/anaconda3/lib/python3.7/site-packages/keras/engine/training.py", line 316, in _make_train_function
loss=self.total_loss)
File "/home/pallavi/anaconda3/lib/python3.7/site-packages/keras/legacy/interfaces.py", line 91, in wrapper
return func(*args, **kwargs)
File "/home/pallavi/anaconda3/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py", line 75, in symbolic_fn_wrapper
return func(*args, **kwargs)
File "/home/pallavi/anaconda3/lib/python3.7/site-packages/keras/optimizers.py", line 504, in get_updates
grads = self.get_gradients(loss, params)
File "/home/pallavi/anaconda3/lib/python3.7/site-packages/keras/optimizers.py", line 93, in get_gradients
raise ValueError('An operation has `None` for gradient. '
ValueError: Операция имеет `None` для градиента. Пожалуйста, убедитесь, что все ваши операции имеют определенный градиент (т.е. являются дифференцируемыми). Обычные операции без градиента: K.argmax, K.round, K.eval.
Я использую TensorFlow-GPU 2.0.0 с Keras 2.3.1. Мог бы кто-нибудь помочь мне понять, где я ошибаюсь?
Возможно, вы неправильно строите свою модель.
Вот альтернативный способ построения модели:
from tensorflow.keras.models import Sequential
layers =[
spectrogram = Input(shape=(time_steps, feature_size))
layer0 = Reshape((time_steps, feature_size, 1))
layer1 = Conv2D(32, kernel_size=(3,3), padding='same')
layer2 = MaxPooling2D(pool_size=(4,4))
layer3 = Conv2D(16, kernel_size=(3,3), padding='same')
layer4 = MaxPooling2D(pool_size=(4,4))
layer5 = Conv2D(16, kernel_size=(3,3), padding='same')
layer6 = MaxPooling2D(pool_size=(4,4))
layer7 = Flatten()
layer8 = Dense(16)
]
model = Sequential(layers)
model.summary()
model.compile(loss="categorical_crossentropy", optimizer=optimizers.Adam(lr=0.002, beta_1=0.5), metrics=['accuracy'])
Ответ или решение
Ошибка: Операция имеет None
для градиента при использовании categorical_crossentropy
— это распространенная проблема, с которой могут столкнуться разработчики, работающие с Keras и TensorFlow, особенно при переходе от метода обучения с использованием fit()
к train_on_batch()
. Давайте подробно разберемся в этой проблеме.
Причины возникновения ошибки
Ошибка "An operation has None
for gradient" возникает, когда Keras не может вычислить градиенты для одной или нескольких операций в вашей модели. Это может произойти по нескольким причинам:
-
Неподдерживаемые операции: Некоторые операции, такие как
K.argmax
,K.round
иK.eval
, не имеют определенного градиента и не могут быть использованы в процессе обратного распространения. -
Необходимые данные: Убедитесь, что на вход модели подаются данные нужной формы. В вашем случае это 2D-выходы (однородные векторы) с использованием функции
to_categorical
. Если данные имеют неправильный размер или формат, это может вызвать проблемы с градиентами. -
Проблемы с совместимостью версий: Используемые версии TensorFlow и Keras могут не полностью поддерживать некоторые функции друг друга. Убедитесь, что используемые вами версии совместимы и обновлены до последних стабильных.
Проверка и решения
Давайте рассмотрим несколько шагов, которые могут помочь вам устранить проблемы, возникшие с вашей моделью:
-
Проверьте форму данных: Убедитесь, что данные
x_real
соответствуют ожидаемым размерностям входного слоя модели. Для вашей модели ожидается, что формаx_real
будет(batch_size, time_steps, feature_size)
, а форма меток будет(batch_size, num_classes)
. -
Отладка потерь: Попробуйте временно заменить функцию потерь на другую, например
sparse_categorical_crossentropy
, если ваши метки не были преобразованы в категориальные векторы, а представлены в виде целых чисел. Это позволило бы избежать проблем с корректностью данных, передаваемых в функцию потерь. -
Структура модели: Убедитесь, что ваша модель построена правильно. Вы можете перепроверить архитектуру модели, убедившись, что она будет правильно обрабатывать входные данные.
Пример создания модели аналогично вашей, но с использованием подхода Sequential
:
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Input, Reshape, Conv2D, MaxPooling2D, Flatten, Dense
from tensorflow.keras import optimizers
def build_discriminator(time_steps, feature_size):
model = Sequential()
model.add(Input(shape=(time_steps, feature_size)))
model.add(Reshape((time_steps, feature_size, 1)))
model.add(Conv2D(32, kernel_size=(3, 3), padding='same'))
model.add(MaxPooling2D(pool_size=(4, 4)))
model.add(Conv2D(16, kernel_size=(3, 3), padding='same'))
model.add(MaxPooling2D(pool_size=(4, 4)))
model.add(Conv2D(16, kernel_size=(3, 3), padding='same'))
model.add(MaxPooling2D(pool_size=(4, 4)))
model.add(Flatten())
model.add(Dense(16))
model.add(Dense(9, activation='softmax'))
opt = optimizers.Adam(lr=0.002, beta_1=0.5)
model.compile(loss="categorical_crossentropy", optimizer=opt, metrics=['accuracy'])
return model
Заключение
Если ни один из предложенных шагов не устраняет проблему, попробуйте проводить более детальную диагностику, добавляя отладочные сообщения или используя инструменты профилирования TensorFlow для отслеживания градиентов. Если ошибка продолжает возникать, рассмотрите возможность публикации вопроса на специализированных платформах с подробным описанием вашего кода и ошибок. Это поможет вам получить более точные советы и рекомендации.