Давайте установим среду в google colab.

Проверьте мой файл ipynb здесь!

#hide
! [ -e /content ] && pip install -Uqq fastbook
import fastbook
fastbook.setup_book()
#hide
from fastbook import *
from fastai.vision.widgets import *

Сбор данных через DuckDuckGo API

bear_types = 'grizzly','black','teddy' # define types of bear that we'd like to download the images
path = Path('bears')
if not path.exists():
  path.mkdir()  # create a directory to save downloaded images
  for o in bear_types:
    dest = (path/o)
    dest.mkdir(exist_ok=True)
    urls = search_images_ddg(f' {o} bear') # search images through DuckDuckGo
    download_images(dest, urls=urls) # download all the URLs for each of our search terms. We'll put each in a separate folder
fns = get_image_files(path) # 
fns
(#568) [Path('bears/teddy/f97da50d-4f1a-4a62-ad93-0575d8fe92ae.jpeg'),Path('bears/teddy/669d7bba-02a8-411e-b70f-b8bd82628121.jpg'),Path('bears/teddy/af9a2a15-07e5-4a3b-a202-e89856d7d42a.jpg'),Path('bears/teddy/22e4d7e7-fb15-4244-9ebd-d10f1af97624.jpg'),Path('bears/teddy/f2191ec9-fc7c-43f4-b9bf-57cdbb703354.jpg'),Path('bears/teddy/473cc5d8-11cb-40aa-b478-e054edfda62e.jpeg'),Path('bears/teddy/4aa392b2-c12b-4c23-8cce-67bebfdd7d80.jpg'),Path('bears/teddy/525f957c-446c-4308-97cb-ad052405d51a.jpg'),Path('bears/teddy/3c6208c5-20cc-49bf-a428-8703fc9af235.jpg'),Path('bears/teddy/91282a54-eafa-44e0-82bb-a610d8625141.jpg')...]
# Often when we download files from the internet, there are a few that are corrupt. Let's check:
failed = verify_images(fns)
# remove all the failed images
failed.map(Path.unlink)
(#0) []

От данных к загрузчикам данных

bears = DataBlock(
    # provide a tuple where we specify what types we want for the independent and dependent variables:
    blocks=(ImageBlock, CategoryBlock), # What kinds of data we are working with
    get_items=get_image_files, # How to get the list of items
    splitter=RandomSplitter(valid_pct=0.2, seed=42), # How to create the validation set
    get_y=parent_label, # How to label these items, gets the name of the folder a file is in
    item_tfms=Resize(128)) # Transformation: picture resize
​
dls = bears.dataloaders(path) # the path where the images can be found
dls.train.show_batch(max_n=4, nrows=1) # check training set
dls.valid.show_batch(max_n=4, nrows=1) # check validation set
dls.show_batch(max_n=4, nrows=1) # check data
​

Различные типы преобразования изображения

Изменить размер

1. Изменить размер по умолчанию

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

2. Заполните изображения нулями (черными)

bears = bears.new(item_tfms=Resize(128, ResizeMethod.Pad, pad_mode='zeros')

3. Сжать/растянуть изображения:

bears = bears.new(item_tfms=Resize(128, ResizeMethod.Squish)

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

RandomResizedCrop

item_tfms=RandomResizedCrop(128, min_scale=0.3)

Увеличение данных

batch_tfms=aug_transforms(mult=2)

# Default
dls.valid.show_batch(max_n=4, nrows=1)
# Pad
bears_pad = bears.new(item_tfms=Resize(128, ResizeMethod.Pad, pad_mode='zeros'))
dls_pad = bears_pad.dataloaders(path)
dls_pad.valid.show_batch(max_n=4, nrows=1)
# Squish
bears_squish = bears.new(item_tfms=Resize(128, ResizeMethod.Squish))
dls_squish = bears_squish.dataloaders(path)
dls_squish.valid.show_batch(max_n=4, nrows=1)
# RandomResizedCrop
​
# min_scale: determines how much of the image to select at minimum each time:
bears_random = bears.new(item_tfms=RandomResizedCrop(128, min_scale=0.3))
dls_random = bears_random.dataloaders(path)
dls_random.train.show_batch(max_n=4, nrows=1, unique=True)
# unique=True to have the same image repeated with different versions of this RandomResizedCrop transform.
# Data Augmentation
bears_aug = bears.new(item_tfms=Resize(128), batch_tfms=aug_transforms(mult=2))
dls_aug = bears_aug.dataloaders(path)
dls_aug.train.show_batch(max_n=8, nrows=2, unique=True)

Сохраните модель и используйте ее для очистки ваших данных

bears = bears.new(
    item_tfms=RandomResizedCrop(224, min_scale=0.5),
    batch_tfms=aug_transforms())
dls = bears.dataloaders(path)
learn = vision_learner(dls, resnet18, metrics=error_rate)
learn.fine_tune(4)​

Проверка ошибок

1. матрица путаницы

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

interp = ClassificationInterpretation.from_learner(learn)
interp.plot_confusion_matrix()

2. plot_top_losses

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

Потеря — это число, которое больше, если модель неверна (особенно если она также уверена в своем неправильном ответе) или если она верна, но не уверена в своем правильном ответе.

interp.plot_top_losses(5, nrows=1)

Чистые данные после проверки ошибки модели

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

fastai включает в себя удобный графический интерфейс для очистки данных под названием ImageClassifierCleaner, который позволяет вам выбрать категорию и набор для обучения и проверки, а также просмотреть изображения с наибольшей потерей (по порядку), а также меню, позволяющие выбирать изображения для удаления или перемаркировки:

#hide_output
cleaner = ImageClassifierCleaner(learn)
cleaner

  • ImageClassifierCleaner на самом деле не удаляет или не изменяет метки за вас; он просто возвращает индексы элементов для изменения.
  • Чтобы удалить (отвязать) все изображения, выбранные для удаления, мы должны запустить:

for idx in cleaner.delete(): cleaner.fns[idx].unlink()

  • Чтобы переместить изображения, для которых мы выбрали другую категорию, мы должны запустить:

for idx,cat in cleaner.change(): shutil.move(str(cleaner.fns[idx]), path/cat)

Применение модели

Использование модели для вывода

модель состоит из двух частей:

  • архитектура
  • обученные параметры

Результат прогноза:

  • ('grizzly', TensorBase(1), TensorBase([0.0546, 0.9432, 0.0022]))
  • прогнозируемая категория в том же формате, который вы указали изначально (в данном случае это строка)
  • индекс прогнозируемой категории
  • вероятности каждой категории.
  • Последние два основаны на порядке категорий в словаре DataLoaders; то есть сохраненный список всех возможных категорий. Во время вывода вы можете получить доступ к DataLoaders как к атрибуту Learner:

learn_inf.dls.vocab

Outcome: (#3) ['black','grizzly','teddy']

learn.export() # fastai will save a file called "export.pkl"
​
# check if the file exists
path = Path()
path.ls(file_exts='.pkl')
(#1) [Path('export.pkl')]

Разверните приложение в блокноте

# create our inference learner from the exported file
learn_inf = load_learner(path/'export.pkl')
# get predictions for one image at a time
learn_inf.predict('images/grizzly.jpg')
('grizzly', TensorBase(1), TensorBase([0.0546, 0.9432, 0.0022]))

Ссылка

Практическое глубокое обучение для кодеров — 2: Развертывание