Класификацията на изображения е широко проучена област на компютърното зрение, която има за цел да етикетира всяко изображение от набор от данни. Има приложения в голямо разнообразие от области, включително биология, медицина, застраховане, реклама...

Значително предизвикателство при класифицирането на изображения е огромният обем данни, необходими за получаване на резултати. По този начин обучението на модел в компютърното зрение може да бъде много дълго и изискващо изчислителни ресурси. Трансферното обучение е популярна техника за справяне с този проблем. Общата идея е да се използва предварително обучен модел, за да се намали времето за обучение. Все пак обучението на модел за класификация на изображения може да отнеме време и затова е интересно допълнително да ускорим обучението на модела благодарение на нашата технология.

В тази публикация се стремим да дадем ръководство стъпка по стъпка за извършване на трансферно обучение при разпознаване на изображения. Ще покажем как да използваме конволюционна невронна мрежа (CNN) заедно с GPU и CPU за изграждане на модел за класификация на изображения и как да ускорим обучението с OPU (Optical Processing Unit), разработен от LightOn.

В процеса ще опресним метода. В края на този интензивен курс ще можете да оцените как работи тази техника и да я изпълните сами.

Прехвърляне на обучение

В стандартната рамка за обучение за трансфер моделът първо се обучава на голям набор от данни, като ImageNet [1], и след това се настройва фино върху набора за обучение на целевия набор от данни. Фината настройка обикновено се осъществява с алгоритъма за обратно разпространение и изисква избор на различни хиперпараметри, като например броя на епохите на обучение, скоростта на обучение или импулса, без никакви предварителни познания за оптималния избор. Възможно е търсене в мрежата по тези параметри, но изчерпателният анализ за намиране на оптималния набор струва време и енергия.

Конвейерът за обучение на класификатор на изображения с произволни проекции може да бъде разделен на следните стъпки:

  1. Заредете избрания набор от данни и модел.
  2. Извлечете конволюционните характеристики на комплекта влакове.
  3. Извършете произволна проекция на характеристиките в k-измерно пространство. Ще обясним как да изпълните тази стъпка с GPU, но също и с OPU на LightOn.
  4. Поставете линеен класификатор върху произволните характеристики на тестовия набор, като логистичен класификатор.

След обучението оценяваме представянето на модела на тестовия комплект. Първите три стъпки са същите, докато напасването на линейния класификатор се заменя с матрично умножение на тестовите произволни характеристики с теглото на класификатора и прилагане на функцията за вземане на решение.

В следващите раздели ще разгледаме всяка стъпка и ще обясним как да ги кодираме в Python. Ще обясним също как да използваме OPU върху GPU, за да ускорим значително обучението на модел в сравнение с обучението, реализирано само с GPU или CPU.

Зареждане на данни и модел

Нека започнем със зареждане на данните за нашата целева задача. Използваме набора от данни STL10, наличен в пакета torchvision, който се състои от 5000 изображения на влакове и 8000 тестови изображения от 10 различни класа. Общ преглед е наличен на фигура 3.

Започваме със задаване на следните параметри:

- root: път към директорията с данни. Ако няма набор от данни, той ще бъде изтеглен тук;

- transforms за прилагане към всяка проба. Използваме проста нормализация и преоразмеряваме изображенията до (224, 224);

- batch_size: размер на партидата за броя на пробите, които трябва да се обработват едновременно;

- num_workers: брой процесорни ядра, които да се използват от DataLoaders.

Ние използваме DenseNet169[2], предварително обучен на ImageNet, наличен в библиотеката torchvision.

Също така настройваме устройството за всякакви бъдещи изчисления: можем или да изберем cpu, ако искаме да извършим всички изчисления на CPU, или cuda:x, ако работим с машина с един или повече GPU. В последния случай използваният GPU ще бъде числото x, обикновено започващо от 0. Например, ние използваме GPU номер 0 в нашия код, като напишем cuda:0.

