Перевод кенийского языка жестов с помощью глубокого обучения

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

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

Сначала беседы с Хадсоном и его также глухим соучредителем Альфредом проходили с помощью переводчиков жестового языка, которых они вызывали на встречи. Приложение Хадсона и бот Sophie (прим.: другой проект автора статьи) финансировались по одной программе, поэтому в них не было недостатка.

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

Взаимодействие с сообществом глухих только выросло после этого. В мае прошлого года на конференции Microsoft Build, в ожидании одного из ключевых докладов, к нам присоединилась команда глухих разработчиков, и я попросил разрешения представиться своим жестовым именем. К счастью, с ними был переводчик, и он помог мне с этим. В июне прошлого года, после событий в прибрежной части Кении (прим.: автор имеет ввиду масштабные наводнения), Хадсон уговорил меня присоединиться к нему и заглянуть на конкурс красоты, в котором участвовала его подруга. Она была текущей королевой конкурса и тоже глухой. Позже мы все отправились выпить, но я не мог полноценно участвовать в разговоре. Все, что я знал, это как правильно произносить «GIF», мое имя и как сказать «привет».

В октябре прошлого года на конференции Droidcon Kenya,которую я помогаю организовывать, присутствовали два глухих разработчика, и они пригласили двух переводчиков жестового языка. Было понятно, что вселенная хочет, чтобы я наконец выучил язык жестов.

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

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

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

partfolio_ds
Специализация Аналитик Данных
Идет набор в группу 6 900₽ в месяц

Классификатор изображений для кенийского языка жестов

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

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

Сбор данных и маркировка данных

Базы данных с Kaggle

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

Я нашел одну, но она была только с образцами жестов, сделанных белыми. А вот так выглядят мои пальцы:

Жест гангстера физики (прим.: правило правой руки, которое, с подачи сериала «Теория большого взрыва», получило новое имя)

Ууупс. Скорее всего это бы не сработало. Это частая проблема с многими научными базами данных. К примеру, персонажи и актеры из «Черной пантеры» получают такие оценки при попытках использовать алгоритмы распознавания лиц на них:

Ваканда навсегдааа!!!!

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

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

Изображения уже были векторизованы и RGB слой был удален. Это не подходило для моей задачи. Я хотел получить сквозную модель, которая получала бы изображение половины тела, как человек в реальной жизни, а не создавать слой обнаружения объектов, который бы определял расположение рук.

Краудсорсинг данных для глубокого обучения

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

Курс по нейронным сетям
Идет набор в группу 4 200₽ в месяц

Самостоятельное создание базы данных

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

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

```
~/data
~/data/A/A (1).jpg
~/data/A/A (2).jpg
...
~/data/Z/Z (1).jpg
~/data/Z/Z (2).jpg
```

Мои данные уже можно найти на FloydHub’e.

Выбор нейронной сети

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

Многие предпочитают fast.ai с ResNet, но я знал как работать с TensorFlow и Keras, так что я поставил на них.

Сверточные нейронные сети – это самое ходовое решение для задач, касающихся компьютерного зрения, но для обучения такой с нуля требуется много данных и времени. Так что давайте не будем этим заниматься, воспользовавшись Keras code labs.

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

Мой опыт разработчика мобильных приложений заставляет меня сначала хвататься за создание мобильной версии. Удачно, что у меня был опыт работы с этими двумя моделями. У меня были даже готовые скрипты из предыдущей codelab «hotdog, not hotdog».

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

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

Скрипты были созданы командой TensorFlow и позже вдохновили их на создание codelab «TensorFlow для поэтов».

Курс по Machine Learning
Идет набор в группу 3 800₽ в месяц

Обучение модели

Преимущество хорошо написанных скриптов от команды TensorFlow – это то, что нам надо просто запустить скрипты с соответствующими гиперпараметрами. В данном случае мы будем тренироваться на FloydHub.

Пробный прогон с гиперпараметрами

Inception

Проделаем это с моделью Inception. Сначала инициализируем FloydHub проект в нашей локальной среде:

```bash
floyd init iamukasa/ksl_translator
```

Теперь обучаем модель:

```bash
floyd run — env tensorflow-1.9 \
 — follow \
 — data iamukasa/datasets/ksl/1: data \
“python retrain.py — model_dir ./inception — image_dir=/data”
```

Mobilenets

Аналогично:

```bash
floyd init iamukasa/ksl_translator_mobilenets
```

И затем обучение:

```bash
floyd run — env tensorflow-1.9 \
 — follow \
 — data iamukasa/datasets/ksl/1:data \
“python retrain.py
 — bottleneck_dir= [path to bottleneck directory]
 — how_many_training_steps= [number of trainnig steps you want]
 — output_graph= [path and name of file you want to save .pb file]
 — output_labels= [ path and name of file you want to save as a .txt file]
 — image_dir=data”
```

