4

Нейронная сеть для распознавания имен на Julia (Flux.jl)

Доброго времени суток,


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


Суть задачи: есть у нас около 112 тысяч никнеймов. Кто-то пишет свое реальное имя правильно, кто-то пишет, но не правильно, кто-то решил написать какое-либо слово, кто-то - абсурдный никнейм по типу аувау324. И вот нам нужно узнать, сколько в данном списке имен Влад, сколько - Саша, и сколько "мусорных" имен.


Решить данную задачу можно было и без использования ML, но:

а) это было бы долго и много ручной работы

б) хотелось поиграться с нейронками


Решая данную задачу, я во многом полагался на данную интересную статью на Хабре.

Во время решения донного задания я допустил несколько критических ошибок, которые повлияли на конечный результат (ошибки рассмотрю по ходу объяснения алгоритма решения).


Алгоритм решения:

1) Подготовка данных

Первым делом нужно было подготовить данные к манипуляциям. Чем меньше лишних данных и чем меньше форм этих данных - тем лучше справятся алгоритмы машинного обучения.


Важно понимать, что свести все данные к одной форме и убрать n-нное количество информации - не одно и тоже. Можно сравнить данный процесс со сжатием без потерь - информация не удаляется, изменяется лишь ее форма.


Подготовил данные я следующим образом:

1) Преобразовал все слова в lowercase.

2) Нормализировал UTF символы (например, перевел ó в о).

3) Удалил смайлики и прочий мусор из имен.

4) Удалил имена, которые имели 2 символа или меньше.


Важный момент(!) - так как в базе мы имели имена на английском (например Julia), транслитом (например Yulia) и кириллицей (Юлия\Юлія), я не додумался перевести все имена, допустим, на латинские буквы, что повлияло на сложность вычислений и на точность нейронной сети. Это важный момент - все данные должны быть в одной форме.


2) Составления словаря

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


Для решения данного пункта я воспользовался материалом с Хабровской статьи, и создал словарь для моего набора слов.

Создавал я словарь следующим образом:

1) Каждое слово делил на би-граммы (если в слове было нечетное количество букв - то на би-граммы и уни-граммы).

2) Далее, если данной би-граммы\уни-граммы еще нет в словаре - записывал ее в словарь. На выходе у меня получился словарь из 2371 би-грамм\уни-грамм без повторений.


Почему я использовал би-граммы, а не уни-граммы? Мой алгоритм не предусматривал определения, например, количества данной буквы в слове, и поэтому нейронная сеть не смогла бы отличить слово "Ана" от "Анна", и вот почему...


3) Векторизация словаря

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


Для начала векторизируем словарь:

1) Так как наш словарь имеет 2871 элемент, закодируем каждое "слово" из словаря в 2371-элементный вектор. Для примера, имеем словарь ["a", "b", "c"] - тогда буква "а" будет иметь вектор [1, 0, 0] относительно словаря, "b" - [0, 1, 0], "c" - [0, 0, 1]. И теперь, если мы захотим векторизировать слово "abbca" относительно такого словаря, то у нас получится вектор [1, 1, 1]. И теперь понимаем, почему данный алгоритм не смог бы различаться некоторые слова, если бы мы использовали уни-граммы - для него что слово "aaabbbbccc", что "abc", имеют одинаковый вектор [1, 1, 1].


Таким Макаром мы также установили количество входных нейронов для нашей сети - 2371, так как каждое наше слово теперь будет кодироваться относительно словаря в 2371-размерный вектор и на каждый нейрон будет подаваться 1 или 0.


4) Создание нейронной сети

Самый спорный момент, так как я почти не разбираюсь в проектировании нейронных сетей и ML в целом, так что я эмпирическим путем узнал, что моя видеокарта способна с адекватной скоростью тренировать нейронку с одним входным слоем, одним скрытым на 1840 нейронов, один скрытый на 700 нейронов, ну и один выходной слой (кстати, размер выходного слоя у нас зависит от количества классов, которые вы хотите иметь. Я хотел, что бы нейронка смогла различить 105 разных имен, поэтом размер выходного слоя у меня соответственный). Такая нейронная сеть давала мне около 75% точности после 100 эпох обучения.


5) Подготовка данных

Вручную мною было классифицировано 2000 имен. По ходу ручной классификации было найдено 105 уникальных имени (класс №1 означал "мусорное имя"). На этих именах я тренировал и тестировал нейронную сеть.


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


Удачи, никогда не забывайте, что программирование - это не знания языка программирования, а в первую очередь умение правильно управлять данными. А еще проектирование не помешает :)

ИТ-проекты пикабушников

585 постов3.4K подписчиков

Правила сообщества

0. Запрещены посты вне тематики сообщества

1. Уважайте труд людей, пишите только конструктивную критику,

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