Краткая история ИИ

Искусственный интеллект призван имитировать человеческий интеллект с помощью различных математических и логических инструментов. Первоначальные системы ИИ были системами, основанными на правилах. Эти системы могли изучать формальные математические правила для решения задач и считались интеллектуальными системами. Но эта система плохо справлялась с решением проблем, для которых не существовало формальных правил, и, будучи людьми, мы могли легко их решать, например. идентификация объектов, понимание произнесенных слов и т. д. Для решения этой проблемы начались активные исследования в области имитации человеческого разума, и в 1958 году однажды Фрэнк Розенблатт предложил такую ​​популярную обучающую сеть под названием «Персептрон». В то время персептроны привлекли к себе большое внимание, и позже со временем появилось множество вариаций и расширений перцептронов. Но не все верили в потенциал перцептронов, были люди, которые считали, что настоящий ИИ основан на правилах, а перцептрон не основан на правилах. Мински и Паперт провели анализ персептрона и пришли к выводу, что персептроны разделяют только линейно разделяемые классы. Их статья породила проблему исключающего ИЛИ (X-OR).

X-OR проблема

Проблема XOR - классическая проблема в области искусственного интеллекта, которая была одной из причин «зимнего» искусственного интеллекта в 70-е годы. Чтобы понять это, мы должны понять, как работает Perceptron. Персептрон основан на упрощении архитектуры нейронов, предложенном Маккаллохом-Питтсом, названном нейроном Маккаллоха-Питтса. Не вдаваясь в подробности, мы обсудим функцию нейрона более простым языком. Он имеет два входа и один выход, а нейрон имеет предопределенный порог, если сумма входов превышает порог, тогда выход активен, иначе он неактивен [Ref. Изображение 1]

Мински и Паперт использовали это упрощение персептрона, чтобы доказать, что он неспособен изучать очень простые функции. Обучение с помощью перцептрона в двумерном пространстве показано на изображении 2. Они выбрали Exclusive-OR в качестве одного из примеров и доказали, что Perceptron не имеет способности изучать X-OR. Как показано на изображении 3, X-OR не разделяется в 2-D. Таким образом, перцептрон не может предложить разделяющую плоскость для правильной классификации входных точек. Эта неспособность перцептрона не справляться с X-OR вместе с некоторыми другими факторами привела к зиме ИИ, когда в нейронных сетях выполнялось меньше работы. Позже появилось много подходов, являющихся расширением базового персептрона и способных решать X-OR.

Краткое введение в глубокое обучение

Глубокое обучение - одно из таких расширений базовой модели персептрона, в которой мы создаем стек нейронов и размещаем их на нескольких уровнях. Начальные модели с одним скрытым слоем называются многослойными персептронами и считаются мелкими сетями. Глубокие сети имеют несколько уровней, и в недавних работах была показана способность эффективно решать такие проблемы, как идентификация объектов, распознавание речи, языковой перевод и многие другие. Хотя нейронные сети были вдохновлены человеческим разумом, цель глубокого обучения - не копирование человеческого разума, а использование математических инструментов для создания моделей, которые хорошо работают при решении таких задач, как распознавание изображений, речь / диалог, языковой перевод, создание произведений искусства и т. Д.

Решение X-OR с многослойным персептроном [MLP] в Керасе

Многослойный персептрон - это сеть, имеющая стек нейронов и несколько слоев. Базовый нейрон в современной архитектуре выглядит как изображение 4:

На каждый нейрон подается входной сигнал вместе с соответствующим весом и смещением. Нейрон выполняет две функции:

1) Аккумуляторная функция: по сути, это взвешенная сумма входных данных с добавленным к ней смещением.
2) Функция активации: функции активации являются нелинейными. И, как следует из названия, это функция, определяющая, будет ли вывод узла активно участвовать в общем выводе модели или нет. ReLu - самая популярная функция активации, используемая сейчас.

Теперь я опишу процесс решения X-OR с помощью MLP с одним скрытым слоем. Итак, наша модель будет иметь входной слой, один скрытый слой и выходной слой. Наша модель будет выглядеть примерно так, как на изображении 5:

