Я тренирую нейронную сеть (детали не важны), где целевые данные - это вектор углов (между 0 и 2 * пи). Я ищу совет о том, как кодировать эти данные. Вот что я сейчас пытаюсь (с ограниченным успехом):
1) Кодирование 1-в-C: я устанавливаю возможные углы в 1000 или около того дискретных углов, а затем указываю конкретный угол, помещая 1 в соответствующий индекс. Проблема в том, что сеть просто учится выводить все 0 (поскольку это почти точно правильно).
2) Простое масштабирование: я масштабировал выходной диапазон сети ([0,1]) до [0,2 * pi]. Проблема здесь в том, что углы, естественно, имеют круговую топологию (т. Е. 0,0001 и 2 * pi на самом деле находятся рядом друг с другом). При таком типе кодирования эта информация теряется.
Мы ценим любые предложения!
источник
Ответы:
Вступление
Я нахожу этот вопрос действительно интересным, я полагаю, что кто-то выпустил статью по нему, но это мой выходной, поэтому я не хочу гоняться за ссылками.
Таким образом, мы могли бы рассматривать это как представление / кодирование вывода, что я и делаю в этом ответе. Я продолжаю думать, что есть лучший способ, где вы можете просто использовать немного другую функцию потерь. (Возможно, сумма квадратов разностей, используя вычитание по модулю 2 ).π
Но далее с фактическим ответом.
метод
Я предлагаю представить угол в виде пары значений, его синуса и косинуса.θ
Таким образом, функция кодирования: а функция декодирования: Для arctan2, являющегося обратными касательными, сохраняя направление во всех квадрантах)θ ↦ ( грех( θ ) , cos( θ ) )
( у1, у2) ↦ арктан2 ( у1, у2)
Теоретически, вы можете эквивалентно работать напрямую с углами, если ваш инструмент поддерживает
atan2
функцию слоя (беря ровно 2 входа и получая 1 выход). TensorFlow делает это сейчас и поддерживает градиентный спуск , хотя и не предназначен для этого использования. Я исследовал использованиеout = atan2(sigmoid(ylogit), sigmoid(xlogit))
с функцией потерьmin((pred - out)^2, (pred - out - 2pi)^2)
. Я обнаружил, что он тренируется гораздо хуже, чемouts = tanh(ylogit), outc = tanh(xlogit))
с функцией потери0.5((sin(pred) - outs)^2 + (cos(pred) - outc)^2
. Что, я думаю, можно объяснить прерывистостью градиентаatan2
Мое тестирование здесь запускает его как функцию предварительной обработки
Чтобы оценить это, я определил задачу:
Я реализовал функцию случайного генерирования этих изображений со линиями под случайными углами (примечание: в более ранних версиях этого поста использовались случайные наклоны, а не случайные углы. Спасибо @Ari Herman за указание на это. Теперь это исправлено). Я построил несколько нейронных сетей, чтобы оценить эффективность выполнения задачи. Полная информация о реализации находится в этой записной книжке Jupyter . Код целиком на Юлии , и я использую библиотеку нейронных сетей Mocha .
Для сравнения я представляю его против альтернативных методов масштабирования до 0,1. и положить в 500 бункеров и использовать softmax. Я не особенно доволен последним, и чувствую, что мне нужно его настроить. Вот почему, в отличие от других, я тестирую его только на 1000 итераций, в отличие от двух других, которые были запущены на 1000 и на 10000
Экспериментальная установка
Изображения были пикселей, с линией, начинающейся в центре и идущей к краю. На изображении не было никаких шумов и т. Д., Только «черная» линия на белом фоне.101 × 101
Для каждого следа 1000 тренировок и 1000 тестовых изображений были сгенерированы случайным образом.
Оценочная сеть имела один скрытый слой шириной 500. В скрытом слое использовались сигмовидные нейроны.
Он обучался Stochastic Gradient Decent с фиксированной скоростью обучения 0,01 и фиксированным импульсом 0,9.
Регуляризация или отсев не использовались. Также не было никакого вида свертки и т. Д. Простая сеть, которая, я надеюсь, предполагает, что эти результаты будут обобщать
Эти параметры очень легко настроить в тестовом коде , и я призываю людей сделать это. (и искать ошибки в тесте).
Результаты
Мои результаты следующие:
Когда я ссылаюсь на ошибку, это абсолютная величина разницы между углом, выведенным нейронной сетью, и истинным углом. Таким образом, средняя ошибка (например) - это среднее значение для 1000 тестовых случаев этой разницы и т. Д. Я не уверен, что мне не следует масштабировать ее, сделав ошибку, скажем, равной к ошибке ). π7 π4 π4
Я также представляю точность на разных уровнях детализации. Точность, являющаяся частью тестовых случаев, была исправлена. Таким
accuracy_to_point01
образом, это означает, что он был посчитан как правильный, если результат был в пределах 0,01 от истинного угла. Ни одно из представлений не дало идеальных результатов, но это не удивительно, учитывая, как работает математика с плавающей запятой.Если вы посмотрите на историю этого поста, то увидите, что результаты немного шумят, немного меняются каждый раз, когда я перезапускаю его. Но общий порядок и шкала ценностей остаются прежними; что позволяет нам сделать некоторые выводы.
обсуждение
Биннинг с softmax работает намного хуже, поскольку я сказал, что не уверен, что ничего не испортил в реализации. Это работает чуть выше, чем скорость догадки, хотя. если бы это было только предположение, мы получили бы среднюю ошибкуπ
Кодирование sin / cos работает значительно лучше, чем масштабированное кодирование 0-1. Улучшение в том, что при 1000 обучающих итерациях sin / cos работает примерно в 3 раза лучше по большинству показателей, чем масштабирование при 10000 итераций.
Я думаю, что отчасти это связано с улучшением обобщения, так как оба получали довольно схожую среднеквадратичную ошибку в обучающем множестве, по крайней мере, один раз было выполнено 10 000 итераций.
Безусловно, существует верхний предел наилучшей возможной производительности в этой задаче, учитывая, что Угол может быть больше или меньше любого действительного числа, но не все такие ангелы выдают разные линии с разрешением пикселей. Так как, например, углы 45.0 и 45.0000001 оба связаны с одним и тем же изображением с таким разрешением, ни один метод никогда не получит оба совершенно правильных.101 × 101
Также представляется вероятным, что в абсолютном масштабе, чтобы выйти за рамки этой производительности, необходима лучшая нейронная сеть. Вместо очень простого, описанного выше в экспериментальной установке.
Вывод.
Кажется, что представление sin / cos является безусловно лучшим из представлений, которые я исследовал здесь. Это имеет смысл, поскольку оно имеет плавное значение при перемещении по кругу. Мне также нравится, что обратное можно сделать с помощью arctan2 , что элегантно.
Я полагаю, что поставленная задача достаточна в ее способности представить разумную проблему для сети. Хотя я полагаю, что на самом деле это просто обучение подгонке кривой к так что, возможно, это слишком просто. И, возможно, хуже, это может быть в пользу парного представления. Я не думаю, что это так, но здесь уже поздно, поэтому я мог что-то упустить, и я приглашаю вас снова просмотреть мой код . Предлагайте улучшения или альтернативные задачи.е( х ) = у1Y2Икс
источник
tan(angle)
пойдет так хорошо, учитывая, что tan не определен для всех углов (например, ). Я перезапущу его со случайно сгенерированными углами и отредактирую посты.Вот еще одна реализация Python, сравнивающая предложенную Линдоном Уайтом кодировку с бинн-подходом. Код ниже выдает следующий вывод:
источник
Вот моя Python-версия вашего эксперимента. Я сохранил многие детали вашей реализации, в частности, я использую одинаковый размер изображения, размеры сетевого уровня, скорость обучения, импульс и метрики успеха.
Каждая протестированная сеть имеет один скрытый слой (размер = 500) с логистическими нейронами. Выходные нейроны являются либо линейными, либо softmax, как отмечено. Я использовал 1000 тренировочных изображений и 1000 тестовых изображений, которые были сгенерированы случайным образом независимо (поэтому могут быть повторы). Обучение состояло из 50 итераций по обучающему набору.
Мне удалось получить довольно хорошую точность, используя биннинг и «гауссовское» кодирование (имя, которое я придумал; похоже на биннинг, за исключением того, что целевой выходной вектор имеет форму exp (-pi * ([1,2,3, ... , 500] - idx) ** 2) где idx - индекс, соответствующий правильному углу). Код ниже; вот мои результаты:
Тестовая ошибка для (cos, sin) кодирования:
1000 тренировочных изображений, 1000 тестовых изображений, 50 итераций, линейный вывод
Среднее значение: 0,0911558142071
Медиана: 0.0429723541743
Минимум: 2.77769843793e-06
Максимум: 6.2608513539
Точность до 0,1: 85,2%
Точность до 0,01: 11,6%
Точность до 0,001: 1,0%
Тестовая ошибка для кодировки [-1,1]:
1000 тренировочных изображений, 1000 тестовых изображений, 50 итераций, линейный вывод
Среднее значение: 0,234181700523
Медиана: 0.17460197307
Минимум: 0.000473665840258
Максимум: 6,00637777237
Точность до 0,1: 29,9%
Точность до 0,01: 3,3%
Точность до 0,001: 0,1%
Тестовая ошибка для кодировки 1 из 500:
1000 тренировочных изображений, 1000 тестовых изображений, 50 итераций, вывод softmax
Среднее значение: 0,0298767021922
Медиана: 0.00388858079174
Минимум: 4.08712407829e-06
Максимум: 6.2784479965
Точность до 0,1: 99,6%
Точность до 0,01: 88,9%
Точность до 0,001: 13,5%
Тестовая ошибка для гауссовой кодировки:
1000 тренировочных изображений, 1000 тестовых изображений, 50 итераций, вывод softmax
Я не могу понять, почему наши результаты противоречат друг другу, но, похоже, это требует дальнейшего изучения.
источник
Другой способ кодирования угла - это набор из двух значений:
Это будет иметь ту же проблему, что и arctan2, в том, что градиент не определен при тета = 0. У меня нет времени, чтобы обучить сеть и сравнить с другими кодировками, но в этой статье техника показалась достаточно успешной.
источник