Распознавание букв нейронные сети c. Быстрый способ распознавания текста

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

Пример 3.11. Распознавание букв. В системе MatLab предусмотрена специальная функция

>> = prprob;

Эта функция возвращает две двоичные матрицы: в матрице alphabet (размером 35×26) каждый столбец кодирует одну букву, а матрица targets (размером 26×26) является диагональной и служит для идентификации столбца.

Каждому столбцу alphabet соответствует матрица 7×5, представляющая собой двоичное изображение буквы.

Следующая функция отображает все столбцы alphabet в виде букв (функцию требуется поместить в рабочий каталог MatLab):

function plotletters(alphabet)

fprintf("plotletters is plotting the first 25 letters\n");

Size(alphabet);

error("plotletters needs columns 35 numbers long");

MM=colormap(gray);

MM=MM(end:-1:1,:);

imagesc(reshape(alphabet(:,j),5,7)");

Результат выполнения функции показан на рис. 3.12:

>> plotletters(alphabet);

Рисунок 3.12. Двоичное кодирование алфавита.

Исходя из структуры матрицы targets, нейронная сеть должна иметь 26 выходных нейронов. Количество нейронов скрытого слоя положим равным 10.

>> net = newff(minmax(alphabet),,{"logsig" "logsig"},"traingdx");

>> P = alphabet; T = targets;

Зададим количество эпох и запустим процесс обучения:

>> net.trainParam.epochs = 1000;

>> = train(net,P,T);

Кривая обучения показана на рис. 3.13.

Рисунок 3.13. Изменение ошибки в процессе обучения

Для проверки качества работы обученной сети рассмотрим зашумленные изображения букв (рис. 3.14):

>> noisyP = alphabet+randn(size(alphabet)) * 0.2;

>> plotletters(noisyP);

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

>> A2 = sim(net,noisyP);

Матрица А2 здесь содержит различные числа в диапазоне . С помощью функции compet можно выделить в каждом столбце максимальный элемент, затем присвоить ему значение 1, а остальные элементы столбца обнулить:

Рисунок 3.14. Изображения букв в присутствии шума

>> for j=1:26

A3 = compet(A2(:,j));

answer(j) = find(compet(A3) == 1);

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

>> NetLetters=alphabet(:,answer);

>> plotletters(NetLetters);

На рис. 3.15 показан окончательный результат распознавания.

Рисунок 3.15. Результат выполнения распознавания нейронной сетью

Очевидно, некоторые буквы идентифицированы ошибочно. Это может быть либо следствием плохой обученности сети, либо слишком высокого уровня шума, либо неправильного выбора количества нейронов внутреннего слоя.

Пусть перед нами экран, разбитый на двенадцать клеток, 4 x 3. Клетки отображают дискретность элементов изображения. При фокусировании изображения клетка либо засвечивается, либо нет. "Засветка" определяет единичное значение величины ее возбуждения, "не засветка" - нулевое. Так, буква О определяет засветку клеток, определяемую на рис.2.1 . Буква А засвечивает экран, как показано на рис.2.2 .

Что надо сделать, чтобы некий конструируемый нами прибор мог сказать, какая это буква?

Очевидно, надо все сигналы возбуждения клеток экрана, засвечиваемые буквой О, подать на конъюнктор , реализующий схему И. Единичный сигнал на выходе конъюнктора , как показано на рис.2.1 , сформируется тогда и только тогда, когда засветятся все клетки экрана, на которое ложится изображение буквы О. Наличие единичного сигнала на выходе конъюнктора и определит ответ: "Это буква О".


Рис. 2.1. Обучение букве "О"


Рис. 2.2. Обучение букве "А"

То же необходимо сделать и для буквы А.

Пометим каждую клетку экрана ее координатами. Тогда на языке математической логики сделанное нами можно записать в виде логических высказываний - предикатов :

Эти предикаты определяют "электронное" воплощение методами схемотехники.

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

А если на экран подать букву К? Тогда ни один из двух конъюнкторов не выработает единичное значение, так как не произойдет полное совпадение засветки соответствующих им клеток экрана. Чтобы "научить" систему букве К, необходимо ввести еще один конъюнктор и проделать те же построения, что и выше.

Таким образом, мы можем говорить, что построили систему распознавания двух "правильно" заданных букв.

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

Рассмотрим возможность распознавания буквы О, допустив возможность засветки клеток (1,1), (1,3), (4,1), (4,3). Тогда ранее построенный предикат примет вид:

Аналогично, для буквы А допустим засветку клеток (4,1) и (4,3):


Рис. 2.3. Совместное обучение буквам "О" и "А"

Объединив оба предиката, получим схему на рис.2.3 .

Таким образом, мы реализовали для обучения и распознавания "схемотехнический" подход, основанный на применении булевых функций и оперирующий булевыми переменными 0, 1.

Построение логической нейронной сети, обученной распознаванию букв

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

Природа и мы, как ее часть, никогда не располагает точной, определенной и достоверной информацией. Засветка клеток экрана, как и рецепторов нашего глаза, не бывает полной, образ не бывает правильным, присутствуют шумы, пропуски и т.д. Тогда жизненную важность обретают понятия похожести, ассоциаций. "На что более всего похож "показанный" образ, возникшая ситуация, и какие ответные действия наиболее обоснованы?" - вот вопрос, определяющий принцип нашей жизни среди многих опасностей и свершений. Ассоциативность нашего мышления является абсолютной.

Значит, надо уйти от вполне определенных булевых переменных (0, 1, "да - нет", "белое - черное" и т.д.) в сторону неопределенности, достоверности или других оценок информации, - в сторону действительных переменных.

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

Преобразуем полученную нами обученную схему в нейронную сеть (рис.2.4).

Каждая клетка экрана - это нейрон -рецептор, который в результате засветки обретает некоторую величину возбуждения, принимающую значение между нулем и единицей. Рецепторы , заменившие экран, образуют входной, или рецепторный, слой нейросети. Каждый конъюнктор и дизъюнктор заменим единой для всей сети моделью нейрона . Введем выходной слой сети, состоящий в нашем примере из двух нейронов , возбуждение которых определяет результат распознавания. Назовем нейроны выходного слоя по названиям букв - О и А.

Рецепторы , подобно экрану, возбуждаются извне. Все же другие нейроны , имитируя распространение возбуждения в мозге, реализуют передаточную функцию (в терминах теории автоматического регулирования) или функцию активации (в терминах теории нейронных сетей). Эта функция преобразует сигналы на входе нейрона , с учетом весов этих входов (пока отложим их рассмотрение), в величину возбуждения данного нейрона , передаваемого далее по сети в соответствии со связями нейронов и достигающего одного или более нейронов выходного слоя .


Рис. 2.4. Нейронная сеть для распознавания букв "О" и "А"

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

Первоначально находим

Затем положим

Требуется создать нейронную сеть для распознавания 26 букв латинского алфавита . Будем считать, что имеется система считывания символов, которая каждый символ представляет в виде матрицы . Например, символ A может быть представлен, как показано на рис. 2.22.

Рис. 2.22. Представление символа

Реальная система считывания символов работает не идеально, а сами символы отличаются по начертанию. Поэтому, например, для символа A единицы могут располагаться не в тех клетках, как показано на рис. 2.22. Кроме того, вне контура символа могут возникать ненулевые значения. Клетки, соответствующие контуру символа, могут содержать значения, отличные от 1. Будем называть все искажения шумом.

В MATLAB имеется функция prprob , возвращающая матрицу , каждый столбец которой представляет записанную в виде вектора матрицу , описывающую соответствующую букву (первый столбец описывает букву A, второй - букву B и т. д.). Функция prprob возвращает также целевую матрицу размером , каждый столбец которой содержит одну единицу в строке, соответствующей номеру буквы при нулевых остальных элементах столбца. Например, первый столбец, соответствующий букве A, содержит 1 в первой строке.

Пример . Определим шаблон для буквы A (программа Template_A.m ).

% Пример формирования шаблона для буквы A

Prprob;

i=1; % номер буквы A

v=alphabet(:,i); % вектор, соответствующий букве A

template=reshape(v, 5,7)";

Кроме уже описанной функции prprob в программе использованы функции reshape , которая формирует матрицу , а после транспонирования - (убедитесь, что невозможно сразу сформировать матрицу ), и функция plotchar , которая рисует 35 элементов вектора в виде решетки . После выполнения программы Template_A.m получим матрицу template и шаблон буквы A, как показано на рис. 2.23.

Рис. 2.23. Сформированный шаблон буквы A

Для распознавания букв латинского алфавита необходимо построить нейронную сеть с 35 входами и 26 нейронами в выходном слое. Примем число нейронов скрытого слоя равным 10 (такое число нейронов выбрано экспериментально). Если при обучении возникнут затруднения, то можно увеличить количество нейронов этого уровня.



Сеть распознавания образов строится функцией patternnet. Обратите внимание, что при создании сети не задается число нейронов входного и выходного слоев. Эти параметры неявно задаются при обучении сети.

Рассмотрим программу распознавания букв латинского алфавита Char_recognition.m

% Программа распознавания букв латинского алфавита

Prprob; % Формирование входных и целевых векторов

Size(alphabet);

Size(targets);

% Создание сети

Train(net,P,T);

% Обучение в присутствии шума

P = ;

Train(netn,P,T);

Train(netn,P,T);

% Тестирование сети

noise_rage=0:0.05:0.5; % Массив уровней шума (стандартных отклонений шума

for noiselevel=noise_rage

for i=1:max_test

% Тест для сети 1

% Тест для сети 2

title("Погрешность сети");

xlabel("Уровень шума");

ylabel("Процент ошибки");

Оператор = prprob ; формируют массив векторов входа alphabet размера с шаблонами символов алфавита и массив целевых векторов targets .

Сеть создается оператором net=patternnet. Примем параметры сети по умолчанию. Обучение сети производится сначала в отсутствии шума. Затем сеть обучается на 10 наборах идеальных и зашумленных векторов. Два набора идеальных векторов используются, чтобы сеть сохранила способность классифицировать идеальные векторы (без шума). После обучения сеть "забыла", как классифицировать некоторые векторы, свободные от шума. Поэтому сеть следует снова обучить на идеальных векторах.

Следующий фрагмент программы производит обучение в отсутствие шума:

% Обучение сети в отсутствие шума

Train(net,P,T);

disp("Обучение сети в отсутствие шума завершено. Нажмите Enter");

Обучение в присутствии шума проводится с применением двух идеальных и двух зашумленных копий входных векторов. Шум имитировался псевдослучайными нормально распределенными числами с нулевым средним значением и стандартным отклонением 0.1 и 0.2. Обучение в присутствии шума производит следующий фрагмент программы:

% Обучение в присутствии шума

netn = net; % сохранение обученной сети

T = ;

P = ;

Train(netn,P,T);

disp("Обучение сети в присутствии шума завершено. Нажмите Enter");

Поскольку сеть обучалась в присутствии шума, то имеет смысл повторить обучение без шума, чтобы гарантировать правильную классификацию идеальных векторов:

% Повторное обучение в отсутствии шума

Train(netn,P,T);

disp("Повторное обучение сети в отсутствии шума завершено. Нажмите Enter");

Тестирование сети проводилось для двух структур сети: сети 1, обученной на идеальных векторах, и сети 2, обученной на зашумленных последовательностях. Шум со средним значением 0 и стандартным отклонением от 0 до 0.5 с шагом 0.05 добавлялся к векторам входа. Для каждого уровня шума формировалось 10 зашумленных векторов для каждого символа, и вычислялся выход сети (желательно увеличить число зашумленных векторов, но это заметно увеличит время работы программы). Сеть обучается так, чтобы сформировать единицу в единственном элементе выходного вектора, позиция которого соответствует номеру распознанной буквы, и заполнить остальную часть вектора нулями. Никогда на выходе сети не будет формировать вектор выхода, состоящий точно из 1 и 0. Поэтому в условиях действия шумов выходной вектор обрабатывается функцией compet , которая преобразует выходной вектор так, что самый большой выходной сигнал получает значение 1, а все другие выходные сигналы получают значение 0.

Соответствующий фрагмент программы имеет вид:

% Выполнение теста для каждого уровня шума

for noiselevel=noise_rage

for i=1:max_test

P=alphabet+randn(35, 26)*noiselevel;

% Тест для сети 1

errors1=errors1+sum(sum(abs(AA-T)))/2;

% Тест для сети 2

errors2=errors2+sum(sum(abs(AAn-T)))/2;

% Средние значения ошибок (max_test последовательностей из 26 векторов целей)

network1=;

network2=;

plot(noise_rage, network1*100, noise_rage, network2*100);

title("Погрешность сети");

xlabel("Уровень шума");

ylabel("Процент ошибки");

legend("Идеальные входные векторы","Зашумленные входные векторы");

disp("Тестирование завершено");

При вычислении погрешности распознавания, например, errors1=errors1+sum(sum(abs(AA-T)))/2, учтено, что при неправильном распознавании не совпадают два элемента выходного вектора и вектора цели, поэтому при подсчете погрешности производится деление на 2. Сумма sum(abs(AA-T)) вычисляет число не совпавших элементов для одного примера. Сумма sum(sum(abs(AA-T))) вычисляет число не совпавших элементов по всем примерам.

Графики погрешности распознавания сетью, обученной на идеальных входных векторах, и сетью, обученной на зашумленных векторах, представлены на рис. 2.24. Из рис. 2.24 видно, что сеть, обученная на зашумленных образах, дает небольшую погрешность, а на идеальных входных векторах сеть обучить не удалось.

Рис. 2.24. Погрешности сети в зависимости от уровня шума

Проверим работу обученной сети (в рабочем пространстве MATLAB должна присутствовать обученная сеть). Программа Recognition_J.m формирует зашумленный вектор для буквы J и распознает букву. Функция randn формирует псевдослучайное число, распределенное по нормальному закону с нулевым математическим ожиданием и единичным среднеквадратичным отклонением. Случайное число с математическим ожиданием m и среднеквадратическим отклонением d получается по формуле m+randn*d (в программеm=0, d=0.2 ).

noisyJ = alphabet(:,10)+randn(35,1) * 0.2;

plotchar(noisyJ);

disp("Зашумленный символ. Нажмите Enter");

A2 = netn(noisyJ);

A2 = compet(A2);

ns = find(A2 == 1);

disp("Распознан символ");

plotchar(alphabet(:,ns));

Программа выводит номер распознанной буквы, зашумленный шаблон буквы (рис. 2.25) и шаблон распознанной буквы (2.26).

Рис. 2.25. Зашумленный шаблон буквы

Рис. 2.26. Шаблон распознанной буквы

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

Задания

1. Проделайте все приведенные примеры.

2. Испытайте распознавание различных букв

3. Исследуйте влияние шума в программах на точность распознавания символов.

Аппроксимация функций

Книги Майкла Нильсона "Neural Networks and Deep Learning".


Перевод я разбил на несколько статей на хабре, чтобы было удобнее читать:
Часть 1) Введение в нейронные сети
Часть 2) Построение и градиентный спуск
Часть 3) Реализация сети для распознавания цифр
Часть 4) Немного о глубоком обучении

