Оказывается кроме нейросетей есть ещё одна парадигма ИИ, не менее серьёзная – ансамбли.
Я всё хотел написать нейросеть, которая будет распознавать буквы на рисунке. Может, проще вначале сделать этого на основе бустинга?
Для бустинга нужно набрать побольше алгоритмов, кое-как решающих нужную задачу, и заставить их обучать друг друга. Какие это могут быть алгоритмы? Я в этой статье пока мало понял про промежуточные парадигмы между обычным программированием и ИИ (регрессия, кластеризация и т.д.).
А может быть, проще самому написать примитивные алгоритмы? Скажем один – простое сопоставление рисунка и шаблона, второй – какой-нибудь топологический анализ и т.д. Далее я заставлю их друг друга обучать по принципу бустинга.
Или я не так понимаю суть ансамблей?
"Ты должен сделать добро из зла, потому что его больше не из чего сделать." Р.П. Уоррен
Здравствуйте, Khimik, Вы писали:
K>Оказывается кроме нейросетей есть ещё одна парадигма ИИ, не менее серьёзная – ансамбли.
Возможно у меня не совсем верное мнение на этот счёт (точнее не совпадающее с нынешним марктетинговым хайпом), но лично я оцениваю и подобные нейронные сети и все остальные статистические методы не как область ИИ. На мой взгляд это всего лишь продвинутые методы апроксимации многомерных функций, в которых подбор множества параметров апроксимации под конкретную задачу почему-то назвали процессом обучения. Хотя никакого реального обучения (в классическом ИИ понимании) там нет — просто заранее готовится набор параметров по тренировочным данным.
Но я не настаиваю на таком понимание — это лично моё мнение. Согласно ему вот в той статье, на которую ты ссылаешься, машинное обучение должно быть не вложенным в ИИ множеством, а пересекающимся с ним. А то иначе какой-нибудь компилятор C++ с PGO тоже становится ИИ... Ну да ладно, это всё вопрос терминологии.
K>Я всё хотел написать нейросеть, которая будет распознавать буквы на рисунке. Может, проще вначале сделать этого на основе бустинга?
Нет, вот как раз распознавание картинок является единственной областью, где нейронные сети безусловно рулят в данный момент. Естественно не любые, а свёрточные. Именно из-за этого механизма (близкого к человеческому зрению) соответствующие нейронные сети могут видеть главные детали, не отвлекаясь на различия в пикселях.
K>Для бустинга нужно набрать побольше алгоритмов, кое-как решающих нужную задачу, и заставить их обучать друг друга. Какие это могут быть алгоритмы? Я в этой статье пока мало понял про промежуточные парадигмы между обычным программированием и ИИ (регрессия, кластеризация и т.д.).
Ты что-то напутал. Использование ансамбля разных алгоритмов — это стекинг (как и написано в статье по ссылке). А бустинг — это применение одного и того же простенького алгоритма на разных выборках из набора данных для обучения. Причём в отличие от бэггинга (в котором тоже один алгоритм на множестве выборок) там берутся не случайные выборки, а специальная последовательность, позволяющая наращивать точность (итеративный градиентный спуск).
K>А может быть, проще самому написать примитивные алгоритмы? Скажем один – простое сопоставление рисунка и шаблона, второй – какой-нибудь топологический анализ и т.д. Далее я заставлю их друг друга обучать по принципу бустинга. K>Или я не так понимаю суть ансамблей?
Нуу в принципе можно попробовать. Если у тебя будет неплохой тупой и быстрый алгоритм с чёткой функцией оценки, то можно применить к нему бустинг. Возможно даже придумаешь что-то новенькое, позволяющее обойти свёрточные нейронные сети. Но со всем этим имеет смысл возиться, только если это у тебя основное занятие в жизни (ну или основное хобби). Потому что надо будет долго и сильно углубляться в детали (всё элементарное уже давно изучено). Если у тебя сейчас стоит какая-то практическая задача, то для всего кроме картинок лучше взять готовый популярный алгоритм типа такого http://scikit-learn.org/stable/modules/ensemble.html#gradient-boosting, а для картинок свёрточную нейронную сеть.
Здравствуйте, alex_public, Вы писали:
_>Нуу в принципе можно попробовать. Если у тебя будет неплохой тупой и быстрый алгоритм с чёткой функцией оценки, то можно применить к нему бустинг. Возможно даже придумаешь что-то новенькое, позволяющее обойти свёрточные нейронные сети. Но со всем этим имеет смысл возиться, только если это у тебя основное занятие в жизни (ну или основное хобби). Потому что надо будет долго и сильно углубляться в детали (всё элементарное уже давно изучено). Если у тебя сейчас стоит какая-то практическая задача, то для всего кроме картинок лучше взять готовый популярный алгоритм типа такого http://scikit-learn.org/stable/modules/ensemble.html#gradient-boosting, а для картинок свёрточную нейронную сеть.
Я пока просто хочу порассуждать, что получится, если я сделаю следующую программу:
Напишу кучу разных простых алгоритмов, которые определяют разные дескрипторы изображения. Например такие:
— центр тяжести объекта;
— ширина;
— высота;
— наличие и количество замкнутых полостей (например в цифре 0 есть одна, а в цифре 8 их две);
— количество прямых углов
— количество разных других углов
— наличие изогнутых линий
— количество вертикальных чёрточек
— количество горизонтальных чёрточек
— количество наклонённых чёрточек (разных степей наклонности)
— площадь объекта
— количество пересечений линий
— количество мест где линия расстраивается
— просуммировать все строки, получится одна строка, на ней найти центр масс и ширину объекта
— просуммировать все столбцы, получится одна строка, на ней также найти центр масс и ширину
— это же повторить для двух диагоналей
— найти полости и их также просуммировать по строкам, по столбцам, найти центр и т.д.
Итого получится столбец из примерно 30 цифр. Далее этот столбец прогоняется через нейросеть, и выдаётся итоговый результат.
Поскольку нейросеть будет небольшая, для её оптимизации, возможно, даже не придётся применять градиентный спуск, а хватит банального перебора.
Я правильно понимаю, что это будет именно стекинг? Как думаете, результат будет лучше, чем если я с теми же затратами мозговремени слелаю для этой же задачи свёрточную НС?
"Ты должен сделать добро из зла, потому что его больше не из чего сделать." Р.П. Уоррен
K>Итого получится столбец из примерно 30 цифр. Далее этот столбец прогоняется через нейросеть, и выдаётся итоговый результат. K>Поскольку нейросеть будет небольшая, для её оптимизации, возможно, даже не придётся применять градиентный спуск, а хватит банального перебора.
Обучение нейросети перебором? Нет.
K>Я правильно понимаю, что это будет именно стекинг? Как думаете, результат будет лучше, чем если я с теми же затратами мозговремени слелаю для этой же задачи свёрточную НС?
Нет. стекинг — это не стек признаков. Стекинг — это пул моделей, возможно, обученных на подмножествах признаков (но не обязательно)
Сеть локальность и зависимую локальность учитывает "бесплатно", у тебя же будет набор неких признаков, неясно где размешенных по карте.Последние части плана относительно "суммирования" звучат беспомощно, тяжеловесно и в то же время как-то угрожающе.
Здравствуйте, Khimik, Вы писали:
_>>Нуу в принципе можно попробовать. Если у тебя будет неплохой тупой и быстрый алгоритм с чёткой функцией оценки, то можно применить к нему бустинг. Возможно даже придумаешь что-то новенькое, позволяющее обойти свёрточные нейронные сети. Но со всем этим имеет смысл возиться, только если это у тебя основное занятие в жизни (ну или основное хобби). Потому что надо будет долго и сильно углубляться в детали (всё элементарное уже давно изучено). Если у тебя сейчас стоит какая-то практическая задача, то для всего кроме картинок лучше взять готовый популярный алгоритм типа такого http://scikit-learn.org/stable/modules/ensemble.html#gradient-boosting, а для картинок свёрточную нейронную сеть. K>Я пока просто хочу порассуждать, что получится, если я сделаю следующую программу: K>Напишу кучу разных простых алгоритмов, которые определяют разные дескрипторы изображения. Например такие: K> — центр тяжести объекта; K> — ширина; K> — высота; K> — наличие и количество замкнутых полостей (например в цифре 0 есть одна, а в цифре 8 их две); K> — количество прямых углов K> — количество разных других углов K> — наличие изогнутых линий K> — количество вертикальных чёрточек K> — количество горизонтальных чёрточек K> — количество наклонённых чёрточек (разных степей наклонности) K> — площадь объекта K> — количество пересечений линий K> — количество мест где линия расстраивается K> — просуммировать все строки, получится одна строка, на ней найти центр масс и ширину объекта K> — просуммировать все столбцы, получится одна строка, на ней также найти центр масс и ширину K> — это же повторить для двух диагоналей K> — найти полости и их также просуммировать по строкам, по столбцам, найти центр и т.д.
Дело в том, что указанно тобой — это не разные алгоритмы распознавания, а просто различные способы выделения признаков из исходных данных. Это совершенное другое дело. В алгоритм распознавания (даже самый простой, типа дерева решений) задаётся (это и называют обучением) шаблон распознавания. А у тебя здесь фиксированные алгоритмы, которые по сути не относятся к распознаванию, а является просто предобработкой исходных данных.
Кстати, свёрточная нейронная сеть на своих начальных слоях в итоге занимается буквально тем же самым. Только вот набор этих алгоритмов у неё намного больше (по сути бесконечный и конкретный набор определяется шаблоном распознавания). Причём многие из этих признаков никогда не были бы придуманы людьми классическим методом. Т.е. основная идея этих свёрточных сетей — это автоматическая генерация наиболее интересных признаков для данного шаблона.
K>Итого получится столбец из примерно 30 цифр. Далее этот столбец прогоняется через нейросеть, и выдаётся итоговый результат.
Да, это известный рабочий вариант. Причём в качестве нейронной сети тут уже должен быть простейший перцептрон.
K>Поскольку нейросеть будет небольшая, для её оптимизации, возможно, даже не придётся применять градиентный спуск, а хватит банального перебора.
Ну метод обучения — это отдельный вопрос. Главное тут другое: подобная схема распознавания будет выдавать результат на уровне нейросетей 90-ых годов, т.е. довольно слабенькие.
K>Я правильно понимаю, что это будет именно стекинг?
Нет, абсолютно другой смысл. Здесь у тебя всё обучение (задание шаблона) сосредоточено в этом твоём сумматоре (простейшей нейронной сети). Т.е. по сути это у тебя просто убогая нейронная сеть с определённой предобработкой. А в стекинге у нас участвуют нормальные (пусть и простенькие) алгоритмы распознавания (т.е. шаблон задаётся в них), а сумматор наоборот тупо усредняет их (ну возможно с разными весами под разные шаблоны, но это не суть).
K>Как думаете, результат будет лучше, чем если я с теми же затратами мозговремени слелаю для этой же задачи свёрточную НС?
Ещё раз: если главная цель не в создание нового алгоритма распознавания, а в чём-то другом (для чего понадобилось по ходу дела распознавать картинки), то вряд ли сейчас есть более правильное решение, помимо скачивания готовой свёрточной нейронной сети. Если же целью является исследование на тему различных методов распознавания изображений, то можно попробовать поиграться. Только в качестве мелких алгоритмов следует брать не описанное выше (это уже давно проверено и работает априори хуже современных решений), а взять какие-то реальные мелких алгоритмы распознавания.
Здравствуйте, SomeOne_TT, Вы писали:
SO_>Здравствуйте, Khimik, Вы писали:
K>>Итого получится столбец из примерно 30 цифр. Далее этот столбец прогоняется через нейросеть, и выдаётся итоговый результат. K>>Поскольку нейросеть будет небольшая, для её оптимизации, возможно, даже не придётся применять градиентный спуск, а хватит банального перебора.
SO_>Обучение нейросети перебором? Нет.
Вот этот момент мне непонятен.
Я вроде понимаю, что для свёрточных нейросетей нужен именно градиентный спуск. Но в моём названном примере я что-то не уверен, что градиентный спуск вообще тут может что-то дать. Здесь ведь на вход НС подаётся набор дескрипторов, и буквы или цифры должны определяться по конкретному сочетанию этих дескрипторов.
Ну вот как отличить 6 от 9, напримеп: у обоих знаков есть одна полость и несколько изогнутых линий, но центр тяжести по оси Y для шестерки ниже, чем для девятки. Т.е. тут почти бинарная логика:
одна полость, несколько линий, центр тяжести внизу — это 6
одна полость, несколько линий, центр тяжести вверху — это 9.
Это как у Платона, который назвал человека двуногим существом без перьев, а Диоген ощипал петуха и заявил, что он точно соответствует этому определению, после чего Платон внес уточнение, добавив, что человек — это двуногое существо без перьев и с плоскими ногтями.
Когда речь о какой-то такой бинарной логике, я не вижу как может помочь градиентный спуск. Тут надо именно перебирать все варианты.
"Ты должен сделать добро из зла, потому что его больше не из чего сделать." Р.П. Уоррен
Здравствуйте, Khimik, Вы писали:
K>Вот этот момент мне непонятен. K>Я вроде понимаю, что для свёрточных нейросетей нужен именно градиентный спуск. Но в моём названном примере я что-то не уверен, что градиентный спуск вообще тут может что-то дать. Здесь ведь на вход НС подаётся набор дескрипторов, и буквы или цифры должны определяться по конкретному сочетанию этих дескрипторов.
Да, но нейросети не смотрят: если-если. Ты сейчас описываешь перцептрон: он определяет по взвешенной сумме.
K>Ну вот как отличить 6 от 9, напримеп: у обоих знаков есть одна полость и несколько изогнутых линий, но центр тяжести по оси Y для шестерки ниже, чем для девятки. Т.е. тут почти бинарная логика: K>одна полость, несколько линий, центр тяжести внизу — это 6 K>одна полость, несколько линий, центр тяжести вверху — это 9. K>Это как у Платона, который назвал человека двуногим существом без перьев, а Диоген ощипал петуха и заявил, что он точно соответствует этому определению, после чего Платон внес уточнение, добавив, что человек — это двуногое существо без перьев и с плоскими ногтями. K>Когда речь о какой-то такой бинарной логике, я не вижу как может помочь градиентный спуск. Тут надо именно перебирать все варианты.
Это описание Decision tree, оно вполне подойдёт и будет быстро работать. Также можешь использовать SVM, его, скорее всего, получится настроить для твоих признаков точнее.
Здравствуйте, Khimik, Вы писали:
K>Итого получится столбец из примерно 30 цифр. Далее этот столбец прогоняется через нейросеть, и выдаётся итоговый результат. K>Поскольку нейросеть будет небольшая, для её оптимизации, возможно, даже не придётся применять градиентный спуск, а хватит банального перебора.
Получится простая распознавалка в пространстве признаков.
Соответственно, в качестве классификатора можно взять что-то более простое, чем NN, ну EM, например, или SVM...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
K>Я правильно понимаю, что это будет именно стекинг?
Это не будет стекингом.
K>Как думаете, результат будет лучше, чем если я с теми же затратами мозговремени слелаю для этой же задачи свёрточную НС?
Результат твоего классификатора будет плохой. А самое главное, медленный и сложный в реализации: можешь начать реализовывать поиск признаков, если центр тяжести и количество замкнутых полостей ты найдёшь быстро, то на количестве вертикальных-горизонтальных чёрточек ты застрянешь (можешь, конечно, использовать LSD из opencv, но всё равно возни будет много, не факт, что будет работать хорошо). Реализация свёрточной нейронной сети для этой задачи на keras занимает пару экранов кода (ResNet), тренируется очень быстро, работает мгновенно.
Здравствуйте, De-Bill, Вы писали:
DB>А самое главное, медленный и сложный в реализации: можешь начать реализовывать поиск признаков, если центр тяжести и количество замкнутых полостей ты найдёшь быстро, то на количестве вертикальных-горизонтальных чёрточек ты застрянешь
Да, это я понимаю.
Тогда, допустим, я сделаю немного другой набор дескрипторов: менее понятный для обычного человека, но лёгкий для программирования и не менее “дескриптивный”.
Например такой. Разбиваем картинку на строки, в каждой считаем число чёрных пикселей. Если у полученной функции найти среднее значение – это будет просто центр масс по оси Y. А если эту фунцию ещё домножить, например, на её абсциссу (это координата Y на исходной картинке, а на функции координата X), и найти среднее значение, то получится новый дескриптор: например, 5 он будет больше, чем для 2 (если ось Y на исходной картинке начинается сверху), поскольку у пятёрки в нижней части центр масс немного правее чем у двойки.
Другой вариант – проинтегрировать функцию, или продифференцировать, и т.д. Так получится много разнообразных дескрипторов.
Это получается как бы “недискретный”, или “аналоговый” дескриптор, не знаю как это назвать правильно. А ещё можно сделать много дискретных дескрипторов. Одним из них может служить количество полостей, как я уже писал. А другой, например, такой:
Разбиваем картинку на строки, в каждой строке считаем количество интервалов одного цвета. Далее в этой функции (“координата Y – количество интервалов”) снова находим количество интервалов в одинаковым значением.
Для 0 получится 5, а для 9 – 6 таких интервалов (а количество полостей у 0 и 9 одинаковое).
Ну а в итоге, если я это реализую (выдача этих дескрипторов будет прогоняться через небольшую нейросеть) – это будет называться стекинг?
"Ты должен сделать добро из зла, потому что его больше не из чего сделать." Р.П. Уоррен
K>Ну а в итоге, если я это реализую (выдача этих дескрипторов будет прогоняться через небольшую нейросеть) – это будет называться стекинг?
Не будет. Для стекинга тебе нужны несколько разных классификаторов, результаты которых ты объединишь для итогового ответа. У тебя же просто несколько алгоритмов поиска фич на основе которых делается классификация нейронной сетью. Сложный и в настоящее время бессмысленный подход. Разве что из-за любви к искусству можно реализовать.
Здравствуйте, Khimik, Вы писали:
K>Тогда, допустим, я сделаю немного другой набор дескрипторов: менее понятный для обычного человека, но лёгкий для программирования и не менее “дескриптивный”.
Тогда надо узнать про Haar features и почему их все так любят. Или про фильтры Габора и почему их применяют для сравнения отпечатков пальцев или кровеносных сосудов. Или про HOG.
На практике уже нашли довольно много очень хороших дескрипторов, до бума нейросетей учёные этим как раз и занимались. Это сейчас полагаются на "волшевную" силу нейросетей по самостоятельному извлечению признаков.
Кстати, тебе должно быть интересно сравнение трёх похожих фреймворков градиентного бустинга: Catboost vs LightGBM vs xgboost. Интересно, что Яндекс лучше всего умеет работать с категориальными признаками и это круто! Майкрософтовский LightGBM, вроде, лежит в основе их Кинекта.
Здравствуйте, Khimik, Вы писали:
K>Ну а в итоге, если я это реализую (выдача этих дескрипторов будет прогоняться через небольшую нейросеть) – это будет называться стекинг?
Нет. Я же тебе уже однозначно описал. Стекинг — это разновидность ансамбля алгоритмов распознавания (ну в твоём контексте). Т.е. сущностей, каждая из которых способна самостоятельно провести полное опознание твоих цифр на картинке, пускай и не с очень хорошей точностью (а вот их ансамбль даёт уже хорошую точность). Какой-нибудь из твоих "дескрипторов" способен сообщать о том какая цифра на картинке? Естественно нет, потому как у тебя там нет ни одного алгоритма распознавания (как ты вообще представляешь себе алгоритм распознавания без задания ему шаблона что распознавать?). Т.е. у тебя там исключительно алгоритмы предварительной обработки массива данных, которые из одного большого одномерного (картинки — будем считать её тут просто как массив байт) массива делают множество небольших массивов (наборов признаков). Это вполне полезное дело (и кстати именно им занимаются начальные слои свёрточной нейронной сети, только заметно лучше, т.к. там набор признаков подбирается непосредственно под шаблон), только вот к собственно распознаванию оно не имеет никакого отношения — это просто некая трансформация начальных данных и всё. А вот на эти трансформированные данные дальше можно натравить любой приличный алгоритм распознавания: и обычную (не свёрточную) нейронную сеть и ансамбли (например тот же бустинг деревьев или стекинг нескольких простеньких алгоритмов типа тех же деревьев, опорных векторов и т.п.) и вообще что угодно.
Т.е. то, что ты описал, является вполне себе действующей моделью распознавания, но с двумя поправками:
1. она известна уже несколько десятков лет и не используется сейчас, т.к. имеет плохую точность (в сравнение с современными аналогами)
2. это не стекинг, а обычная наивная нейронная сеть, работающая на сформированных руками признаках.