Тъй като не се нуждаем от линейния участък в края, избираме само конволюционната част на CNN с .features. Освен това, за да оптимизираме количеството памет, разпределено на GPU за задачата, ние предаваме фиктивен вход през мрежата, за да получим размера на конволюционните функции. За DenseNet169, обучен на (224, 224) изображения, изходният размер ще бъде 81536.

Извличане на конволюционните функции

Следващата стъпка се състои от извличане на конволюционните характеристики на набора за обучение и тест, за да се извърши произволната проекция с GPU или OPU.

Това става със следното извикване на функция:

Разпределяме матрица conv_features с размер (num_images, out_shape) за конволюционните характеристики на влака или тестовия набор и вектор labelsс дължина num_imagesза етикетите. Преглеждаме всички изображения в товарача и съхраняваме конволюционните характеристики и съответните етикети в тези две матрици.

И накрая, ние използваме базирано на знаци кодиране за конволюционните функции, където положителните числа се съпоставят с 1, а останалите с 0. Ние също така измерваме времето както за извличане на характеристики, така и за кодиране с библиотеката time в python. Всички извиквания към time се предшестват от torch.synchronize(), за да се гарантира, че времената се изчисляват правилно, ако се използва GPU, тъй като операциите на GPU се изпълняват асинхронно.

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

Извършване на произволна проекция

Произволна проекция: просто като умножение

Можем да извършим произволната проекция на GPU или OPU. Напомняме, че случайната проекция се състои в умножение с фиксирана матрица R, чиито записи са извлечени от нормално разпределение, както в следната формула:

Y = |XR|²

Матрицата X с размер (n*m), съдържаща конволюционните характеристики, се проектира в k-измерно пространство. Ако k › m, характеристиките ще бъдат проектирани в пространство с по-високо измерение, където могат да бъдат линейно разделими. Това е свойство, изключително за нелинейни произволни проекции. Ако k ‹ m, размерът на характеристиките ще бъде намален, ускорявайки обучението на линейния класификатор, който следва за сметка на крайната точност.

По-долу изследваме първата ситуация, като зададем k=120000.

С графичен процесор

Нека първо започнем с GPU. Започваме с генериране на случайна матрица с размер (out_shape , n_components), където n_components е броят на произволните проекции. Разделяме матрицата на 10 блока, тъй като ще трябва да преместим тази матрица в паметта на графичния процесор заедно с матрицата на конволюционните характеристики и може да няма достатъчно място и за двете.

Избираме 120 000 като брой произволни функции и генерираме произволната матрица:

След като генерираме матрицата, можем да извършим проекцията. Ние умножаваме всеки блок от произволната матрица с матрицата на конволюционните характеристики и свързваме частичните изходи, за да получим крайния резултат.

За да получим произволната матрица на характеристиките за набора от влак/тест и времето за проекция, ние извикваме:

С OPU

Нека сега извършим същата операция с OPU.

За извършване на произволна проекция с OPU използваме библиотеката lightonml, която предоставя прост API на python за извършване на произволни проекции с OPU на LightOn.

На първо място, импортираме OPUMap обекта от lightonmlбиблиотеката и създаваме екземпляр на класа, като предаваме броя на произволните проекции n_components като аргумент.

Просто извикване на opu.transform(X) извършва произволната проекция на входната матрица X, съдържаща конволюционните характеристики на набора от влак/тест. Ние съхраняваме изходната матрица в променливата random_features.

Ние също така измерваме продължителността на проекцията с библиотеката time, налична в python.

Тъй като извикването е синхронно, няма нужда да извиквате torch.synchronize() преди изразите за време, както направихме за конволюционните функции.

След проекцията характеристиките, произведени от OPU, са във формат uint8 . Въпреки че не е строго необходимо, удобно е да ги преобразувате в float32, тъй като много алгоритми в python, като вътрешността на функцията за прилягане на някои scikit-learn класификатори, са оптимизирани за този тип данни.

Последното извикване на функция за получаване на произволни функции за обучение/тест с OPU на LightOn е следното:

Поставяне на класификатора