Введение

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

Простую интуицию - "у 9-тки есть петля сверху, и вертикальный хвост внизу" не так просто реализовать алгоритмически. Нейронные сети используют примеры, выводят некоторые правила и учатся на них. Более того чем больше примеров мы покажем сети, тем больше она узнает о рукописных цифрах, следовательно классифицирует их с большей точностью. Мы напишем программу в 74 строчки кода, которая будет определять рукописные цифры с точностью >99%. Итак, поехали!

Персептрон

Что такое нейронная сеть? Для начала объясню модель искусственного нейрона. Персептрон был разработан в 1950 г. Фрэнком Розенблатом , и сегодня мы будем использовать одну из основных его моделей - сигмоидный персептрон. Итак, как он работает? Персепрон принимает на вход вектор и возвращает некоторое выходное значение .



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



И это все, что нам нужно! Варьируя и вектор весов , можно получить совершенно разные модели принятия решения. Теперь вернемся к нейронной сети.



Итак, мы видим, что сеть состоит из нескольких слоев нейронов. Первый слой называется входным слоем или рецепторами (), следующий слой - скрытый (), и последний - выходной слой (). Условие довольно громоздко, давайте заменим на скалярное произведение векторов . Далее положим , назовем его смещением персептрона или и перенесем в левую часть. Получим:


Проблема обучения

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



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

Сигмоидный нейрон

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



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


Архитектура нейронных сетей

Проектирование входных и выходных слоев нейросети - достаточно просто занятие. Для примера, предположим, что мы пытаемся определить, изображена ли рукописная "9" на изображении или нет. Естественным способом проектирования сети является кодирование интенсивностей пикселей изображения во входные нейроны. Если изображение имеет размер , то мы имеем входных нейрона. Выходной слой имеет один нейрон, который содержит выходное значение, если оно больше, чем 0.5, то на изображении "9", иначе нет. В то время как проектирование входных и выходных слоев - достаточно простая задача, выбор архитектуры скрытых слоев - искусство. Исследователи разработали множество эвристик проектирования скрытых слоев, например такие, которые помогают скомпенсировать количество скрытых слоев против времени обучения сети.


До сих пор мы использовали нейронные сети, в которых выход из одного слоя - использовался как сигнал для следующего, такие сети называются прямыми нейронными сетями или сетями прямого распространения(). Однако существуют и другие модели нейронных сетей, в которых возможны петли обратной связи. Эти модели называются рекуррентными нейронными сетями (). Рекуррентные нейронные сети были менее влиятельными, чем сети с прямой связью, отчасти потому, что алгоритмы обучения для рекуррентных сетей (по крайней мере на сегодняшний день) менее эффективны. Но рекуррентные сети по-прежнему чрезвычайно интересны. Они гораздо ближе по духу к тому, как работает наш мозг, чем сети с прямой связью. И вполне возможно, что повторяющиеся сети могут решать важные проблемы, которые могут быть решены с большим трудом с помощью сетей прямого доступа.


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

 
Статьи по теме:
Учимся вязать и выбираем схемы двухцветных узоров
Базовые узоры ажурными и снятыми петлями Ажурные узоры получаются благодаря накидам и сочетанием их с другими петлями. Накиды используются в узорах со сложными переплетениями нитей, для прибавления и удлинения петель. Без накидов нельзя связать ажурные у
Логопеды для детей В каких случаях мы гарантировано поможем
В каких случаях ребенку нужна помощь логопеда? Какой возраст оптимален для обращения к специалисту и постановки сложных звуков? Как родители могут помочь в развитии речи? На эти и другие вопросы читателей «Ю-мамы» отвечает Дениза Раисовна, логопед медико-
Как крючком связать чехол для подушки (прямоугольной и круглой формы)
Размеры Каждый чехол – 30 х 30 смВам потребуется Для каждого чехла меланжевая пряжа (45% шелка, 45% мохера, 10% шерсти; 100 м/50 г) – по 50 г в пастельных тонах (= цвет А), зелено-рыжей (цвет В) и сине-бирюзовой (= цвет С); крючок №4; для каждого чехла
Ангел связаный крючком. Описание работы. Вязание ангела крючком. Подборка схем и МК Ангелочки крючком со схемами простые и красивые
Сделать вашу зеленую красавицу авторской, особенно если вы увлекаетесь рукоделием для вас не составит труда. Правда, я не знаю почему ангелочки изображаются в человеческом облике и с крыльями, ведь во всех мировых религиях: христианство, ислам, иудаизм и