Решение базового математического уравнения с использованием RNN [с примером кода]
Опубликовано: 2020-12-07Если жизнь дает вам RNN, сделайте калькулятор
Рекуррентная нейронная сеть — это одна из классических искусственных нейронных сетей, в которой связи между узлами образуют последовательный ориентированный граф. RNN известны такими приложениями, как распознавание речи, распознавание рукописного ввода и т. Д., Из-за их внутренней памяти состояний для обработки последовательностей переменной длины.
RNN далее подразделяются на два типа. Первый представляет собой конечный импульс, нейронная сеть которого представляет собой направленный ациклический граф, в котором один узел может быть соединен с одним или несколькими узлами, находящимися впереди, без видимого цикла в сети. Другой — бесконечный импульс, нейронная сеть которого представляет собой направленный циклический граф, который нельзя развернуть в нейронную сеть прямого распространения.
Оглавление
Что мы собираемся делать?
Давайте построим модель, которая предсказывает вывод арифметического выражения. Например, если я даю ввод «11+88», то модель должна предсказать следующее слово в последовательности как «99». Вход и выход представляют собой последовательность символов, поскольку RNN имеет дело с последовательными данными.
Теперь проектирование архитектуры модели выглядит простой задачей по сравнению со сбором наборов данных. Генерация данных или сбор набора данных — сложная задача, потому что модели искусственного интеллекта, нуждающиеся в данных, требуют достаточного количества данных для приемлемой точности.
Таким образом, эту модель можно реализовать за 6 основных шагов:

- Генерация данных
- Построение модели
- Векторизация и де-векторизация данных
- Создание набора данных
- Обучение модели
- Тестирование модели
Прежде чем мы углубимся в реализацию модели, давайте просто импортируем все необходимые библиотеки.
| импортировать numpy как np импортировать тензорный поток как tf из tensorflow.keras.models импортировать последовательно из tensorflow.keras.layers импортировать Dense, Dropout, SimpleRNN, RepeatVector, TimeDistributed из tensorflow.keras.callbacks импортировать EarlyStopping, LambdaCallback цветной импорт из termcolor |
1. Генерация данных
Давайте определим строку char, содержащую все символы, необходимые для написания основного арифметического уравнения. Итак, строка состоит из всех символов от 0 до 9 и всех арифметических операторов, таких как /, *, +, -, .(десятичный).
Мы не можем напрямую передавать числовые данные в нашу модель, нам нужно передавать данные в виде тензоров. Преобразование строки в данных в вектор с горячим кодированием даст нам оптимизированную производительность модели. Вектор с горячим кодированием представляет собой массив с длиной, равной длине нашей строки char, каждый вектор с горячим кодированием имеет единицы только в соответствующем индексе символа, присутствующего в каждой строке.
Например, предположим, что наша строка символов — «0123456789», и если мы хотим закодировать строку, подобную «12», то однократный вектор будет [ [0,1,0,0,0,0,0,0 ,0,0], [0,0,1,0,0,0,0,0,0,0]]. Для этого нам нужно создать два словаря с одним индексом в качестве ключей и символов в качестве значений, а другой - наоборот.
| char_string = ' 0123456789/*+-. ' num_chars = длина (char_string) character_to_index = dict ((c, i) для i, c в перечислении (char_string)) index_to_character = dict ((i, c) для i, c в перечислении (char_string)) |
Теперь давайте напишем функцию, которая возвращает случайное арифметическое уравнение вместе с результатом этого уравнения.
| деф деление (н, д): вернуть n / d , если d != 0 иначе 0 определение генератора данных (): random1 = np.random.randint (низкий = 0 , высокий = 100 ) random2 = np.random.randint (низкий = 0 , высокий = 100 ) op = np.random.randint (низкий = 0 , высокий = 4 ) если оп == 1 : ариф = ул (случайный1) + ' + ' + ул (случайный2) рез = ул (случайный1 + случайный2) Элиф оп == 1 : ариф = ул (случайный1) + ' - ' + ул (случайный2) res = str (random1 – random2) Элиф оп == 2 : ариф = ул (случайный1) + ' * ' + ул (случайный2) рез = ул (случайный1 * случайный2) еще : ариф = ул (случайный1) + ' / ' + ул (случайный2) res = str ( раунд (деление (random1, random2), 2 )) вернуть ариф, рез |
Читайте также: Интересные идеи проекта нейронной сети
2. Построение модели
Модель будет иметь энкодер и декодер. Кодер представляет собой простую модель RNN с формой ввода как (None,num_chars) и 128 скрытых единиц, причина, по которой мы выбираем скрытые единицы как 32, 64, 128 и т. д., заключается в лучшей производительности ЦП или графического процессора со скрытыми единицами в качестве степени 2.
Наш кодировщик будет полностью подключенной сетью, и его выходные данные будут возвращаться обратно в сеть, именно так работает RNN. Слой RNN по умолчанию использует активацию tanh, мы не собираемся его менять, потому что он лучше всего подходит для кодировщика. Выход этого слоя будет одним вектором, и для получения единого вектора всего вывода мы будем использовать слой RepeatVector() с требуемым количеством раз в качестве параметра.
Теперь выходной вектор будет иметь сущность заданного ввода, и этот вектор будет подаваться в декодер.
Декодер состоит из простого уровня RNN, и он будет генерировать выходную последовательность, поскольку нам нужно, чтобы уровень RNN возвращал предсказанную последовательность, которую мы собираемся отметить для «return_sequences» как True. Присвоив «return_sequences» значение «Истина», уровень RNN будет возвращать прогнозируемую последовательность для каждого временного шага (от многих ко многим RNN).
Выходные данные этого слоя RNN передаются в плотный слой с количеством скрытых единиц «num_chars», и мы будем использовать активацию softmax, поскольку нам нужна вероятность каждого символа. Прежде чем мы развернем плотный слой, нам нужно сократить этот слой до слоя TimeDistributed, потому что нам нужно развернуть плотный слой для вывода каждого временного шага.
| скрытые_единицы = 128 макс_время_шагов = 5 # мы жестко кодируем вывод, чтобы он состоял из 5 символов модель защиты (): модель = Последовательный() model.add(SimpleRNN(hidden_units, input_shape = ( None , num_chars))) model.add(RepeatVector(max_time_steps)) model.add (SimpleRNN (hidden_units, return_sequences = True )) model.add(TimeDistributed(Dense(num_chars, активация = ' softmax ' )) модель возврата модель = модель() модель.резюме() model.compile (потеря = ' categorical_crossentropy ' , оптимизатор = ' адам ' , метрика = [ ' точность ' ]) |

