Построение отличного классификатора видов птиц за минимально возможное количество шагов


TL;DR

Используя библиотеку fast.ai, мы можем построить отличный классификатор изображений за минимально возможное количество шагов. Для этого не требуется ни математических, ни глубоких знаний в области ML, ни сложных навыков программирования. Я настоятельно рекомендую ознакомиться с курсом fast.ai, который был выпущен в 2022 году для лучшего понимания и еще более интересных примеров.

import os
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
from fastcore.all import *
import time
import json
iskaggle = os.environ.get('KAGGLE_KERNEL_RUN_TYPE', '')

if iskaggle:
    !pip install -Uqq fastai
Вход в полноэкранный режим Выход из полноэкранного режима

Шаг 1. Давайте соберем некоторые данные.

Сначала я думал погуглить изображения 100 самых популярных видов птиц в Великобритании (где я сейчас живу), но, к счастью, кто-то уже подготовил набор данных видов птиц на kaggle, который мы можем сразу же использовать.
https://www.kaggle.com/datasets/gpiosenka/100-bird-species

# read the data from the dataset
PREFIX = '../input/100-bird-species/';
birds_data = pd.read_csv(PREFIX + 'birds.csv')
latin_names = pd.read_csv(PREFIX + 'birds latin names.csv')
class_dict = pd.read_csv(PREFIX + 'class_dict.csv')

print(birds_data.shape)
print(latin_names.shape)
print(class_dict.shape)
Войти в полноэкранный режим Выйти из полноэкранного режима

(62388, 4)
(400, 3)
(400, 6)

Вот как выглядят данные

birds_data.head(5)
Вход в полноэкранный режим Выход из полноэкранного режима

from fastai.vision.all import *
im = Image.open(PREFIX + birds_data['filepaths'][0])
im.to_thumb(224,224)
Войти в полноэкранный режим Выход из полноэкранного режима

Шаг 2. Подготовьте данные.

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

birds_train = birds_data[birds_data['data set'] == 'train']
train_path = Path(PREFIX + 'train')
Войти в полноэкранный режим Выйти из полноэкранного режима
  • Мы используем ImageBlock и CategoryBlock, поскольку у нас есть данные изображений, которые мы хотим разделить по категориям.
  • Функции get_image_files и parent_label нужны для доступа к изображениям и меткам во время загрузки данных.
  • Одной из важных частей является изменение размера данных, чтобы убедиться, что все они имеют одинаковый формат, используя трансформатор Resize.
  • Кроме того, мы также должны взять 20% от нашего обучающего набора, чтобы проверить нашу модель в процессе обучения.

Давайте посмотрим на данные:

dls = DataBlock(
    blocks=(ImageBlock, CategoryBlock), 
    get_items=get_image_files, 
    splitter=RandomSplitter(valid_pct=0.2, seed=42),
    get_y=parent_label,
    item_tfms=[Resize(224, method='squish')]
).dataloaders(train_path)

dls.show_batch(max_n=6)
Войти в полноэкранный режим Выход из полноэкранного режима

Шаг 3. Построить модель.

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

learn = vision_learner(dls, resnet18, metrics=error_rate)
learn.fine_tune(4)
Вход в полноэкранный режим Выход из полноэкранного режима

Шаг 4 Тестирование.

Итак, 4 эпохи заняли всего 12 минут, и у нас уже есть готовая модель!
Давайте возьмем тестовые данные и посмотрим на предсказания 🙂

birds_test = birds_data[birds_data['data set'] == 'test']
birds_test_sample = birds_test.sample(5)
birds_test_sample 
Войти в полноэкранный режим Выйти из полноэкранного режима

python

Получение индекса метки

def get_index(label):
    return class_dict[class_dict['class'] == label].iloc[0]['class_index']; 

## Make a prediction for particular image
def predict_image(path):
    img = PILImage.create(path)
    is_bird,_,probs = learn.predict(img)
    print(f"This is a: {is_bird}.")
    index = get_index(is_bird)
    print(f"Probability it's {is_bird}: {probs[index]:.4f}")

#This is a: INLAND DOTTEREL.
#Probability it's INLAND DOTTEREL: 1.0000
#This is a: PURPLE MARTIN.
#Probability it's PURPLE MARTIN: 0.9097
#This is a: AMERICAN REDSTART.
#Probability it's AMERICAN REDSTART: 0.9960
#This is a: BULWERS PHEASANT.
#Probability it's BULWERS PHEASANT: 1.0000
#This is a: GREAT POTOO.
#Probability it's GREAT POTOO: 0.9986
Вход в полноэкранный режим Выход из полноэкранного режима

Виола!

Похоже, что модель вполне уверенно работает с тестовым набором. Давайте попробуем несколько специальных примеров из duckduckgo.

# Searching images on ddg
def search_images(term, max_images=200):
    url = 'https://duckduckgo.com/'
    res = urlread(url, data={'q': term})
    searchObj = re.search(r'vqd=([d-]+)&', res)
    requestUrl = url + 'i.js'
    params = dict(l='us-en', o='json', q=term,
                  vqd=searchObj.group(1), f=',,,', p='1', v7exp='a')
    headers = dict(referer='https://duckduckgo.com/')
    urls, data = set(), {'next': 1}
    while len(urls) < max_images and 'next' in data:
        res = urlread(requestUrl, data=params, headers=headers)
        data = json.loads(res) if res else {}
        urls.update(L(data['results']).itemgot('image'))
        requestUrl = url + data['next']
        time.sleep(0.2)
    return L(urls)[:max_images]

urls = search_images('duck', max_images=1)

from fastdownload import download_url
dest = 'bird'
download_url(urls[0], dest, show_progress=False)

from fastai.vision.all import *
im = Image.open(dest)
im.to_thumb(256,256)
Войти в полноэкранный режим Выход из полноэкранного режима

predict_image(dest)

#This is a: MALLARD DUCK.
#Probability it's MALLARD DUCK: 0.8892
Войти в полноэкранный режим Выход из полноэкранного режима

Да, черт возьми (LOL)

Очевидно, что предсказать утку с duckduckgo — не самая сложная задача.
Давайте используем фотографию, которую я сделал на улице, и посмотрим, как оно с ней справится.

import ipywidgets as widgets
from IPython.display import display

uploader = widgets.FileUpload()
display(uploader)
Войти в полноэкранный режим Выход из полноэкранного режима

(здесь показано, как это будет выглядеть на Jupyter notebook)

img = PILImage.create(uploader.data[0])
img.to_thumb(224,224)
Войти в полноэкранный режим Выход из полноэкранного режима

predict_image(uploader.data[0])

#This is a: BLUE HERON.
#Probability it's BLUE HERON: 0.6347 (!)
Войти в полноэкранный режим Выход из полноэкранного режима

Результаты

63% для цапли, что правильно, однако не так уверенно, как хотелось бы.

Поэтому следующие шаги для исследования:

  • Попробовать увеличение данных.
  • Увидеть и очистить неправильные случаи с помощью ClassificationInterpretation.
  • Наконец, развернуть на веб / мобильном устройстве.

Ссылки

Блокнот: https://www.kaggle.com/vladisov/bird-species-inspired-by-fast-ai
Блокнот Fast.ai: https://www.kaggle.com/code/vladisov/is-it-a-bird-creating-a-model-from-your-own-data/

Оцените статью
devanswers.ru
Добавить комментарий