Входные данные

Как объяснялось ранее, модели глубокого обучения используют математические инструменты для обработки входных данных. Итак, нам нужен входной слой для представления данных в виде чисел. Во многих приложениях мы получаем данные в других формах, таких как входные изображения, строки и т. Д. Нам нужно найти методы для их представления в виде чисел, например. для изображений мы можем использовать значения RGB каждого пикселя изображения, для текстовых строк мы можем сопоставить каждое слово с предопределенным словарем. Во входных данных нам нужно сосредоточить внимание на двух основных аспектах:

  1. Количество функций: входные данные для модели обучения могут иметь только одну функцию, которая влияет на результат, например нам дан набор зеленых и красных шаров, и мы хотим, чтобы наша модель разделяла их, вводя отдельные классы. Здесь нам нужна только одна характеристика для этой задачи - цвет мяча. Но в большинстве случаев вывод зависит от нескольких функций ввода, например. распознавание лиц или идентификация объекта в цветном изображении учитывает значения RGB, связанные с каждым пикселем.
  2. Количество примеров: для каждой проблемы нам придется кормить нашу сеть несколькими входными примерами, чтобы ее можно было обобщить по проблемному пространству. например если мы хотим разработать модель, которая идентифицирует кошек, нам потребуются тысячи изображений кошек в разных средах, позах, изображения разных пород кошек.

Входные данные представлены в виде матрицы, в которой строки представляют примеры, а столбцы представляют функции. Итак, если у нас есть, скажем, m примеров и n функций, тогда у нас будет матрица m x n в качестве входных данных.

В нашем примере X-OR у нас есть четыре примера и две функции, поэтому наш вход представляет собой матрицу 4 x 2 [Ref. изображение 6].

В Keras мы определяем наш ввод и ожидаемый вывод с помощью следующих строк кода:

x = np.array ([[0,0], [0,1], [1,0], [1,1]])

y = np.array ([0,1,1,0])

Выход

В зависимости от рассматриваемой проблемы мы ожидаем различных видов вывода, например для задачи распознавания кошек мы ожидаем, что система выдаст Yes или No [1 или 0] для cat или not cat соответственно. Такие задачи называются проблемой классификации двух классов. У нас есть только один результат для одного примера. Тогда у нас могут быть проблемы классификации нескольких классов, в которых входные данные являются распределением по нескольким классам, например. скажем, у нас есть шары 4 разных цветов, и предполагается, что модель помещает новый мяч, указанный в качестве входных данных, в один из 4 классов. Некоторые сложные задачи, такие как языковой перевод, создание текстовой сводки, имеют сложное пространство вывода, которое мы не будем рассматривать в этой статье. Функция активации в выходном слое выбирается на основе выходного пространства. Для задачи бинарной классификации активация сигмоида является правильным выбором, в то время как для классификации на несколько классов softmax является наиболее популярным выбором.

В нашей задаче X-OR выходное значение равно 0 или 1 для каждой входной выборки. Итак, это проблема двухклассной или бинарной классификации. Мы будем использовать двоичную кросс-энтропию вместе с сигмоидной функцией активации на выходном слое [ссылка на изображение 6].

В Keras мы определяем наш выходной слой следующим образом:

model.add (Dense (units = 1, activate = "sigmoid"))

Скрытые юниты:

Сеть глубокого обучения может иметь несколько скрытых единиц. Цель скрытых модулей - изучить некоторые скрытые функции или представление входных данных, которые в конечном итоге помогают в решении возникшей проблемы. Например, в случае распознавания кошки скрытые слои могут сначала найти края, второй скрытый слой может идентифицировать части тела, а затем третий скрытый слой может сделать прогноз, кошка это или нет.

