Вопрос или проблема
Прямо сейчас у меня есть обучающий набор данных, который выглядит примерно так (Изображение, Число с плавающей запятой), где Изображение является независимой переменной, а число с плавающей запятой — зависимой переменной:
(Собака1, 3.8)
(Собака2, 0.2)
(Собака3, 2.3)
(Собака4, 4.1)
(Собака5, 1.8)
(Собака6, 5.2)
(Кот1, -1.01)
(Кот2, -1.12)
(Кот3, -0.93)
(Кот4, -0.98)
(Кот5, -0.95)
В данном случае, собаки в среднем имеют значение 2 со стандартным отклонением 3. А коты в среднем имеют значение -1 со стандартным отклонением 0.05.
Я пытаюсь научить свою нейронную сеть работать с этими данными. Где, после завершения обучения, она сможет принимать входное изображение и выдавать кортеж из чисел с плавающей запятой, представляющий среднее и стандартное отклонение того, чем, вероятно, является зависимая переменная. То есть, нейронная сеть, когда видит собаку, должна выводить (2, 3). А когда видит кота, должна выводить (-1, 0.05).
По сути, нейронная сеть должна получать изображение и определять как среднее значение, так и то, насколько сильно это значение может отличаться от среднего (выводя стандартное отклонение). Вероятность того, что число будет равно самому среднему, составляет 0%.
~
Я знаю, что обучая выходную переменную “среднее” на втором значении кортежа, нейронная сеть будет обучаться предсказывать среднее значение. Но моя основная проблема заключается в том, что я не совсем уверен, что использовать для обучения второго выхода нейронной сети, чтобы второй выход обучился стандартному отклонению (т.е. в некотором смысле, второй выход также является своего рода “коэффициентом доверия” к первому выходу).
Я нашел ответ здесь: https://medium.com/deeplearningmadeeasy/how-to-add-uncertainty-to-your-neural-network-afb5f855e66a
В частности, давайте скажем, что для данного (Изображение, Значение) ваша нейронная сеть выдает (Среднее, Стандартное отклонение). Вы хотите, чтобы ваша функция потерь была такой:
distr = normal.distribution(mean=Mean, stddev=Stddev);
loss = -distr.log_prob(Val);
Это означает, что нужно определить вероятность P того, что число Val или хуже встречается в распределении (Среднее, Стандартное отклонение). Поскольку потеря -log(P). Если P очень низкая, -log(P) будет высокой. Если P очень высокая, -log(P) будет низкой. Она будет обучаться делать вероятности точными.
Неясно, повредит ли это способности нейронной сети учить среднее значение, так как она больше не использует MSE для обучения среднего.
Ответ или решение
Для решения вашей задачи по обучению нейронной сети, которая должна предсказывать как среднее значение, так и стандартное отклонение для заданных изображений, вам необходимо правильно настроить архитектуру модели и функцию потерь. Вот пошаговая инструкция по реализации этого подхода.
1. Архитектура Нейронной Сети
Ваша нейронная сеть должна иметь два выходных слоя:
- Один слой для предсказания среднего значения (Mean).
- Второй слой для предсказания стандартного отклонения (Stddev).
Модель может быть реализована с помощью библиотек глубокого обучения, таких как TensorFlow или PyTorch. Вот примерный код для определения модели:
import tensorflow as tf
from tensorflow.keras import layers, models
# Определение модели
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(height, width, channels)))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
# Два выхода
model.add(layers.Dense(1, name='mean_output')) # Выход для среднего
model.add(layers.Dense(1, name='stddev_output')) # Выход для стандартного отклонения
model.compile(optimizer='adam', loss={'mean_output': 'mse', 'stddev_output': 'custom_loss'})
2. Функция Потерь
Вашей основной задачей будет создание пользовательской функции потерь, основанной на вероятностном подходе. Это позволит вашей модели обучаться как на предсказании среднего значения, так и на предсказании стандартного отклонения. Основная идея заключается в использовании нормального распределения, чтобы оценить вероятность наблюдаемого значения (Val).
import tensorflow_probability as tfp
def custom_loss(y_true, y_pred):
mean = y_pred[:, 0]
stddev = tf.math.exp(y_pred[:, 1]) # Используем экспоненту, чтобы гарантировать положительность
distr = tfp.distributions.Normal(loc=mean, scale=stddev)
loss = -distr.log_prob(y_true)
return tf.reduce_mean(loss)
3. Подготовка Данных
Убедитесь, что вы правильно подготовили свои данные. Изображения должны быть нормализованы, чтобы их размеры были совместимы с вашей моделью. Кроме того, ваши выходные значения (mean и stddev) должны быть подготовлены заранее.
4. Обучение Модели
После определения архитектуры и функции потерь, вы можете приступить к обучению модели:
# Обучение модели
history = model.fit(x_train, y_train, epochs=100, batch_size=32, validation_split=0.2)
Где x_train
— это массив изображений, а y_train
— это массив пар (mean, stddev).
5. Оценка Результатов
После обучения модели вы можете оценить её производительность, тестируя на новых изображениях и анализируя предсказания, сравнивая их с реальными значениями. Это даст вам представление о том, насколько точно ваша модель предсказывает и среднее значение, и стандартное отклонение.
Заключение
Подход, который вы описали, с использованием вероятностных распределений для оценки стандартного отклонения и функционала потерь, позволит нейронной сети эффективно учиться как предсказывать среднее значение, так и понимать неопределенность этого предсказания. Такой подход имеет множество применений, например, в задачах, где важно учитывать уровень неопределенности в предсказаниях.
Удачи в обучении вашей модели!