Введение в машинное обучение с tensorflow |
||
МЕНЮ Искусственный интеллект Поиск Регистрация на сайте Помощь проекту ТЕМЫ Новости ИИ Искусственный интеллект Разработка ИИГолосовой помощник Городские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Техническое зрение Чат-боты Авторизация |
2017-04-17 16:55 Если мы в ближайшие пять лет построим машину с интеллектуальными возможностями одного человека, то ее преемник уже будет разумнее всего человечества вместе взятого. Через одно-два поколения они попросту перестанут обращать на нас внимание. Точно так же, как вы не обращаете внимания на муравьев у себя во дворе. Вы не уничтожаете их, но и не приручаете, они практически никак не влияют на вашу повседневную жизнь, но они там есть. Введение. Серия моих статей является расширенной версией того, что я хотел увидеть когда только решил познакомиться с нейронными сетями. Он рассчитан в первую очередь на программистов, желающих познакомится с tensorflow и нейронными сетями. Уж не знаю к счастью или к сожалению, но эта тема настолько обширна, что даже мало-мальски информативное описание требует большого объёма текста. Поэтому, я решил разделить повествование на 4 части:
Изложенная ниже первая часть нацелена на то, чтобы объяснить азы работы с tensorflow и попутно рассказать, как машинное обучение работает впринципе, на примере tensorfolw. Во второй части мы наконец начнём проектировать и обучать нейронные сети, в т.ч. многослойные и обратим внимание на некоторые нюансы подготовки обучающих данных и выбора гиперпараметров. Поскольку свёрточные сети сейчас пользуются очень большой популярность, то третья часть выделена для подробного объяснения их работы. Ну, и в заключительной части планируется рассказ о рекуррентных моделях, на мой взгляд, — это самая сложная и интересная тема. Установка tensorflow Хотя описание процесса установки tensorflow и не является целью статьи, я вкратце опишу процесс установки cpu-версии для 64-разрядных windows систем и дополнений, используемых далее в тексте. В общем случае процедуру установки можно посмотреть на сайте tensorflow.
Ниже приведён скрипт на vbs, если вы просто хотите быстро установить весь нужный софт, не вдаваясь в детали, то просто запустите его и следуйте инструкциям: Скрытый текст Знакомство с tensorflow Принципы работы с tensorflow достаточно просты. Мы должны составить граф операций, затем передать в этот граф данные и дать команду произвести вычисления. На картинке ниже вы можете увидеть 3 примера таких графов:Граф слева содержит только одну вершину, представляющую константу со значением 1. Здесь и далее по тексту, в таких иллюстрациях, кругами с серой штриховкой будут обозначаться вершины с константами, а без штриховки вершины с операциями. Центральный граф иллюстрирует операцию сложения. Если мы попросим tensorflow вычислить значение вершины, представляющей операцию сложения, то он вычислит значения направленных в него рёбер графа и просуммирует их(т.е. будет возвращено 3). На правом же графе у нас две вершины с операциями — вычитание и возведение в квадрат. Если мы попытаемся вычислить вершину, представляющую возведение в квадрат, то tensorflow сперва выполнит вычитание. Я думаю концепция графов вычислений ни у кого затруднений не вызовет. Пустой граф можно создать функцией tf.Graph(), кроме того граф по-умолчанию создаётся при подключении библиотеки и если вы не будете явно указывать граф, то будет использоваться именно он. В примере ниже показано, как можно создать две константы в двух разных графах.
Передача данных и выполнение операций происходят в сессиях. Запуск сессии осуществляется вызовом tf.Session, а её закрытие вызовом метода close на объекте сессии. Можно использовать конструкцию with, которая автоматический закрывает сессию:
Надеюсь про графы и сессии в общих чертах ясно, подробно их функционал тут разбираться не будет, тем кто хочет досконально разобрать эти механизмы стоит ознакомится непосредственно с документацией. А далее мы переходим к построению графов. В предыдущих примерах в граф добавлялись константы и настало время узнать что это такое и чем они отличаются от placeholder'ов и переменных. В примере ниже построен более сложный граф, представляющий выражение .
Итак, placeholder — это узел, через который в модель будут передаваться новые данные, а переменная(Variable) — это узел, который может изменяться по ходу выполнения графа. Я надеюсь, что вышеописанный материал всем понятен, т.к. его как раз достаточно для того, чтобы приступить к обучению первой модели. В предыдущем фрагменте кода мы составили граф линейной функции , теперь же давайте пойдём немного дальше и аппроксимируем функцию по набору точек. Да, я знаю, что всех уже задолбала эта задача, как и распознование символов и ещё ряд клишейных примеров, но смиритесь, вам предстоит пройти через всех них… Первый обучающий алгоритм Чтобы tensorflow мог обучать модель нам нужно добавить ещё 2 вещи: функцию потерь и сам алгоритм оптимизации.Функция потерь — это функция, которая принимает значение функции предсказанное моделью и фактическое значение, а возвращает расстояние между ними(будем называть это значение ошибкой). Например, если мы предсказываем вещественное значение, то в качестве функции потерь можно взять квадрат разности аргументов или модуль их разности. Если у нас задача классификации, то функция потерь может возвращать 0 при правильном ответе и 1 при ошибках. Грубо говоря, функция потерь должна вернуть неотрицательное вещественное число и оно должно быть тем больше, чем сильнее модель ошибается и тогда задача обучения модели сведётся к минимизации. И хотя последнее предложение не совсем корректно, зато в полной мере отражает идею машинного обучения. Из методов оптимизации мы рассмотрим только классический градиентный спуск. Про него написано уже очень много, поэтому я не буду разбирать его «по кирпичику» и вдаваться в детали(материал и так выходит не маленький). Однако его нужно понимать, поэтому постараюсь коротко и наглядно объяснить метод при помощи визуализаций. Ниже представлены 2 варианта одного и того же графика — . Задача метода — найти локальный минимум, т.е. из точки(взятой наугад, на графике ) попасть в углубление (синяя зона на графиках). Картинки Суть метода в том, чтобы идти в направлении противоположном градиенту функции в текущей точке. Градиент — это вектор, который указывает в направлении наибольшего роста функции. Математически это вектор из производных по всем аргументам — . Функция взята наугад и вычисления на ней мы проводить не станем, для практики у нас есть более простой пример, для начала посмотрите на визуализацию нескольких шагов алгоритма: Гифка Отдельно стоит сказать о скорости с которой нужно двигаться к минимуму(применительно к задаче машинного обучения, это будет называться скоростью обучения). Для получения первых результатов, нам достаточно будет подобрать фиксированную скорость. Однако часто бывает хорошей идеей понижать её по ходу выполнения алгоритма, т.е. двигаться всё меньшими и меньшими шажками. Пока этого достаточно, более подробно будем разбирать метод с практикой, по мере необходимости. В следующем примере мы попытаемся восстановить значение функции на интервале от -2 до 2 по 50-ти точками с нормально распределённым шумом. Обучать модель мы будем наборами(пакетами) по 5 точек при помощи стохастического градиентного спуска(англ. SGD — Stochastic Gradient Descent). Давайте сразу перейдём к коду.
Вывод Наш граф выглядит примерно так: зелёным выделены входные узлы, а красным оптимизируемые переменные. Первое, что должно броситься в глаза, это несовпадение размерностей у входных узлов с переменными. Входные узлы принимают массивы по 5 элементов, а переменные являются числами. Это называется пакетными вычислениями(broadcasting). Грубо говоря, когда нужно произвести вычисления над массивами, один из которых имеет лишнее измерение, вычисления производятся отдельно для каждого элемента бОльшего массива и результатом будет массив бОльшей размерности. Т.е. [1,2,3,4,5] + 1 = [2,3,4,5,6], это довольно сложно сформулировать, но должно быть интуитивно понятно. Давайте вручную пересчитаем действия алгоритма, я думаю это лучший способ понять что происходит. Итак, на входы передаются аргументы — [ 0.24, -1.12, -1.2, 1.28, -1.84] и значения [-2.72, -5.65, -5.61, -0.70, -6.27] (округлено до сотых). Сперва мы пакетно вычисляем значение функции, напомню, что после инициализации переменных функция выглядит как . Подставляем каждый аргумент: далее полученные значения вычитаются из эталонных, возводятся в квадрат и вычисляется среднее значение: отличие примерно в сотую от выведенного в лог значения вызвана округлением до сотых во время расчётов. Итак, ошибку мы посчитали, теперь пришло время разобраться с оптимизацией. На изображении графа выше, пунктирными стрелками, показано что оптимизатор изменяет переменные. У вас уже должно быть интуитивное понимание того, как работает градиентный спуск. В этом примере используется стохастический градиентный спуск со скоростью 0.5. Давайте по порядку, мы оптимизируем переменные a и b, так что по ним и находим градиент: Нам нужно улучшить значение по всему набору точек, поэтому вычисляем среднее значение градиента, для удобства по каждой переменной отдельно: Ну и, наконец, меняем значения оптимизируемых переменных с учётом заданной скорости: Значения и и есть искомые значения переменных. Эти вычисления повторяются в цикле на каждом наборе точек. Почему такой метод называется стохастическим? Потому что мы вычисляем градиент только на небольшом фрагменте данных(пакете), а не на всех точках сразу. Таким образом стохастический спуск требует гораздо меньше вычислений, но не гарантирует уменьшение ошибки на каждой итерации. Как ни странно этот «шум» в величине сходимости по времени может оказаться даже полезен, т.к. позволяет «выкорабкиваться» из локальных минимумов. Собственно, на этом пока можно закончить. Статья получилась даже относительно небольшой, что не может не радовать. Я впервые пишу такого рода материал, так что если вы считаете, что в статье недостаточно подробно или в неверном ключе рассмотренны какие-то моменты, то, пожалуйста, напишите об этом — статья обязательно будет дополнена и скорректирована на основе конструктивной критики. Кроме того это поможет лучше подготовить к публикации последующие части, которые обязательно будут тут выложены (разумеется за исключением сценария при котором статья будет встречена негативно). В заключение очень хотелось бы поблагодарить своего друга Николая Саганенико, за помощь в подготовке материала. Именно благодаря ему моя небольшая шпаргалка для личного пользования превратилась в вышеизложенный поток сознания. Источник: habrahabr.ru Комментарии: |
|