В качестве интересного задания я начал немного изучать искусственный интеллект и машинное обучение. Прошла отличный курс 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 г.