Как правильно оформить функцию потерь в torch?

Есть нейронная сеть, на выходе 4 нейрона с активатором softmax. При обучении подаю батч на 100 примеров.
Если у меня есть готовые ответы, то обучение работает, но этот вариант не для меня. ))
В моём случае, я обрабатываю в отдельной функции ответы сети и получаю размер ошибки допустим 80%.
Как правильно оформить loss, чтобы на нём сработал backward и optimizer?
  • Вопрос задан
  • 127 просмотров
Решения вопроса 1
FerroPanda
@FerroPanda Автор вопроса
Сам разобрался.
В итоге всё сводится к тому, чтобы в своей какой-то функции обработать ответы сети, оценить их и самостоятельно высчитать ошибку. Потом взять любой ответ сети, на его основе создать свой правильный ответ, в сравнении с которым будет ошибка нужного нам размера, и потом это всё запихнуть в функцию потерь. Вся фишка в том, что к ответам сети привязаны графы их получения, т.е. в тензоре ответа сети есть вся последовательность как он получен. И на основании правильного ответа, ответа сети и этого графа, привязанного к ответу сети, выполняется обратное распространение ошибки. Нет графа - нет обучения. ))
Ещё один момент - если в сети используется какой-то не типовой не дифференцируемый слой, то штатная оптимизация тоже не будет работать, но при этом никаких ошибок не покажет.
В моём случае с выходной активацией softmax это оказалось не очень удачным вариантом, потому что допустим при ошибке 0,2 я не смог придумать как правильно создать целевой ответ.
Условный код как это работает:
optimizer.zero_grad()
answers = agent.forward(train_data)
#вычисляем ошибку на основе ответов сети в какой-то своей функции f(). 
#Получаем например 0,2 - типа ошибка 20%
nn_error = f(answers)
#берём первый из ответов сети, который содержит граф расчётов
nn_ans = answers[0]
#тут нам нужно создать правильный ответ - возможны вариант и нужно придумать правильно
#чтобы получить правильный можно как прибавить 20%, так и вычесть. Я прибавил.
target_ans = nn_ans * (1 + nn_error)
#функцию потерь можно сделать как свою, так и использовать штатную
f_loss = nn.L1Loss()
loss = f_loss(nn_ans, target_ans)
loss.backward()
optimizer.step()
#print(list(agent.parameters()))
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@rPman
Твоя обучающая выборка должна быть разделена на две части (максимально случайно/равномерно), бОльшая (на порядок или два) - обучающая, меньшая - тестовая. Обучение проходишь только на обучающей.

После каждого прохода или через несколько, сохраняешь функцию ошибки для обеих обучающих выборок, строишь графики и смотришь динамику, если скорость падения ошибки для обучающей выборки будет падать а вот для тестовой перестанет и даже начнет расти - это явный признак переобученности (как я знаю есть и другие способы детекта этого).

Это значит либо обучающая выборка недостаточна - т.е. нужно больше данных (100 это очень мало, что там за задача?) и данные должны лучше и равномернее описывать предметную область, либо структура/размер сети (внутренних слоев и их количество) неверное (в обе стороны) и нужны эксперименты с изменениями, смотреть динамику становится ли лучше если усложнять/упрощать сеть.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы