Популярные нейросетевые архитектуры Автор: Александр Вежневец (vezhnick@mtu.ru) Содержание. 1. 2. 3. 4. 5. Введение. Модель формального кибернетического нейрона. Данные. Обучение. Классические нейросетевые архитектуры. 1. Общие замечания. 2. Персептрон Розенблата. 3. Многослойный Персептрон. 4. Рекурсивные сети. 6. Библиография. Введение. Нейронные сети применяются для решения задач классификации или кластеризации многомерных данных. Основная идея лежащая в основе нейронных сетей - это последовательное преобразование сигнала, параллельно работающими элементарными функциональными элементами. Основой нейронной сети является нейрон. Нейрон состоит из 3 логических блоков: входы, функция преобразования, выход. На каждый вариант входа (вектор) функция преобразования нейрона вырабатывает определённый сигнал (выход) (обычно скаляр), и передает его на входы другим нейронам сети. Подавая на входы некоторым нейронам сигналы извне, и отметив выходы части нейронов, как выходы сети в целом, мы получим систему осуществляющею отображение Rn → Rk, где n - размерность входа (информации из вне), а k - размерность выхода. Нейронные сети различаются функцией преобразования в нейронах, внутренней архитектурой связей между нейронами и методами настройки (обучения). Для того, чтобы нейросеть выполняла желаемое отображение, требуется особым образом настроить функции преобразования нейронов и внутреннюю архитектуру связей. Чаще всего архитектура связей выбирается заранее из известных моделей и остаётся неизменной во время работы и настройки сети; настраиваемой же является функция преобразование. Зачастую применяется следующий подход построения функции преобразования: все элементы вектора входа суммируются с некоторыми весами (синаптические веса), а далее сумма преобразуется нелинейной функцией (самый простой случай порог) и результат работы данной функции и есть выход нейрона. В процессе настройке сети (обучение) мы подстраиваем только синаптические веса у нейронов. Для каждой нейросетевой архитектуры существуют различные методы обучения. Основным плюсом нейросетей является возможность решения широкого класса задач алгоритмически не разрешимых или задач с нечёткими условиями. Отметим наиболее интересные нейросетевые архитектуры и результаты их применения: 1. Модель Хопфильда с ассоциативной памятью. 2. Самоорганизующиеся карты Кохеннена, обладающие возможностью самостоятельно выявлять закономерности в данных а разбивать входные данные на кластеры. 3. Рекурсивные сети Элмана, способные обрабатывать последовательности векторов. 4. Вероятностные сети, аппроксимирующие Байесовские классификаторы с любой степенью точности. Далее в статье мы введем общую терминологию и сформулируем основные понятия, затем последовательно разберём несколько нейросетевых архитектур. Модель формального кибернетического нейрона. Формальный нейрон состоит из 3 логических блоков: входы, функция преобразования, выход. Рассмотрим подробнее блок функции преобразования. Figure 1. Модель формального нейрона. Пунктирной рамкой выделен блок функции преобразования. Блок функции преобразования можно так же разделить на части: синаптические веса, блок суммирования, функция нелинейного преобразования. Итак, опишем алгоритм работы блока функции преобразования: 1. Входные сигналы умножаются на коэффициенты (синаптические веса или просто веса). Для каждого входа - свой коэффициент. 2. Умноженные на веса входы суммируются. 3. Результат суммирования подаётся на вход функции преобразования. Обычно . 4. Результат функции подаётся на выход. В качестве функции преобразование обычно используются следующие: • простой порог, • ленейно-пороговая функция, • сигмоида, ,где Θ - некий фиксированный порог. Следует заметить, что это не полный список, а лишь набор самых популярных вариантов. Данная модель формально кибернетического нейрона, была предложена Мак-каллоком и Питтсом в 1943 году и встречается во многих нейросетях, но не является догмой. Существуют нейронные сети и с другими моделями нейронов: о них подробнее мы поговорим ниже. Данные. Нейронная сеть, как уже говорилось, осуществляет некоторое отображение. Математически, нейросеть работает с векторами, осуществляя отображение из одного пространства в другое, однако в отношение нейросетей принято говорить "образы" или "сигналы". Входные данные принято обычно называть "входные образами" или "входные сигналы", а выходные соответственно - "выходные образы" или "выходные сигналы",. Такая терминология связана с историей возникновения и областью применения нейросетей. Обучение. Как мы уже отмечали, для того чтобы нейросеть осуществляла требуемое отображение, т.е. на каждый вектор входных данных создавала требуемый вектор на выходе, требуется её настроить. Обычно процесс настройки называется "обучением" (далее мы всегда будем говорить обучение). Существуют два метода обучения: с наставником и на основе самоорганизации. Рассмотрим общий для всех сетей принцип обучения с наставником. Пускай имеется некоторый набор пар следующего вида: входной вектор - выход сети (т.е. нам известно как точно должна работать сеть на некотором множестве входных векторов). Такое множество пар называют "обучающая выборка" (далее мы будем использовать именно этот термин). Процесс обучения выглядит следующим образом: 1. 2. 3. 4. Предадим синаптическим весам некоторые начальные значения. Предъявим сети вектор из обучающей выборки. Вычислим отклонения выхода сети от желаемого. По некоторому алгоритму (зависящему от конкретной архитектуры) подстроим синаптические веса, учитывая отклонение полученное на предыдущем шаге. 5. Повторим шаги 2-4 пока сеть не станет выдавать ожидаемый выход на векторах из обучающей выборки или пока отклонение не станет ниже некоторого порога. Другими словами, подстроим веса сети так, чтобы сеть работала с приемлемой точностью на известных данных. Идея метода состоит в предположении, что при достаточно репрезентативной обучающей выборки, более-менее равномерно покрывающей всё множество возможных входных векторов, обученная нейросеть будет выдавать правильный или близкий к правильному результат на векторах которым её не обучали. Отметим, что такое предположение вполне закономерно, ведь обученная сеть будет обрабатывать входные вектора схожим образом с векторами из обучающей выборки, следовательно если искомое преобразование в достаточной степени непрерывно и гладко, то результат должен быть вполне удовлетворительным. Самоорганизация - это свойство небольшого количества нейронных сетей. Под самоорганизацией подразумевается способность сети приспособиться осуществлять желаемое отображение самостоятельно в процессе работы - то есть без обучающей выборки. Обычно такие сети применяются к задачам кластеризации некоторого множества. Для этого метода обучения трудно сформулировать некий общий абстрактный алгоритм, т.к. обычно метод обучения очень сильно зависит от архитектуры конкретной сети. Далее, при описании конкретных архитектур, мы будем подробно говорить об алгоритмах обучения для каждой конкретной сети. Классические нейросетевые архитектуры. Общие замечания. В данной части мы поговорим о конкретных нейросетевых парадигмах, возникших на заре нейроинформатики. Именно эти сети стали основой для развития кибернетических нейронных сетей. В их основе лежат первые представления, полученные человеком о функционировании мозга. Несмотря ни на что, многие из этих сетей до сих пор успешно применяются на практике. Для описания любой нейронной сети нужно определить для неё следующие положения: • • • Модель формального нейрона (функция преобразования и т.д.) Структура связей нейронов сети Метод обучения сети В дальнейшем мы будем придерживаться именно такого плана изложения. Персептрон Розенблата. Простейшая нейросеть, представляющая в данный момент чисто историческую ценность. Хотя её практическая ценность сомнительна, мы опишем её, т.к. на её примере легко показать некоторые важные принципы. Модель нейрона: у персептрона есть два типа нейронов. Первый тип - нейроны рецепторы: они воспринимают на вход двоичный сигнал из окружающего мира и передают его дальше без искажений. Второй тип - ассоциативные нейроны: стандартные нейрон описанный нами выше с функцией преобразования: т.е. простым порогом. Структура связей персептрон состоит из двух слоёв независимых нейронов. Первый слой состоит из рецепторов, второй из ассоциативных нейронов. Каждый нейрон первого слоя соединен со всеми нейронами последующего, но между нейронами одного и того же слоя связи отсутствуют. В современной терминологии такая сеть называется однослойной - по количеству слоёв ассоциативных нейронов Отметим, что на входе и на выходе у персептрона - двоичные вектора, то есть персептрон осуществляет некоторое двоичное отображение (функцию). Действительными числами являются только веса связей соединяющих рецепторы и ассоциативный слой. Для j-ого нейрона сети определён вектор Vj. Таким образом персептрон определяется матрицей W размерности m x n, где Wij - вес связи i-ого рецептора с jым ассоциативным нейроном. Обучение персептрона происходит с учителем. Пускай есть обучающая выборка: xα - обучающий вектор, yα - ожидаемый ответ сети на xα. Тогда будем обучать персептрон следующим образом: 1. Начальными значениями элементов матрицы весов W(t=0) положим случайные неотрицательные числа. 2. Пусть на входной вектор xα сеть формирует выход 3. Вычислим ошибку , где 0<η<1. 4. Подстроим веса по следующей формуле: 5. Будем повторять шаги 2-4 пока на всех обучающих векторах не будет нулевой ошибки, или пока суммарная ошибка не будет меньше некоторого малого числа. Поясним смысл формулы в 4 пункте: идея заключается в коррекции весов нейрона, пропорционально внесённой им ошибке, а играет роль темпа обучения. Итак, мы установили как обучить персептрон некоторой двоичной функции. Возникает вопрос - любую ли двоичную функцию может осуществлять персептрон? Оказывается, что нет. Основным недостатком персептрона является, так называемая, линейная разделимость. Поясним на простом примере. Пускай у нас есть два рецептора и один ассоциативный нейрон. Такая сеть должна осуществлять двоичную функцию от двух аргументов. К таким функциям относятся многие основные функции алгебры логики, такие как логическое "и", "или", сложение по модулю 2. Проведём некоторые преобразования. Как известно выход данной сети где f - функция преобразования, x1 и x2 -входы, W1 и W2 - веса связей. Следовательно иными словами нейрон является линейным классификатором, т.е. разделяет пространство входных векторов(образов) на 2 класса гиперплоскостью, в нашем случае прямой x1W1 + x2W2 - Θ = 0. Как видно на картинке множества белых и чёрных точек нельзя разделить прямой. Одна из известных двоичных функций не представимых с помощью персептрона - исключающие "или" (сложение по модулю 2). Когда рецепторов больше двух, получим общее уравнение гиперплоскости в n мерном пространстве: . Так как в персептроне ассоциативные нейроны не зависят друг от друга, то в общем случае (n рецепторов, k ассоциативных нейронов), мы всё равно получим k линейных классификаторов. Этот недостаток и послужил причиной забвения персептрона. Многослойный Персептрон. Сразу после краха персептрона Розенблата начались попытки создать нейросеть без свойства линейной разделимости. Основной идеей являлось увеличение количества слоёв ассоциативных нейронов, однако долгое время не существовало алгоритма обучения таких сетей. Первым алгоритмом обучения многослойной нейросети был алгоритм обратного распространения ошибки (error back propagation). Итак опишем многослойный персептрон и методы его обучения. Модель нейрона претерпела изменения. Теперь нейроны рецепторы принимают на вход действительные числа (обычно от 0 до1), а ассоциативные нейроны используют сигмоидальную функцию преобразования Как видно из модели нейрона многослойный персептрон работает с действительными числами. Отметим несколько важных свойств функции преобразования. 1. Областью значений функции является интервал (0,1). 2. Функция бесконечное число раз непрерывно дифференцируема. 3. Её производная выражается только через неё саму: f' = f (1 - f) . Структура связей в многослойном персептроне весьма похожа на структуру классического персептрона Розенблата. Имеется один слой нейронов рецепторов и произвольное число слоёв ассоциативных нейронов. Нейроны одного и того же слоя друг с другом не связаны, и каждый нейрон связан со всеми нейронами последующего слоя (кроме последнего слоя - его выходы являются выходами сети в целом). На схеме изображена двухслойная нейросеть - хотя можно использовать произвольное число слоёв, но обычно используются два. Существует теорема о том, что для любой n-слойной сети (n>2), можно построить эквивалентную ей двухслойную сеть. На практике иногда используют больше двух слоёв - в некоторых случаях это может сократить суммарное число нейронов. В двухслойной сети первый слой ассоциативных нейронов обычно называют скрытым слоем, а второй - выходным. Как видно из архитектуры k-слойная нейросеть производит цепочку отображений Существует теорема утверждающая, что многослойная нейронная сеть может с любой заданной точностью приближать произвольную кусочно-непрерывную и ограниченную функцию (мы не будем приводить доказательство). Обучение многослойного персептрона происходит по схеме "обучение с наставником". Опишем самый популярный метод обучения многослойного персептрона - метод обратного распространения ошибки. Сначала изложим основную идею метода. Итак, мы хотим изменять веса связей нейронов . пропорционально их вкладу в ошибку. Для последнего слоя вычисление ошибки довольно очевидное действие, но как вычислить ошибку для предыдущих слоёв? Главной идеей метода обратного распространения ошибки является предположение, что ошибка распространяется по нейросети в обратном направлении (от выхода к входам). То есть вклад веса связи в ошибку пропорционален значению проходящего по связи сигнала и ошибке (дальнего по ходу сигнала) нейрона. Таким образом ошибка связи двух нейронов зависит от ошибки ближнего к выходу сети нейрона и прошедшего по связи сигнала. Ошибка как бы распространяется от выходов к входам - отсюда и название метода. Опишем его в точных математических терминах. Пускай у нас есть обучающая выборка из пар (Xα, Yα), α=1,2,..,p. Будем использовать для обучения метод градиентного спуска: 1. Пусть W - матрица весов связей нейронов скрытого слоя, V - матрица весов выходного слоя. Придадим им в начальный момент случайные значения 2. Пускай на входной образ Xα сеть вырабатывает выходной образ функционирует скрытый слой: . Запишем как и выходной слой: 3. В качестве функционала подлежащего минимизации методом градиентного спуска возьмём среднеквадратичное отклонение реального выхода сети от предполагаемого, то есть 4. Начнём с выходного слоя. Согласно методу градиентного спуска где h - темп обучения. Так как воспользовавшись правилами неявного дифференцирования получим Вычислим Используя свойство 3 сигмоидальной функции активации вычислим Так же очевидным является равенство Итак мы получили 5. Теперь перейдём к скрытому слою. Опять по методу градиентного спуска имеем: Как и на предыдущем шаге применяя формулы неявного дифференцирования и свойства сигмоды вычислим В формуле (*) для вычисления ошибки нейрона скрытого слоя и раскрывается главный смысл метода обратного распространения ошибки о котором мы говорили выше. 6. В случае наличия более двух слоёв к ним применяются все те же методы и принципы, мы не будем их описывать. 7. Далее, согласно концепции обучения с наставником, мы повторяем шаги 2-6 пока для всех обучающих образов суммарная ошибка не станет ниже некоторого фиксированного малого числа. Можно было заметить, что мы проводили все вычисления с параметром функции преобразования Θ = 0. Это было сделано для упрощения. Как же нам учесть его? Легко заметить, что параметр Θ можно заменить, так называемым, фиктивным входом x0 = -1 с весом W0 = Θ. Таким образом для любого нейрона выход равен Итак введя фиктивный вход, мы можем применить вышеописанный метод просто начиная все суммирование с нуля и учитывая в конце смысл W0. Сложность этого алгоритма линейная от числа нейронов, то есть метода являются: • • • . Главными недостатками Медленная сходимость (свойство метода градиентного спуска). В силу применения метода градиентного спуска, функционал среднеквадратичной ошибки минимизируется к локальному, а не к глобальному минимуму. В большинстве случаев этого достаточно, но если найденный локальный минимум недостаточен, то возможным выходом может быть попытка повторить обучение придав матрицам V и W другие значения на первом шаге. Подстраивая веса и минимизируя ошибку для одного из обучающих векторов, мы можем её увеличивать для другого. Поэтому метод может, вообще говоря, не сойтись. Однако, практика показала, что такие случаи крайне редки. После появления метода обратного распространения ошибки было придумано много других методов: стохастические, генетические и т.д. Всех их объединяет идея впервые использованная в методе обратного распространения ошибки: подход к обучению нейросети, как к задачи многомерной оптимизации. На сегодняшний день многослойный персептрон - одна из самых популярных и используемых нейросетей. Причин успеха немало. Одно из главных преимуществ многослойного персептрона, это возможность решать алгоритмически неразрешимые задачи или задачи, для которых алгоритмическое решение неизвестно, но для которых возможно составить репрезентативный набор примеров с известными решениями. Многослойный персептрон функционирует очень похоже на человека. При обучение нейросеть, за счёт своего внутреннего строения, выявляет закономерности в связи входных и выходных образов, тем самым как бы "обобщает" полученный на обучающей выборке опыт. В этой способности к обобщению и состоит основа привлекательности многослойного персептрона. Мы сами можем и не знать какова зависимость между входными и выходными образами, достаточно иметь большой набор векторов для которых известен ожидаемый выход. Вот небольшой список задач где успешно применялся многослойный персептрон: • • • • • Прогнозирование поведения рынка Распознавание речи Анализ изображений Экспертные системы И т.д. Рекурсивные сети. На практике нейросети зачастую применяются для обработки некоторых последовательностей: звуковых волн, видеопоследовательностей, данных с измерительных приборов и т.д. Для предъявления нейросети данные разбиваются на блоки и подаются нейросети. Такая модель, зачастую работает, но обладает недостатком - обычный многослойный персептрон рассматривает каждый блок независимо от другого, не учитывая возможную связь между ними. Для обработки последовательностей это может оказаться существенным недостатком. Рассмотрим нейросеть, специально приспособленную для обработки последовательностей рекурсивную сеть. В литературе их, зачастую, называют сетями Эльмана [2], однако, Эльман является автором лишь одной из моделей. Идея состоит в том, что бы приспособить двухслойный персептрон к обработке последовательностей. Модель нейрона такая же, как и в многослойном персептроне. Структура связей: любая рекурсивная сеть строится на основе двухслойного персептрона. В первых рекурсивных сетях главной идеей было дать сети видеть свой выходной образ на предыдущем шаге. У такой сети только часть рецепторов принимает сигналы из окружающего мира, на другие рецепторы приходит выходной образ из предыдущего момента времени. Что же происходит? Рассмотрим прохождение последовательности сигналов через сеть. Сигнал поступает на группу рецепторов соединённых с внешним миром и проходит в скрытый слой (будем считать, что на начальном этапе другие рецепторы неактивны). Преобразованный скрытым слоем сигнал пойдёт на выходной слой. Сигнал, пройдя через выходной слой, выйдет из сети, а его копия попадёт на задержку. Далее в сеть, на рецепторы, воспринимающие внешние сигналы, поступает второй образ, а на вторую группу рецепторов - выходной образ с предыдущего шага из задержки. Далее со всех рецепторов сигнал пойдёт в скрытый слой. Для скрытого слоя безразлична природа сигнала на второй группе рецепторов, поэтому он будет функционировать, как в обычном многослойном персептроне. Сигнал из скрытого слоя поступит в выходной. Переработанный выходным слоем, сигнал выйдет из сети, а его копия опять попадёт на задержку. И так далее. Следующим шагом было использование того же принципа, но сохранять не выходной образ, а выход скрытого слоя. Как видно из схемы у сети два входа для сигналов извне. Три нейрона в скрытом слое и три нейрона во входном слое, на которые с задержкой приходит копия результата работы скрытого слоя. Самым популярным является следующий подход: возьмём обычный двухслойный персептрон и выходы скрытого слоя, передав сигнал выходному слою, пустим через задержку опять на входы скрытого слоя, смешав их сигналом из окружающего мира. Поясним что же имеется ввиду. Что же происходит? Рассмотрим прохождение последовательности сигналов через сеть. Сигнал поступает на вход проходит в скрытый слой. Преобразованный скрытым слоем сигнал пойдёт на выходной слой, а его копия - на задержку. Сигнал, пройдя через выходной, слой выйдет из сети. Далее в сеть поступает второй сигнал. Поступив на входы он пойдёт на скрытый слой, просуммированный с сигналом, находящимся на задержки. После этого выход скрытого слоя пойдёт в выходной, а его копия опять сохранится в задержке. И так далее. Обычно, перед суммированием сигнал из задержки умножается на некоторый коэффициент W меньше единицы. Чем больше этот коэффициент, тем сильней влияние предыдущих сигналов на выход сети. Иногда между сигналом в задержке и входным сигналом берётся среднее арифметическое. Из структуры понятно, что количество нейронов скрытого слоя и количество входов (размерность входного образа) должны быть равны. Такой вариант рекурсивной сети реализован, например, в Neural Networks Toolbox в системе MatLab. Можно так же придумывать множество вариантов и комбинаций, но суть останется неизменной: результат работы одного из слоёв сети, в том или ином виде, подается на входы при обработке следующего сигнала. Сделаем несколько общих для всех рекурсивных нейросетей замечаний: • • • • Единицей обработки является не один образ, а последовательность. Нейросеть "помнит" начало обрабатываемой последовательности. Память, о каждом из образов, а следовательно и его влияние, затухает экспоненциально. Сеть сохраняет все свойства многослойного персептрона. Для первого элемента обрабатываемой последовательности все рекурсивные элементы предполагаются неактивными или принимают заранее предопределённое состояние. Обучение, несмотря на всю сложность структуры связей, обучение проводится, примерно, по той же схеме, что и для многослойного персептрона, притом схема одинакова для всех вариантов рекурсивной архитектуры. Основным отличием является, то что обучающая выборка теперь состоит не из отдельных образов, а из их последовательностей. Коротко опишем этот алгоритм. Итак, пускай у нас есть обучающая выборка: {Xα, Yα}; &alpha = 1,2,...,p, где n - число элементов в последовательности. n - может быть фиксированным для всех последовательностей в обучающей выборке, а может и зависеть от α.Придадим весам случайные значения и далее будем действовать по следующему алгоритму: 1. Возьмём некоторую последовательность {Xnα, Ynα} из обучающей выборки. 2. Для пары образов {X1α, Y1α}, проведём коррекцию весов с помощью алгоритма обратного распространения ошибки, считая задержку пустой (нулевой сигнал), заполнив все элементы задержки, согласно конкретной архитектуре связей. 3. Далее будем проводить коррекцию весов алгоритмом обратного распространения ошибки последовательно для всех остальных пар последовательности, каждый раз учитывая сигнал на задержке и заполняя её заново. 4. Очистив задержку повторим шаги 1-3 для последовательностей в обучающей выборке, пока суммарная ошибка не станет достаточно мала. Заметим, что каждый раз при оптимизации весов мы работаем с сетью, как с обычным многослойным персептроном (на картинках связи, изображенные пунктиром, не оптимизируются). Следует заметить, что в случае рекурсивных сетей мы будем использовать не сам градиент ошибки, а лишь его приближение. Почему так? При подсчёте ошибки мы не учитываем ошибку, внесённую из-за данных на задержки. Попытка учёта этой составляющей напрямую может привести к слишком глубокой рекурсии и т.д. Из-за этого обучение сходится медленнее и для качественного функционирования рекурсивной сети требуется, в общем случае, большее количество нейронов, чем для обычной. Однако эти недостатки перекрываются множеством достоинств: • • Способность обрабатывать последовательности образов, учитывая связь между элементами последовательности. Способность вырабатывать последовательности в ответ как на последовательности, так и на единичные образы (достаточно дополнить образ до последовательности нулевыми сигналами). • Высокая способность к обобщению, как показано в [3] она выше даже чем у обычного многослойного персептрона. Рекурсивные нейросети широко используются в: • • • Задачах обработки звука и речи. Анализе электронных схем. В различных задачах компьютерного зрения и обработки сигналов. Библиография: [1] С. Терехов. Лекции по теории и приложениям нейронных сетей. [2] J. L. ELMAN. Finding Structure in Time. COGNITIVE SCIENCE, 14, 179-211 (1990). [3] H. NINOMIYA, A SASAKI. A Study on Generalization Ability of 3-Layer Recurrent. Neural Networks. IJCNN '02. [4] T. Koskela, M. Lehtokangas, J. Saarinen, K. Kaski. Time Series Prediction with Multilayer Perceptron, FIR and Elman Neural Networks. [5] Е. Лисицин Radial Based Functions. Graphics and Media Journal. [6] J. Chao, M. Hoshino, T. Kitamura, T. Masuda. A MULTILAYER RBF NETWORK AND ITS SUPERVISED LEARNING. [7] M. Y. Mashor. Hybrid Training Algorithm for RBF Network. [8] A.G. Bors, I. Pitas. Optical Flow Estimation and Moving Object Segmentation Based on Median Radial Basis Function Network. [9] Da-chuan Cheng, Qin Pu, Kuo-sheng Cheng, Hans Burkhardt. Possibilistic Hopfield Neural Network on CT Brain Hemorrhage Image Segmentation. [10] H. C. C. Tan and L. C. De Silva. Human Activity Recognition by Head Movement using Elman Network and Neuro-Markovian Hybrids [11] Ling Li, Zhidong Deng, and Bo Zhang. A Fuzzy Elman Neural Network