Хочу поделиться опытом переписывания нейронной сети с Python на Java |
||
|
МЕНЮ Главная страница Поиск Регистрация на сайте Помощь проекту Архив новостей ТЕМЫ Новости ИИ Голосовой помощник Разработка ИИГородские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Искусственный интеллект Слежка за людьми Угроза ИИ Атаки на ИИ Внедрение ИИИИ теория Компьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Нейронные сети начинающим Психология ИИ Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Промпты. Генеративные запросы Распознавание лиц Распознавание образов Распознавание речи Творчество ИИ Техническое зрение Чат-боты Авторизация |
2026-08-25 11:59 Я Антон, Java-разработчик в Сбере, работаю над продуктом GigaIDE. В этой статье я хочу поделиться опытом переписывания нейронной сети с Python на Java. Изначально это была классическая сеть для распознавания рукописных цифр из датасета MNIST. Мне было интересно не просто скопировать код, а по-настоящему разобраться, как всё устроено, поэкспериментировать и даже заглянуть в её «мозги». Сначала немного теории: нейросеть — это математическая модель, которая преобразует входной сигнал в выходной. В нашем случае сеть состоит из трёх слоёв: входного (784 нейрона), скрытого (200 нейронов) и выходного (10 нейронов). Каждый нейрон одного слоя связан с каждым нейроном следующего, и у каждой связи есть вес. Сигнал, проходя через связи, умножается на вес, суммируется и пропускается через функцию активации. Входной слой получает значения пикселей картинки 28?28, нормализованные к диапазону 0–1. Выходной слой показывает «уверенность» сети в том, что на картинке та или иная цифра. Датасет MNIST — это классика: 60 000 картинок для обучения и 10 000 для тестирования. Каждая картинка представлена в CSV как строка: сначала эталонная цифра, затем 784 значения яркости от 0 до 255. Я написал небольшое приложение, чтобы посмотреть на эти цифры вживую. Было интересно, как можно 6000 раз по-разному написать один и тот же ноль или единицу. Оказалось, что многие цифры написаны в американской манере: единица — это просто наклонная чёрточка, девятка часто без завитка внизу. Это важное наблюдение, ведь сеть обучается именно на таких образах. Самой интересной частью было переписать нейросеть на Java. В Python она занимает несколько строк благодаря библиотеке numpy, которая быстро перемножает матрицы. Я не хотел сразу подключать тяжёлые зависимости, поэтому написал собственный прикладной класс для матричных вычислений — в лоб, по определению. Это немного монструозно, но зато позволяет понять, что реально происходит под капотом. В конструкторе сети задаётся количество узлов в слоях, коэффициент обучения, а веса инициализируются специальным способом: из нормального распределения с центром в нуле и стандартным отклонением, обратно пропорциональным корню из количества узлов. Для детерминированности эксперимента я добавил также стратегии с нулевыми и единичными весами — заведомо провальные, но полезные для сверки результатов с Python-версией. Обучение методом обратного распространения — это самая сложная часть. Я переписал код строчка в строчку, чтобы минимизировать ошибки. На Java формула корректировки весов выглядит громоздко, но работает. Обучение проходило на 60 000 картинках в течение 5 эпох, каждая эпоха занимала около минуты. Это небыстро, но терпимо. После проверки на тестовом множестве точность составила 97,5%, то есть ошибка всего 2,5%. Отличный результат для такой простой сети! Затем я решил пойти дальше: сохранять обученную сеть в файл и загружать её, а также нарисовать свои цифры мышкой и посмотреть, как сеть их распознает. Я написал приложение-визуализатор, где можно открыть сеть, посмотреть её структуру, порисовать на холсте и увидеть вероятности для каждой цифры. И вот тут началось самое интересное. Свои рисунки сеть распознавала очень плохо — точность была примерно 50–60%, никаких 97,5%. Я пробовал менять размер кисти, добавлял размытие, чтобы линии были похожи на рукописные — не помогало. Обиднее всего, когда рисуешь почти одинаковые цифры, а сеть выдаёт разные ответы: то 0,95 для одной, то для другой. Кружок в середине картинки — очевидный ноль для человека, а сеть может принять его за что-то другое. Чтобы понять, что происходит у неё в голове, я реализовал обратный запрос: подаю на выход желаемую цифру, а с входа снимаю «образ», который сеть считает характерным для этой цифры. Ожидал увидеть размытые, но узнаваемые силуэты. На деле получилось, что только ноль и семёрка хоть как-то похожи на цифры, остальное — мазня. Сравнил с картинкой из книги Тарика Рашида, там тоже не идеально, но ноль чёткий. Впрочем, глядя на эти образы, я стал лучше понимать, как рисовать, чтобы сеть угадывала: семёрки, девятки и единицы стали получаться точнее, и точность распознавания немного возросла. В итоге я сделал несколько выводов. Во-первых, нейросеть, обученная на стандартном датасете, не обязана хорошо работать на ваших «каракулях», если они отличаются от того, что было в обучающей выборке. Во-вторых, рукописные цифры мы пишем иначе, чем американские школьники из MNIST. В-третьих, чтобы получить хороший результат, надо либо больше и разнообразнее обучать сеть, либо генерировать синтетические данные с похожим искажением. Эксперимент получился очень познавательным: я не только переписал код, но и на практике увидел сильные и слабые стороны простой нейросети. А вы сталкивались с ситуацией, когда модель отлично работает на тестовой выборке, но плохо справляется с реальными данными? Что бы вы посоветовали для улучшения распознавания таких «живых» примеров? Телеграм: t.me/ainewsline Источник: vk.com Комментарии: |
|