Как объяснялось, мы используем MLP только с одним скрытым слоем. Это неглубокая сеть, и мы ожидаем, что скрытый слой преобразует входной сигнал X-OR из двумерной плоскости в другую форму, где мы сможем найти разделяющую плоскость, соответствующую нашему ожиданию для вывода X-OR. Мы будем использовать функцию активации ReLu в нашем скрытом слое для преобразования входных данных. Одно из таких преобразований показано на рисунке 7 [наша модель может предсказать другое преобразование]:

Следующая строка кода реализует наш предполагаемый скрытый модуль в Keras:

model.add (Dense (units = 2, Activation = ”relu”, input_dim = 2))

Скрытый слой состоит из 2 единиц и использует ReLu в качестве активации. Вход в скрытый модуль - это 4 примера, каждый из которых имеет 2 функции. т.е. матрица 4x2. Следовательно, размеры связанной весовой матрицы будут 2x2.

Веса и предубеждения

Все входные и скрытые слои в нейронных сетях имеют связанные веса и смещения. Эти веса и смещения являются значениями, которые перемещают границу решения в пространстве решений для правильной классификации входных данных [ref. изображение 4]. Веса обычно инициализируются случайным образом, и все смещения равны нулю.

Для, значения X-OR для начальных весов и смещений следующие [устанавливаются случайным образом реализацией Keras во время моего испытания, ваша система может назначать разные случайные значения]. Мы можем получить значение веса в keras, используя функцию model.get_weights ().

Веса скрытого слоя: массив ([[0,6537529, -1,0085169], [0,11241519, 0,36006725]], dtype = float32)

Смещение скрытого слоя: массив ([0., 0.], dtype = float32)

Веса выходного слоя: массив ([[- 0,38399053], [-0,0387609]], dtype = float32)

Смещение выходного уровня: массив ([0.], dtype = float32)]

Стратегия обучения

Чтобы обучение происходило, нам нужно обучить нашу модель с помощью образцов пар ввода / вывода, такое обучение называется обучением с учителем. Подход к обучению с учителем дал потрясающий результат в глубоком обучении при применении к различным задачам, таким как распознавание лиц, идентификация объектов, задачи НЛП. Большинство практически применяемых моделей глубокого обучения в таких задачах, как робототехника, автомобилестроение и т. Д., Основаны только на подходе к обучению с учителем. Другие подходы - это обучение без учителя и обучение с подкреплением. Мы будем придерживаться только контролируемого подхода.

Мы также используем подход к обучению с учителем для решения X-OR с использованием нейронной сети.

Функция потерь и функция стоимости

Чтобы система могла обобщать пространство ввода и позволяла точно прогнозировать новые варианты использования, нам необходимо обучить модель с доступными входными данными. Во время обучения мы прогнозируем выходные данные модели для различных входных данных и сравниваем прогнозируемые выходные данные с фактическими выходными данными в нашем обучающем наборе. Разница в фактическом и прогнозируемом выходе называется потерями по сравнению с этим входом. Суммирование потерь по всем входам называется функцией затрат. Выбор функций потерь и затрат зависит от того, на какой результат мы нацелены. Для классификации используется кросс-энтропийная функция стоимости. В Keras у нас есть функция затрат двоичной перекрестной энтропии для двоичной классификации и функция перекрестной энтропии по категориям для классификации нескольких классов.

Скомпилируем нашу модель в Keras следующим образом:

model.compile (loss = ’binary_crossentropy’, optimizer = ’adam’, metrics = [‘precision’])

Обратное распространение

Цель обучения - минимизировать функцию затрат. Это достигается с помощью алгоритма обратного распространения. Алгоритм обратного распространения является важной вехой в нейронных сетях. Таким образом, обратное распространение позволяет градиентам распространяться по сети в обратном направлении, а затем они используются для корректировки весов и смещений, чтобы переместить пространство решений в направлении уменьшения функции стоимости. Вот ссылка на Википедию, чтобы узнать больше об алгоритме обратного распространения: https://en.wikipedia.org/wiki/Backpropagation

Обучение керасу начинается со следующей строчки:

model.fit (x, y, epochs = 1000, batch_size = 4)

