В качестве интересного задания я начал немного изучать искусственный интеллект и машинное обучение. Прошла отличный курс Fast.AI. Это серия видеороликов, которые бесплатно перенесут вас с нуля до героя с помощью машинного обучения.

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

  • Свободно доступный набор данных
  • Может использоваться для общественного блага
  • Не слишком сложно для моей первой попытки

Итак, поискав в Kaggle и в Интернете в целом крутой набор данных, я наткнулся на базу данных изображений ножей, которая содержала как положительные, так и отрицательные примеры. С моим набором данных пора было приступить к работе!

Социальное благо

К сожалению, преступления с ножами - серьезная проблема в Великобритании. В течение года, закончившегося март 2018 года, в Англии и Уэльсе было совершено около 40 100 правонарушений с применением ножа или острого инструмента.

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

Метод

Структурирование данных

Сначала я сопоставил свои данные и поместил все свои изображения в одну папку с шаблоном именования:

knife_1.bmp notknife_1.bmp

Номера порядковые: нож_1, нож_2 и т. Д.

Запуск Jupyter Notebook

Блокноты Jupyter де-факто являются инструментом для работы с этими наборами данных, и я не отклонялся от этого.

Сначала я настроил свой блокнот на автоматическое обновление и загрузил свои библиотеки FastAI:


!pip install --upgrade fastai %reload_ext autoreload %autoreload 2 %matplotlib inline from fastai.vision import * from fastai.metrics import error_rate

Затем я импортировал свои данные, чтобы моя модель могла легко получить к ним доступ:

path = Path('/data/') knives = fnames = get_image_files(path) print(knives[:5])

Я распечатал набор из пяти имен своих файлов, чтобы убедиться, что они импортируются эффективно:

[PosixPath('/data/notknife_3198.bmp'), PosixPath('/data/notknife_2790.bmp'), PosixPath('/data/notknife_2296.bmp'), PosixPath('/data/notknife_8269.bmp'), PosixPath('/data/notknife_5795.bmp')]

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

pat = r'/([^/]+)_\d+.bmp$'

Затем я воспользовался одной из функций FastAI, которая объединяет наши изображения в формат, подходящий для компьютерного зрения:

data = (ImageDataBunch .from_name_re(path, knives, pat, ds_tfms=get_transforms(), size=224, bs=64) .normalize(imagenet_stats))

Итак, как вы можете видеть выше, у нас есть наш путь для доступа к данным, наш обучающий набор в форме knives, затем мы гарантируем, что они действительны, применяя наше регулярное выражение, мы изменяем размер изображений до равномерного 224 (множитель 7, который оптимально для наших данных RestNet, которые появятся позже), а затем мы нормализуем набор данных.

Чтобы убедиться, что все прошло так, как мы ожидали, я вывожу 4 строки наших изображений, а также две ожидаемые метки: knife, notknife:

data.show_batch(rows=4) print(data.classes)

На выходе я получаю следующее:

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

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

Для этого я использую сверточную нейронную сеть или CNN и тренируюсь с использованием resnet50, который, как следует из названия, является 50-слойной остаточной сетью. Это позволяет нам использовать так называемое трансферное обучение, которое использует знания, хранящиеся в одной модели, и применяет их к другой. По сути, это отправная точка для нашей модели.

С Fast.AI это очень просто:

learn = create_cnn(data, models.resnet50, metrics=error_rate) learn.fit_one_cycle(4) learn.save('knives-stage-1')

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

После завершения, это может занять некоторое время! Получаем что-то вроде этого:

Итак, как видите, мы начинаем с более высокой частоты ошибок и постепенно снижаем ее с 98% до 99,5% точности.

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

Выявление ошибок модели

interp = ClassificationInterpretation.from_learner(learn) interp.plot_top_losses(9)

Выполняя вышеуказанное, я прошу FastAI интерпретировать результаты и отобразить 9 основных неверных предположений, которые вернут следующее:

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

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

learn.lr_find() learn.recorder.plot()

Это отображает следующую диаграмму:

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

learn.fit_one_cycle(10, max_lr=slice(1e-03,1e-02)) learn.save('knives-stage-2')

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

Затем мы получаем следующее:

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

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

Вывод

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

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

Первоначально опубликовано на сайте ruairidhwm.github.io 1 февраля 2019 г.