Программирование глубоких нейронных сетей на Python. Моделируем глубокую нейронную сеть ResNet34

Начинаем строить модель с чистого листа, вернее с чистого нового виртуального ноутбука Colabolatory!

Наша первая модель нейронной сети: быстрый старт

Для облегчения решения задачи моделирования нейронной сети, мы будем использовать предварительно подготовленную модель глубокой нейронной сети ( например ResNet34), то есть модель, уже созданную и которая выиграла конкурс ImageNet 2015 года. 
Вместо того, чтобы нам создавать модель с нуля для решения нашей проблемы, мы будем использовать модель, подготовленную на ImageNet (1,2 миллиона изображений и 1000 классов) в качестве отправной точки. Модель представляет собой сверточную нейронную сеть (англ. convolutional neural network, CNN), тип нейронной сети, которая строит самые современные модели для компьютерного зрения. Конечно мы можем выбрать любую, из непрерывно пополняемых в библиотеке PyTorch (подпакет torchvision)  моделей нейронных сетей и исследовать ее для решения проблем в той или иной прикладной области.
Проблему которую будет решать наша первая нейронная сеть мы выбрали также довольно известную: как отличить кошку от собаки. По заумному: решение задачи автоматического отнесения предъявленного входного изображения к одному из классов: к классу кошки или к классу собаки.
Запускаем в любом Internet браузере облачный сервис Colaboratory от Google, заводим новый ноутбук в этом сервисе
#Cмотрим корневой каталог виртуального ноутбука Colaboratory:

!ls /
#Обновляем менеджер пакетов pip до версии pip3:

!pip install --upgrade pip

# Устанавливаем пакет FastAI (через 12 часов сервис Colaborator зачистит (удалит-сборка мусора) все установленные Вами пакеты, команда !ls /usr/local/lib/python3.6/dist-packages не покажет папки и файлы пакетов fastai и torch, а команда !pip3 show fastai torch | grep Name -A 1 не укажет их версий так что Вам придется через 12 часов устанавливать пакеты и данные заново:

!pip3 install fastai
# Для взаимодействия программы на языке Python с операционной системой Linux подменим несовместимый модуль os от  Python2 совместимым модулем subprocess от  Python3. Сразу проверим работу модуля, выполнив команду os.uname() и узнаем на какой операционной системе мы работаем:

import subprocess, os
os.uname()

#Импортируем из пакета fastai все * функции модуля conv_learner используемого для обучения выбранной модели сверточной нейронной сети. Например. ResNet-34 и т. д.

from fastai.conv_learner import *

# Посмотрим версии пакетов fastai и torch

!pip3 show fastai torch | grep Name -A 1

#Подключаем и смотрим какой графический процессор (ускоритель) мы подключили, и подключился ли он вообще к нашему ноутбуку Colabolatory:
torch.cuda.set_device(0)
torch.cuda.get_device_name(0)

#Загружаем, с сайта Fast.AI на  наш ноутбук, запакованный файл dogscats.zip c входными данными, то есть большое количество различных изображений кошек и собак, и распаковываем его:

!wget http://files.fast.ai/data/dogscats.zip
!unzip dogscats.zip


# Как мы можем заметить в окошке слева отобразились каталоги train и valid каждый из которых имеет подкаталоги cats и dogs с картинками кошек и собак для обучения нейронной сети  и проверки нейронной сети на предмет нашим ожидания - способностью отличать кошек от собак, то есть проверки на валидацию
Исходя из того что мы будем использовать готовые пакеты программ и моделей нейронных сетей, и разработчики не регламентируют жесткие названия папок и файлов и путей к ним, нам необходимо выполнить процедуры по обезличиванию этих параметров в строковые переменные языка Python:
#Присваиваем  переменной PATH имя папки dogscats/ :

PATH = "dogscats/"

#Выводим на экран содержимое папки  PATH (dogscats/) с помощью функции listdir модуля os:

os.listdir(PATH)


#Присваиваем  переменной CLASSES имя папки {PATH}train/ (dogscats/train) и выводим на экран её содержимое:

CLASSES = os.listdir(f'{PATH}train/')
CLASSES

 

#Выводим на экран 10 элементов списочной переменной train_dogs[:10]предварительно присвоив ей путь PATHtrain/(имя нулевого элемента строковой переменной CLASSES[0]) :  (dogscats/train/catsс помощью метода listdir:

train_dogs = os.listdir(f'{PATH}train/{CLASSES[0]}')
train_dogs[:10]






#Используем основной интерфейс pyplot библиотеки визуализации данных двумерной графики matplotlib языка  Python для отображения картинки:

#Подготовка изображения

import matplotlib.pyplot as plt

train_dogs_img_0 = plt.imread(f'{PATH}train/{CLASSES[0]}/{train_dogs[0]}')

plt.imshow(train_dogs_img_0)

plt.axis('off')

plt.show()

Без сетки: plt.axis('off') : 

Изображение представляет собой многомерный массив  из количества пикселей их яркости и цветовой гаммы) Под «многомерностью» массива мы понимаем то, что у него может быть несколько измерений или осей. Поскольку слово «измерение» является неоднозначным, вместо него мы чаще будем использовать слова «ось» (axis) . Число осей называется рангом (rank) : 


 С выводом методом imshow : 

Посмотрим размеры массива, его форму. Это кортеж натуральных чисел, показывающий длину массива по каждой оси. Для матрицы из n строк и m столбов, shape будет (n,m). Число элементов кортежа shape равно рангу массива, то есть ndim.   train_dogs_img_0[:4][:2] 
# размер обрезки фотографий 244x244 :

sz = 224
 
# Архитектура нейросети
#arch = resnet34 # https://download.pytorch.org/models/resnet34-333f7ec4.pth
#arch = resnet50 # https://download.pytorch.org/models/resnet50-19c8e357.pth



# Подготовка данных (дополнение, сведение размера, обрезке, нормализации)
# aug_tfms (augmentation transforms) - включить дополнения данных
tfms = tfms_from_model(arch, sz, aug_tfms=transforms_side_on, max_zoom=1.2)
tfms
# Организация набора данных для обучения

data = ImageClassifierData.from_paths(PATH, tfms=tfms)
data

# Подготовка нейросети классификатора двух объектов (заменяется последний слой)
# learn = ConvLearner.pretrained(arch, data, precompute=True)
# learn # показывает добавленные слои для полученной модели


learn = ConvLearner.pretrained(arch, data, precompute=True)
learn

Дополнение данных

# Функция для визуализации вариантов дополнения
def get_augs():
data = ImageClassifierData.from_paths(PATH, bs=2, tfms=tfms, num_workers=1)
x,_ = next(iter(data.aug_dl))
return data.trn_ds.denorm(x)[1]


 

# Пакет изображений вариантов
ims = np.stack([get_augs() for i in range(6)])



 

from fastai.plots import *
plots(ims, rows=2)

Нахождение оптимальной скорости обучения

# Вычисление скоростей обучения
learn.lr_find()

 

learn.sched.plot_lr()


# подбирается по максимальному уклону графика потерь (loss)
learn.sched.plot()


# Скорость обучение берётся на порядок меньшим значения, слегка левей самой низкой точки графика

Обучение

# Обучение с подобранной скоростью обучения (данные в папке train)
# 1e-2 - подобранная скорость обучения (0.01)
# 1 - количество циклов (не эпох)
learn.fit(1e-2, 1)


# метки классов
data.val_y 


# классы
data.classes 



# Дополнение данных не работает с предвычисленными активациями
# Для получения своих активаций, используем precompute=False
learn.precompute = False

 

# Снова обучаем, уже без предвычисленных активаций # Указанная скорость обучении (0.01) - максимальная скорость перед автоматическим снижением # cycle_len=1 - за сколько циклов автоматически уменьшается скорость обучения # общее количество эпох = количество циклов * cycle_len learn.fit(0.01, 3, cycle_len=1)



# Результаты обучения в текущих значениях таблицы:

 

  epoch номер эпохи — указывает который раз сеть просматривает обучающий и тестовый наборы кошек и собак  trn_loss ошибки (потери (loss)) на обучающей выборке (тренировка) val_loss ошибки на тестовой выборке (валидация) accuracy точность предсказывания (метрика)
0 0.051173 0.027369 0.989
1 0.043045 0.028862 0.99
2 0.041786 0.027403 0.99

# Если валидационные ошибки больше тестовых — имеем переобучение # Точность (потери, ошибки) — это отношение правильных прогнозов к их общему числу

 

# График изменения скорости обучения
# Видим как работает метод SGDR - стохастический градиентный спуск с перезапусками

learn.sched.plot_lr()
# Разморозка слоёв
learn.unfreeze() # разморозка всех слоёв
#learn.unfreeze_to(n) # разморозка всех слоёв до n-ного
learn.bn_freeze(True) # фиксирует нормализацию минибатчей

# Дифференциальная скорость обучения
# Сейчас используется нейросеть с 3 группами слоёв
# Последний слой с такой же скоростью, каждый предыдущий - на порядок меньше
lr=np.array([1e-4, 1e-3, 1e-2])
# Дообучаем с размороженными слоями
# cycle_mult=2 - во сколько раз увеличивать cycle_len после каждого цикла
learn.fit(lr, 3, cycle_len=1, cycle_mult=2)
# Замечаем, что время обучения сети за один проход составляет в среднем 6,5 минут:


# Всего проходов (epoch - эпох) в нашем случае 7,  время обучения сети составило  39 минут:
# График изменения скорости обучения
# Видим как работает метод SGDR
learn.sched.plot_lr()
 # Метод TTA прогнозирования (test time augmentation)

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

log_preds,y = learn.TTA()
probs = np.mean(np.exp(log_preds),0)



# Точность (метрика)
accuracy_np(probs, y)



Видео лекции с субтитрами на русском языке "Глубокое обучение 2018" от Jeremy Howard, перевод субтитров Екатерина Колодезева . . .

Cтатья на GitHub на русском языке, двух уроков про FastAi (копия notebook jupyter) от  Нави Арх   здесь . . .
torchvision.models - подпакет моделей нейронных сетей: VGG, RESNET, SqueezeNet, DenseNet, Inception v3 . . .

Понимание и реализация архитектур ResNet и ResNeXt для самой современной классификации изображений: от Microsoft до Facebook . . .

Ссылка на форум Fast AI . . .

Matplotlib представляет собой библиотеку 2D-графики Python . . .

Pillow - библиотека изображений Python от Fredrik Lundh и Contributors . . .

Первый и второй уроки по Fast AI для русскоязычной аудитории . . .

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

16 − 4 =

© 2018 Журнал научно-технического творчества педагогов и школьников "Главный конструктор"