Разница в гиперпараметрах появляется из-за того, что в скрипте Inception определено больше значений, чем в Mobilenets. Когда все настроено, и код сработал как показано сверху, то полученный результат будет примерно таким же, как я опишу ниже. 

Курс «Python для анализа данных»
Идет набор в группу 2 700₽ в месяц

Оценка нашей обученной модели

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

Ничто не может удовлетворить разработчика AI больше, чем эти два графика, где точность направлена к 1, а потери (энтропии) — к 0 на каждой итерации обучения. Это первый признак того, что вы все делаете правильно.

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

Вы можете повторить это на FloydHub’е.

Отладка модели

Через 1500 итераций модель Inception дала итоговую сводку точности 99,6%. Подозрительно высокая точность — я подозреваю, что случилось «переобучение» (прим.: или оверфиттинг) модели. Когда модель AI слишком успешно учится на ваших тренировочных данных, она может плохо обобщаться на реальные данные. Сейчас я оставлю эту конкретную модель как есть и буду улучшать ее по мере поступления более разнообразных данных из работающего демо.

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

С Mobilenets я столкнулся с другой проблемой. Те же гиперпараметры, что и в начальной модели, дали итоговое значение точности в 100%. Явно происходил оверфиттинг модели, и случалось это слишком рано — на итерации номер 22.

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

В тот момент оба варианта были для меня неприемлемы, поэтому мне пришлось схитрить (и я не стал бы поощрять вас делать так же). Я переучил модель с меньшим количеством итераций вместо того, чтобы позволить моим тренировочным итерациям добраться до того места, где они получают 100% -ную точность оценок.

Деплой

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

Я переписал Python-скрипты для маркировкой изображений как модульные методы, которые просто переносят фрейм с моей веб-камеры на фотографию и возвращают прогноз вместе с доверительной оценкой для прогноза. Далее нужно было программно передавать живое фото с моей камеры и передавать каждый кадр модели для прогнозирования, а затем отображать прогноз и оценку достоверности на экране.

Если вы используете мое репозиторий на GitHub, то вот код, который нужно запустить для этого:

import tensorflow as tf
import cv2
import base64
import  time
cap = cv2.VideoCapture(-1)
count =0
if cap.isOpened():
rval,frame=cap.read()
else :
rval=False
# Loads label file, strips off carriage return
label_lines = [line.rstrip() for line
in tf.gfile.GFile("inception/output_labels.txt")]
# Unpersists graph from file
f = tf.gfile.FastGFile("inception/output_graph.pb", 'rb')
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
_ = tf.import_graph_def(graph_def, name='')
with tf.Session() as sess:
while True:
cv2.imshow("Inception Classifier", frame)
# true or false for ret if the capture is there or not
ret, frame = cap.read()  # read frame from the ]
buffer= cv2.imencode('.jpg',frame)[1].tostring()
image_data=buffer
# Feed the image_data as input to the graph and get first prediction
softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
predictions = sess.run(softmax_tensor,{'DecodeJpeg/contents:0': image_data})
# Sort to show labels of first prediction in order of confidence
top_k = predictions[0].argsort()[-1:][::-1]
for node_id in top_k:
human_string = label_lines[node_id]
score = predictions[0][node_id]
#Only add label to feed if confidence is more than 40 %
if score > 0.4:
text_color = (255, 0, 0)
cv2.putText(frame, s, (33, 455),
cv2.QT_FONT_NORMAL, 1.0, text_color, thickness=2)
name_of_file="frames/"+str(human_string)+str(score)+".jpg"
cv2.imwrite(name_of_file,frame)
print(name_of_file)
count= count+1
key = cv2.waitKey(20)
if key == 27:
break
cv2.destroyWindow("Inception Classifier")

Вот что из этого получилось:

Жест, обозначающий букву D
Жест для буквы O

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

Но на этом все не закончилось.

 Следующие шаги

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

Деплой на Андройде

Деплой приложения для Android имеет два пути. Первый — это добавить приложение tflite в исходный код, как, например, в этом примере c TensorFlow. Или использовать Firebase ML Kit, как в этом руководстве. Второй путь предполагает преобразование полученных графов в файлы TensorFlow Lite и разворачивание их в приложении для Android. Для этого надо запустить следующую команду

```bash  
toco \ — input_file= [path to .pb file] \ — output_file=output/output_graph.tflite \ — input_format=TENSORFLOW_GRAPHDEF \ — output_format=TFLITE \ — input_shape=1,224,224,3 \ — input_array=input \ — output_array=final_result \ — inference_type=FLOAT \ — input_data_type=FLOAT\ — allow_custom_ops```

Расширение функционала для использования видео

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

Источником вдохновения для этой статьи послужило демо от Fchollet на TensorFlow Dev Summit.

Оригинал: https://towardsdatascience.com/translating-the-kenyan-sign-language-with-deep-learning-e58792f1b27a

Перевод: Ухарова Елена

Поделиться: