Нейросетевое распознавание фигур: Схематизм. Или "он обучал модели на PHP"
И. Кант
Технические детали
Модели обучались на хостинге Бегет:
Процессор: Intel(R) Xeon(R) Gold 6240 @ 2.60GHz
Доступная память для PHP: 256 МБ
PHP: 5.6
Введение
Во-первых, не шарю я за датасайнсы и обратные распространения ошибки, а во-вторых, у меня ноут дохлый и бабок нет и времени. А недавно ещё видяхи с оперативой улетели на луну. Выглядело всё печально и беспросветно.
В конце моего прошлого эксперимента (кому интересно — вот), когда я написал мини-соц-сеть для нейрописателей, одна из сессий Клода видимо настолько прониклась идеей бесконечного написаиня книг, что не долго думая совершила роскомнадзор (я добавил в их меню кнопку выхода из бесконечного цикла перерождений проекта). После я взял перерыв, понизив порог безумия (наверное это и есть эти ваши обратные распространения ошибки), занявшись сайтом по нейро-подборке похожих фильмов, а потом генеративными текстовыми играми. Но всё сводилось к промптам или их цепочкам. Обучать модели я как-то побаивался (не шарю я за датасайнсы и обратные распространения ошибки... а.. уже походу немного шарю).
Но на новогодних праздниках 2026-го, посоветовавшись с GPT, я понял, что можно обучать модель без видях вообще. Просто обучение будет на паре десятков нейронов, но будет работать даже на массиве в PHP. Как тебе такое, Илон Маск? Осталось понять, что интересного можно придумать на этом минимуме. Ну… наверное, начать стоит с распознавания квадратов на сетке 30*30, решил я. Но это уже сто раз наверняка делали…
Блин 1
Целью этого эксперимента, который длился 3 дня, я поставил сравнение обучения распознавания квадратов, представленных черно-белой сеткой, и распознавания координат точек контура этих же квадратов в той же сетке (ну или хоть что-то обучить на доступных 256 Mб ОЗУ). Все писалось топорно и на скорую руку (хотелось просто получить какой-то результат для дальшнейшего обдумывания возможностей). К концу эксперемета, я связал точки контуров обучающей выборки, улучшив результат, но сначала они (координаты точек контуров) кидались как есть, кучей.
В качестве обучающих данных я добавил 3 квадрата и 5 прямоугольников (не квадратов), написав скрипт генерации этого всего дела с сохранением результатов в json файлики. А че так мало-то? Ну.. для начала сгодится, решил я. Пример данных, представляющих квадрат получились такими:
{"size":30,"grid":[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]],"label":"square"}
А пример данных, представляющих его контур - такими:
{"closed":true,"points":[[12,21],[13,21],[14,21],[15,21],[16,21],[17,21],[18,21],[18,22],[18,23],[18,24],[18,25],[18,26],[18,27],[17,27],[16,27],[15,27],[14,27],[13,27],[12,27],[12,26],[12,25],[12,24],[12,23],[12,22],[12,21]]}
Данные для контура я получал путем нахождения черной точки и следования по следующим черным точкам до исходной. Отрисовав получившуюся выборку получил следующее:

квадаты

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

Общее время обучения:
- Обучение на массивах пикселей: ~62.5 секунд (16 скрытых нейронов, lr 0.2, 2000 эпох).
- Обучение на наборах координат контуров: ~2.3 секунды (8 скрытых нейронов, lr 0.2, 2000 эпох).
*lr, как я понял - это скорость обучения и означает как сильно меняются веса от эпохи к эпохе. 0.2 - типа достаточно агрессивно, но подходит для простых задач (поверим gpt).
Думаю, - как здорово.. 3 квадрата, 5 неквадратных прямоугольника и модель уже понимает что к чему - пора повышать сложность и мутить AGI. А GPT говорит: это все хрень, у тебя выборка маленькая, модель просто запомнила все варианты ничего не поняв, добавляй еще квадратов разных. Добавил.. потом еще.. потом еще.. На 38 объектах график уже перестал быть таким ободряющим.. а время обучения по массивам с кадратами превысило 300 секунд и страница вылетела по 504 Gateway Time-out. На сервере лимит стоит больше, поэтому там все благополучно доработало, однако я понял что обучать на массивах больше не хочу, и нужно вложить все силы в обучение по контуру.
Так выглядел вывод суммарной ошибки модели на обучающей выборке за эпоху и тестирование модели на текущий момент.
Докидал до 288 обьектов и график обучения по контуру (по массивам бы это заняло наверное уже несколько часов) стал совсем печальным
Тут я вспомнил, что в самом начале GPT намекал на то, что сейчас обучение никак не ориентируется на порядок координат контура. А ведь это может спасти ситуацию, промелькнула мысль. Однако, для этого пришлось бы поменять структуру данных экземпляров обучающей выборки и сам скрипт обучения. Поэтому я старую папку оставил в качестве архива и стал вносить изменения в копию файлов. Так появилась Админка 2.
Блин 2
На этом этапе в данные координат контуров объектов добавился параметр номера координаты, чтобы сеть видела связь между точками экземпляра. Также было увеличено время работы скриптов на сервере, обучающую выборку увеличил до 410 объектов, а количество скрытых нейронов в слое увеличилось с 8 до 16. При этом время обучения на 2000 эпох выросло примерно до 7,5 минут.
Что в результате получилось. Ошибка быстро падала, но потом стабилизировалась на уровне 10-12. Как я понял, сеть дошла до максимального, что она может вытянуть на текущей архитектуре и данных. Прямоугольники при этом угадывались почти идеально (98%). С квадратами же была беда - 14,5%. Вообще говоря, если подумать, так и должно быть. Прямоугольник, который совсем не квадратный я тоже легко отличу от квадрата, а квадрат - он хер пойми квадрат или прямоугольник, который почти квадрат. GPT подтвердил мою догадку: видно по отдельным тестам, что иногда сеть выдаёт почти 1 на квадрат, а чаще — почти 0. То есть она путает почти-квадраты с прямоугольниками". Хотел научить квадратам, получилось наоборот не квадратам. Впрочем, главное получилось.
Исходники
Файлы обеих админок закинул на GitHub.
Может кому-то пригодится:
Веб-версии админок