Мы выполняем 1000 итераций, чтобы подогнать модель к заданным данным. Размер пакета составляет 4, то есть полный набор данных, так как наш набор данных очень мал. На практике мы используем очень большие наборы данных, и тогда определение размера пакета становится важным для применения стохастического градиентного спуска [sgd].

Полный код Keras для решения XOR

импортировать numpy как np
из keras.layers import Dense
из keras.models import Sequential

model = Sequential ()

model.add (Dense (units = 2, activate = ’relu’, input_dim = 2))
model.add (Dense (units = 1, activate = ’sigmoid’))

model.compile (loss = ’binary_crossentropy’, optimizer = ’adam’, metrics = [‘precision’])

print (model.summary ())
print (model.get_weights ())

x = np.array ([[0., 0.], [0., 1.], [1., 0.], [1., 1.]])
y = np .array ([0., 1., 1., 0.])

model.fit (x, y, epochs = 1000, batch_size = 4)

print (model.get_weights ())

print (model.predict (x, batch_size = 4))

Выходы модели после обучения

Веса скрытых слоев: array ([[- 1.68221831, 0.75817555],
[1.68205309, -0.75822848]], dtype = float32)

Смещение скрытого слоя: array ([-4.67257014e-05, -4.66354031e-05], dtype = float32)

Веса выходного слоя: array ([[1.10278344],
[1.97492659]], dtype = float32)

Смещение выходного уровня: array ([- 0,48494098], dtype = float32)

Прогноз для x = [[0,0], [0,1], [1,0], [1,1]]

[[ 0.38107592]
[ 0.71518195]
[ 0.61200684]
[ 0.38105565]]

значения ‹0,5 отображаются в 0, а значения› 0,5 отображаются в 1. Следовательно, наша модель успешно решила проблему X-OR.

Повышение производительности нейронной сети:

Мы начнем обсуждение улучшения производительности в отношении следующих компонентов:

  1. Вход
  2. Выход
  3. Функция активации
  4. Инициализация весов
  5. Функция потерь
  6. Функция оптимизатора

Вход

Входные данные в нашем примере XOR:

x = np.array ([[0., 0.], [0., 1.], [1., 0.], [1., 1.]])

В глубоком обучении на уровне ввода применяется стратегия оптимизации - Нормализация. Вы можете обратиться к следующему видео, чтобы понять концепцию нормализации: https://www.youtube.com/watch?v=FDCfw-YqWTE

Ввод в случае XOR прост. Обе функции находятся в одном диапазоне, поэтому нормализовать этот ввод не требуется.

В некоторых практических случаях, например, при сборе отзывов о товарах в Интернете для различных параметров, и если параметры являются необязательными полями, мы можем получить некоторые недостающие входные значения. В таком случае мы можем использовать различные подходы, такие как установка отсутствующего значения на наиболее часто встречающееся значение параметра или установка его на среднее значение. Один интересный подход может заключаться в использовании нейронной сети в обратном порядке для заполнения недостающих значений параметров.

Выход

Вывод в нашем примере XOR:

y = np.array ([0., 1., 1., 0.])

Это снова очень простые данные, и они тоже полные.

Но, как и в случае с входными параметрами, для многих практических задач доступные нам выходные данные могут иметь пропущенные значения для некоторых заданных входов. И с этим можно было бы справиться теми же подходами, которые описаны выше.

Функция активации

Активация, используемая в нашей настоящей модели, - это «relu» для скрытого слоя и «sigmoid» для выходного слоя. Выбор кажется хорошим для решения этой проблемы, а также позволяет легко найти решение.

model.add (Dense (units = 2, activate = ’relu’, input_dim = 2))
model.add (Dense (units = 1, activate = ’sigmoid’))

Но при многократных попытках с таким выбором функции активации я заметил, что иногда повторная активация может вызвать хорошо известную проблему умирающего ReLu. Это происходит, когда блоки ReLu постоянно получают отрицательные значения на входе, и в результате на выходе всегда 0. Поскольку градиент 0 также будет равен 0, это останавливает процесс обучения сети. Подробнее о смерти ReLu вы можете прочитать в следующей статье https://medium.com/tinymind/a-practical-guide-to-relu-b83ca804f1f7