Сега можем просто да напаснем линеен класификатор върху обучителните функции и да оценим ефективността му върху тестовия набор. Избрахме RidgeClassifier, наличен в scikit-learn, поради бързото му внедряване в сравнение с други класификатори като логистична регресия.

Създаваме RidgeClassifierобект и предаваме като аргумент коефициента на регулиране alpha. Можем да го зададем чрез кръстосано валидиране, но обикновено стойности, близки до 1e6са склонни да дават доста добри резултати с OPU на LightOn. Ако се използва GPU, тази стойност трябва да бъде намалена до 1e3.

Резултати

В този цикъл получаваме 96,50% точност на тестовия набор чрез извършване на произволна проекция с OPU на LightOn, срещу 96,9% при използване на GPU. Тъй като наборът от данни STL10 има 8000 тестови изображения, разликата между 96,5% и 96,9% точност на теста се състои само от още 32 грешни класификации.

Тук ясно виждаме, че резултатите, получени с OPU и GPU, са доста близки, ако сравним един модел. Въпреки това, няма сравнение, когато става въпрос за времето. За да извършим проекцията върху GPU, трябва първо да генерираме произволната матрица и да я разделим на блокове, което отнема 430 s за матрицата с размер (81536, 120000), използвана в този експеримент. Действителната произволна проекция отнема 30,3 s върху конволюционните характеристики на тестовия набор, докато OPU извършва същата проекция за 8,5 s, за 3,5x ускорение. Освен това OPU няма нужда да генерира произволна матрица, което означава, че достигаме 54x ускорение, ако вземем предвид процеса на генериране.

Това означава, че можем да отделим времето, необходимо за обучение на един модел с GPU, за да обучим множество модели с OPU на LightOn. Можем дори да комбинираме множество модели много бързо и по този начин да подобрим точността на крайния класификатор.

Заключение

В тази публикация в блога ние показваме метод за обучение на класификатор на изображения с трансферно обучение, използвайки произволни проекции както на GPU, така и на OPU.

Обучението с двете устройства дава същото ниво на точност, но OPU драстично намалява времето за обучение поради липсата на необходимост от генериране на произволна матрица и е по-бърз при извършване на действителното умножение на матрицата.

Не чакайте повече да ускорите работата си, елате и опитайте нашия OPU чрез LightOn Cloud, проста платформа, създадена за вас да кодирате своите модели за машинно обучение. Кандидатствайте сега, за да използвате LightOn Cloud.

Ако искате да проверите кода и да го стартирате, ето „връзката към бележника на Jupyter“.

За нас

LightOn е хардуерна компания, която разработва нови оптични процесори, които значително ускоряват изчисленията с машинно обучение. Процесорите на LightOn откриват нови хоризонти в компютърните и инженерните области, които са изправени пред изчислителни ограничения. Интересувате ли се от ускоряване на вашите изчисления? Изпробвайте нашето решение на LightOn Cloud! 🌈

Моля, следвайте ни в Twitter на адрес @LightOnIO, абонирайте се за нашия бюлетин и/или се регистрирайте за нашата серия от семинари. Ние предаваме на живо, така че можете да се присъедините отвсякъде. 🌍

Автора

Лука Томасоне, инженер по машинно обучение в LightOn AI Research.

Благодарности

Благодарим на Igor Carron, Victoire Louis, Iacopo Poli и François Boniface за прегледа на тази публикация в блога.

Препратки

[1]Олга Русаковски*, Джиа Денг*, Хао Су, Джонатан Краузе, Санджив Сатиш, Шон Ма, Джихен Хуанг, Андрей Карпати, Адитья Хосла, Майкъл Бърнстейн, Александър К. Берг и Ли Фей -Фей. (* = равен принос) ImageNet Large Scale Visual Recognition Challenge. Международен журнал за компютърно зрение, 2015 г.

[2]Huang, G., et al. „Плътно свързани конволюционни мрежи. arXiv 2017.“ предпечат на arXiv arXiv:1608.06993