Необходимо создать модель, которая получает изображение постера фильма и возвращает возрастной рейтинг (многоклассовая классификация) и список жанров (классификация по нескольким меткам).
Код модели:
class NNetwork(Model):
def __init__(self, rating: int, genres: int):
super(NNetwork, self).__init__()
self.rescaling = Rescaling(1.0 / 255.0)
self.convolution = [
Conv2D(16, 3, padding='same', activation='relu'),
Conv2D(32, 3, padding='same', activation='relu'),
Conv2D(64, 3, padding='same', activation='relu')
]
self.pooling = [
MaxPooling2D(),
MaxPooling2D(),
MaxPooling2D()
]
self.flatten = Flatten()
self.dense = [
Dense(128, activation='relu'),
Dense(rating, activation='softmax'),
Dense(genres, activation='softmax')
]
def call(self, images: Tensor, training=None, **kwargs) -> tuple[Tensor, Tensor]:
x = self.rescaling(images)
for i in range(3):
x = self.convolution[i](x)
x = self.pooling[i](x)
x = self.flatten(x)
x = self.dense[0](x)
rating = self.dense[1](x)
genres = self.dense[2](x)
return rating, genres
Код функции потерь:
def loss(true: Tensor,
predict: Tensor) -> Tensor:
categorical = CategoricalCrossentropy(
reduction=None
)
loss = tf.reduce_mean(categorical(
y_true=true,
y_pred=predict
))
return loss
Код цикла обучения:
@tf.function
def train_step(images_batch, rating_batch, genres_batch):
with tf.GradientTape() as tape:
rating_predict, genres_predict = model(images_batch)
rating_loss = loss(rating_batch, rating_predict)
genres_loss = loss(genres_batch, genres_predict)
gradients = tape.gradient([rating_loss, genres_loss], model.trainable_variables)
optimizer.apply_gradients(zip(gradients, model.trainable_variables))
rating_score.update_state(rating_batch, rating_predict)
genres_score.update_state(genres_batch, genres_predict)
return rating_loss, genres_loss
Код основного цикла:
for n in range(EPOCHS):
total_loss = 0
total_rating_loss = 0
total_genres_loss = 0
for inputs, outputs in train:
images_batch = inputs['image']
rating_batch = outputs['rating']
genres_batch = outputs['genres']
rating_loss, genres_loss = train_step(images_batch, rating_batch, genres_batch)
total_loss += (rating_loss + genres_loss)
total_rating_loss += rating_loss
total_genres_loss += genres_loss
print(f'EPOCHS: {n} - total_loss: {total_loss.numpy()}, total_rating_loss: {total_rating_loss.numpy()}, total_genres_loss: {total_genres_loss.numpy()}')
Процесс обучения запускается, но функция потерь на каждой эпохе огромная, 10 в 15 степени. Значит алгоритм обучения составлен неверно.
Я предполагаю в чем может быть проблема:
1. Неверно выбрана или оформлена функция потерь.
2. Неверно вычисляются и применяются градиенты.
В чем может быть еще причина такой большой функции потерь?