Существуют различные варианты ReLu для решения проблемы смерти ReLu, поэтому я заменил «relu» на один из его вариантов под названием «LeakyReLu», чтобы решить эту проблему. Сделать это в керасе можно следующим образом:

from keras.layers import LeakyReLU
act = LeakyReLU (alpha = 0.3)

и измените скрытый слой следующим образом:

model.add (Dense (units = 2, Activation = act, input_dim = 2))

Это увеличивает производительность обучения модели, и в этом случае сходимость выполняется быстрее с LeakyReLU.

Инициализация веса

Инициализация веса - важный аспект архитектуры нейронной сети.

Один простой подход состоит в том, чтобы изначально установить все веса равными 0, но в этом случае сеть будет вести себя как линейная модель, поскольку градиент потерь относительно. все веса будут одинаковыми на каждом слое соответственно. Это сделает сеть симметричной, и, таким образом, нейронная сеть потеряет свои преимущества, связанные с возможностью отображать нелинейность, и будет вести себя во многом как линейная модель.

Итак, веса инициализируются случайными значениями. Существуют различные схемы случайной инициализации весов. В Keras плотные слои по умолчанию используют случайный инициализатор glorot_uniform, он также называется нормальным инициализатором Xavier.

Для получения дополнительной информации об инициализаторах веса, вы можете проверить следующую документацию keras относительно инициализаторов https://keras.io/initializers/

В нашем коде мы использовали только этот инициализатор по умолчанию, который нам подходит.

Функция потерь

Выбор правильной функции потерь очень важен, при выборе функции потерь следует учитывать следующие моменты.

  1. Эффективное измерение потерь, то есть расстояния между фактическим и прогнозируемым значением
  2. Дифференцируемость при использовании градиентного спуска

Выбор функции потерь обычно зависит от решаемой задачи. Ниже приведены несколько примеров функций потерь, соответствующих конкретному классу задач.

  1. Классификация- ›Перекрестная энтропия
  2. Линейная регрессия- ›Среднеквадратичная ошибка

Keras предоставляет функции потерь binary_crossentropy и category_crossentropy соответственно для двоичной и многоклассовой классификации. Оформить заказ на все функции потери, поддерживаемые keras, можно по адресу https://keras.io/losses/.

Поскольку наша проблема XOR является проблемой двоичной классификации, мы используем потерю binary_crossentropy.

Функция оптимизатора

Оптимизаторы в основном - это функции, которые используют потери, вычисленные функциями потерь, и обновляют весовые параметры с использованием обратного распространения, чтобы минимизировать потери при различных итерациях. Цель состоит в том, чтобы приблизиться к глобальным минимумам функции потерь. Градиентный спуск - старейшая из стратегий оптимизации, используемых в нейронных сетях. Многие из его вариантов и расширенные функции оптимизации теперь доступны, некоторые из самых популярных когда-то были

  1. Стохастический градиентный спуск [sgd]
  2. Адаград
  3. Adamax
  4. RMSprop
  5. Адам

SGD хорошо работает для неглубоких сетей, и для нашего примера XOR мы можем использовать sgd. Другие - более продвинутые оптимизаторы, например RMSprop хорошо работает в рекуррентных нейронных сетях. Выбор подходящей стратегии оптимизации - это вопрос опыта, личных предпочтений и сравнения. Keras по умолчанию использует оптимизатор «adam», поэтому мы также использовали его в нашем решении XOR, и он хорошо работает для нас.

Поскольку наш пример для этого поста представляет собой довольно простую проблему, нам не нужно вносить много изменений в нашу исходную модель, за исключением использования LeakyReLU вместо функции ReLU. Поскольку многие практические проблемы мы можем напрямую ссылаться на отраслевые стандарты или общепринятые практики для достижения хороших результатов.

P.S. Я начал вести блог совсем недавно и хотел бы услышать отзывы сообщества, чтобы улучшить себя.