Вступ
Я вважаю це питання дійсно цікавим, я припускаю, що хтось виклав на ньому документ, але це мій вихідний день, тому я не хочу переслідувати посилання.
Таким чином, ми могли б розглядати це як подання / кодування результатів, що я роблю в цій відповіді. Я все ще думаю, що є кращий спосіб, де можна просто використовувати дещо іншу функцію втрат. (Можливо, сума квадратичних різниць із використанням модуля віднімання 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
Моє тестування тут працює як функція попередньої обробки
Для цього я визначив завдання:
Дано чорно-біле зображення, що представляє одну лінію на порожньому тлі. Виведіть, під яким кутом знаходиться ця лінія до «позитивної осі x»
Я реалізував функцію випадковим чином генерувати ці зображення із лініями під випадковими кутами (Примітка: в попередніх версіях цієї публікації використовувались випадкові нахили, а не випадкові кути. Завдяки @Ari Herman за її вказівку. Це тепер виправлено). Я побудував кілька нейронних мереж, щоб оцінити ефективність цього завдання. Повна інформація про реалізацію міститься в цьому ноутбуці Юпітера . Цей код у Julia , і я використовую бібліотеку нейронних мереж Mocha .
Для порівняння, я подаю це проти альтернативних методів масштабування до 0,1. і складати в 500 бункерів і використовувати softmax з м'якою міткою. Я не особливо задоволений останнім, і відчуваю, що мені потрібно підправити це. Ось чому, на відміну від інших, я пробую лише 1000 ітерацій, проти двох інших, які були виконані на 1000 і на 10 000
Експериментальне встановлення
Зображення становили піксель, лінія починається в центрі і йде до краю. На зображенні не було шуму тощо, лише "чорна" лінія на білому тлі.101 × 101
Для кожного треку було створено 1000 тренувань та 1000 тестових зображень випадковим чином.
Мережа оцінювання мала єдиний прихований шар шириною 500. У прихованому шарі використовувались сигмоїдні нейрони.
Його готували за стохастичним градієнтним порядком, із фіксованою швидкістю навчання 0,01 та фіксованим імпульсом 0,9.
Ні регуляризація, ні випадання не використовувались. Не було ніякої згортки тощо. Проста мережа, яка, сподіваюсь, дозволяє припустити, що ці результати узагальниться
Налаштувати ці параметри в тестовому коді дуже просто , і я закликаю людей до цього. (і шукайте помилок у тесті).
Результати
Мої результати такі:
| | 500 bins | scaled to 0-1 | Sin/Cos | scaled to 0-1 | Sin/Cos |
| | 1,000 Iter | 1,000 Iter | 1,000 iter | 10,000 Iter | 10,000 iter |
|------------------------|--------------|----------------|--------------|----------------|--------------|
| mean_error | 0.4711263342 | 0.2225284486 | 2.099914718 | 0.1085846429 | 2.1036656318 |
| std(errors) | 1.1881991421 | 0.4878383767 | 1.485967909 | 0.2807570442 | 1.4891605068 |
| minimum(errors) | 1.83E-006 | 1.82E-005 | 9.66E-007 | 1.92E-006 | 5.82E-006 |
| median(errors) | 0.0512168533 | 0.1291033982 | 1.8440767072 | 0.0562908143 | 1.8491085947 |
| maximum(errors) | 6.0749693965 | 4.9283551248 | 6.2593307366 | 3.735884823 | 6.2704853962 |
| accurancy | 0.00% | 0.00% | 0.00% | 0.00% | 0.00% |
| accurancy_to_point001 | 2.10% | 0.30% | 3.70% | 0.80% | 12.80% |
| accurancy_to_point01 | 21.90% | 4.20% | 37.10% | 8.20% | 74.60% |
| accurancy_to_point1 | 59.60% | 35.90% | 98.90% | 72.50% | 99.90% |
Де я посилаюсь на помилку, це абсолютне значення різниці між кутом виходу нейронної мережі та справжнім кутом. Отже, середня помилка (наприклад) - це середня величина за 1000 тестових випадків такої різниці тощо. Я не впевнений, що мені не слід її змінити, зробивши помилку, скажімо, бути рівним до помилки ).7 π4π4
Я також представляю точність на різних рівнях деталізації. Точність, що є частиною тестових випадків, яку вона отримала. Значить accuracy_to_point01
, це вважалося правильним, якщо вихід був у межах 0,01 від істинного кута. Жодне з представлень не дало ідеальних результатів, але це зовсім не дивно, враховуючи, як працює математика з плаваючою комою.
Якщо ви подивитесь на історію цього допису, ви побачите, що результати мають трохи шуму до них, трохи відрізняючись кожного разу, коли я його повторюю. Але загальний порядок і масштаб значень залишаються однаковими; тим самим дозволяючи зробити деякі висновки.
Обговорення
Спілка з softmax є найгіршою, тому що я сказав, що не впевнений, що я щось не накрутив у виконанні. Хоча це і працює незначно вище показника здогаду. якби тільки здогадувалися, ми отримаємо середню помилкуπ
Кодування sin / cos працює значно краще, ніж масштабування 0-1. Поліпшення полягає в тій мірі, коли на 1000 тренувань тренувань sin / cos виконує приблизно в 3 рази краще на більшості метрик, ніж масштабування становить 10 000 ітерацій.
Я думаю, частково це пов’язано з вдосконаленням узагальнення, оскільки обидва отримували досить схожу середню квадратичну помилку на тренувальному наборі, принаймні один раз виконувались 10 000 ітерацій.
Звичайно, існує верхня межа щодо найкращого виконання цього завдання, враховуючи, що кут може бути більш-менш будь-яким реальним числом, але не всі такі ангели створюють різні лінії з роздільною здатністю пікселів. Так як, наприклад, кути 45.0 і 45.0000001 обидва прив’язані до одного зображення при цій роздільній здатності, жоден метод ніколи не отримає обидва цілком правильні.101 × 101
Також здається ймовірним, що в абсолютних масштабах, щоб вийти за рамки цієї продуктивності, потрібна краща нейронна мережа. Замість простого, описаного вище в експериментальних установках.
Висновок.
Здається, що представлення гріх / союз є найкращим з представлень, які я тут досліджував. Це має сенс, оскільки воно має плавне значення під час переміщення по колу. Мені також подобається, що обернення можна зробити за допомогою arctan2 , який є елегантним.
Я вважаю, що поставлене завдання є достатнім для його здатності представляти розумну проблему для мережі. Хоча я гадаю, що насправді це просто навчитися робити криву, що підходить до тому, можливо, це занадто просто. І, можливо, гірше, що це може сприяти парному представництву. Я не думаю, що це так, але тут вже запізно, тому я, можливо, щось пропустив, я запрошую вас ще раз переглянути мій код . Запропонуйте вдосконалення чи альтернативні завдання.f( х ) = у1у2х