Архитектура модели будет такой, как показано выше.
Обязательно прочтите: учебник по нейронной сети
3. Векторизация и развекторизация данных
Давайте определим функции для векторизации и де-векторизации данных.
Вот функция векторизации арифметического выражения и результата вместе.
| def vectorize (арифметика, разрешение): x = np.zeros ((max_time_steps, num_chars)) y = np.zeros ((max_time_steps, num_chars)) ![]() x_remaining = max_time_steps – len (арифметическое) y_remaining = max_time_steps – длина (разрешение) для i, c в перечислении (арифм.): x[x_оставшееся + i, символ_к_индексу[c]] = 1 для i в диапазоне (x_remaining): х[i, символ_в_индекс[ ' 0 ' ]] = 1 для i, c в перечислении (рез): y[y_оставшееся + i, символ_к_индексу[c]] = 1 для i в диапазоне (y_remaining): y[i, символ_в_индекс[ ' 0 ' ]] = 1 вернуть х, у |
Точно так же здесь функция для де-векторизации строки. Поскольку на выходе мы получаем вектор вероятностей, мы будем использовать np.argmax() для выбора символа с наибольшей вероятностью. Теперь словарь index_to_character используется для отслеживания символа по этому индексу.
| def devectorize (ввод): res = [index_to_character[np.argmax(vec)] для i, vec в перечислении ( ввод )] вернуть ' ' .join(res) |
Теперь ограничение, которое мы имеем с функцией devectorize, заключается в том, что она дополняет конечные символы нулями. Например, если входной вектор равен ('1-20', '-19'), то девекторизованный вывод будет ('01-20', '00-19'). Нам нужно позаботиться об этих дополнительных нулях. Давайте напишем функцию для удаления строки.
| деф зачистки (ввод): флаг = Ложь вывод = ' ' для c на входе : если не флаг и c == ' 0 ' : Продолжать если c == ' + ' или c == ' – ' или c == ' * ' или c == ' / ' или c == ' . ' : флаг = Ложь еще : флаг = Истина выход += с возвратный вывод |
4. Создание набора данных
Теперь, когда мы закончили с определением функции для генерации данных, давайте воспользуемся этой функцией и создадим набор данных со многими такими парами (арифметическое выражение, результат).
| def create_dataset (num_equations): x_train = np.zeros((num_equations, max_time_steps, num_chars)) y_train = np.zeros((num_equations, max_time_steps, num_chars)) для i в диапазоне (num_equations): е, л = генерация данных () х, у = векторизовать (е, л) х_поезд [я] = х у_поезд [я] = у вернуть x_train, y_train |
5. Обучение модели
Давайте создадим набор данных из 50 000 образцов, что является достаточным количеством для обучения нашей модели голода данных, мы будем использовать 25% этих данных для проверки. Также давайте создадим обратный вызов для интеллектуального прерывания обучения, если точность остается неизменной в течение 8 эпох. Этого можно добиться, установив параметр терпения на 8.

| x_train, y_train = create_dataset( 50000 ) simple_logger = LambdaCallback( on_epoch_end = lambda e, l: print ( ' {:.2f} ' .format (l [ ' val_accuracy ' ]), end = ' _ ' ) ) Early_stopping = EarlyStopping (монитор = ' val_loss ' , терпение = 8 ) model.fit(x_train, y_train, эпохи = 100 , validation_split = 0,25 , подробный = 0 , callbacks = [simple_logger, Early_Stopping]) |
6. Тестирование модели
Теперь давайте проверим нашу модель, создав набор данных размером 30.
| x_test, y_test = create_dataset (num_equations = 20 ) предс = модель.прогноз(x_test) полный_seq_acc = 0 для i, пред в перечислении (пред): pred_str = удаление (девекторизация (пред)) y_test_str = зачистка (devectorize (y_test [i])) x_test_str = зачистка (devectorize (x_test [i])) col = ' зеленый ', если pred_str == y_test_str иначе ' красный ' full_seq_acc += 1 / длина (предыдущие) * целое число (пред_стр == y_test_str ) outstring = ' Ввод: {}, вывод: {}, прогноз: {} ' .format(x_test_str, y_test_str, pred_str) печать (цветная (outstring, col)) print ( ' \n Полная точность последовательности: {:.3f} % ' .format( 100 * full_seq_acc)) |
Вывод будет следующим

Мы видим, что точность здесь немного плохая, в любом случае мы можем оптимизировать ее, настроив несколько гиперпараметров, таких как количество скрытых единиц, разделение проверки, количество эпох и т. д.
Заключение
Мы поняли основной рабочий процесс RNN, поняли, что RNN лучше всего подходят для последовательных данных, сгенерировали набор данных случайных арифметических уравнений, разработали последовательную модель для прогнозирования вывода базового арифметического выражения, обучили эту модель с набором данных, который мы создали и, наконец, протестировали эту модель с небольшим набором данных, который модель никогда раньше не видела.
Если вам интересно узнать больше о RNN, машинном обучении, ознакомьтесь с дипломом PG IIIT-B и upGrad в области машинного обучения и искусственного интеллекта, который предназначен для работающих профессионалов и предлагает более 450 часов тщательного обучения, более 30 тематических исследований и заданий, Статус выпускника IIIT-B, более 5 практических практических проектов и помощь в трудоустройстве в ведущих фирмах.
Какие существуют типы нейронных сетей в машинном обучении?
В машинном обучении искусственные нейронные сети — это в основном вычислительные модели, которые были разработаны так, чтобы напоминать человеческий мозг. Существуют различные виды искусственных нейронных сетей, которые машинное обучение использует на основе математических вычислений, которые необходимо выполнить. Эти нейронные сети представляют собой подмножество различных методов машинного обучения, которые изучают данные по-разному. Некоторые из наиболее широко используемых типов нейронных сетей: рекуррентная нейронная сеть с долговременной кратковременной памятью, нейронная сеть с прямой связью, искусственный нейрон, нейронная сеть с радиальной базисной функцией, самоорганизующаяся нейронная сеть Кохонена, сверточная нейронная сеть и модульная нейронная сеть. среди прочих.
Каковы преимущества рекуррентной нейронной сети?
Рекуррентные нейронные сети являются одними из наиболее часто используемых искусственных нейронных сетей в глубоком и машинном обучении. В этом типе модели нейронной сети результат, полученный на предыдущем шаге, подается в качестве входных данных для последующего шага. Рекуррентная нейронная сеть имеет несколько преимуществ, например, она может сохранять каждый бит информации с течением времени, включая предыдущие входные данные, что делает ее идеальной для прогнозирования временных рядов. Этот тип является лучшим примером долго-короткой памяти. Кроме того, рекуррентные нейронные сети обеспечивают конструктивное соседство пикселей с помощью сверточных слоев.
Как нейронные сети используются в реальных приложениях?
Искусственные нейронные сети — неотъемлемая часть глубокого обучения, которое опять-таки является сверхспециализированной ветвью машинного обучения и искусственного интеллекта. Нейронные сети используются в разных отраслях для достижения различных критических целей. Некоторые из наиболее интересных реальных приложений искусственных нейронных сетей включают прогнозирование фондового рынка, распознавание лиц, высокопроизводительное автопилотирование и диагностику неисправностей в аэрокосмической отрасли, анализ вооруженных нападений и определение местоположения объектов в оборонном секторе, обработку изображений, поиск лекарств и выявление заболеваний в секторе здравоохранения, проверка подписи, анализ почерка, прогнозирование погоды и прогнозирование тенденций в социальных сетях, среди прочего.

