Четох много за fastai, особено през последните няколко седмици и трябва да кажа, че има някои наистина интересни неща в тази библиотека. Благодаря на JermyHowardи RachelThomasи общността на fastai за популяризиране на материала и най-съвременните техники публични и достъпни за всеки и направяне на невронните мрежи отново неудобни😉 .

Този конкретен блог (първият от много) се занимава със създаването на класификатор Куче срещу Котка от нулата. Една от най-трудните части при изграждането на всяко приложение за наука за данни е събирането на набори от данни за обучение и тестване. Разбира се, има примерни стандартни набори от данни като Titanic, iris, Mnist и т.н., лесно достъпни за тестване на производителността на различни модели. Но когато искате да изградите модел от нулата за конкретен случай на употреба в реалния свят, това може да бъде най-трудната и отнемаща много време част. За щастие имаме идеалното решение за създаване на общи приложения, което също се оказва много интуитивно, когато го погледнете от човешка гледна точка. Кажете, че искате да накарате едно дете да разбере как изглежда котка или куче. Как бихте направили това? Най-естественият отговор би бил да потърсите в Google снимки на котки и кучета и да ги покажете на детето, обяснявайки мисловния процес, който преминава в класифицирането им в съответните етикети. Ние в този блог ще следваме точно същото, за да изградим класификатор. Ще извлечем резултатите от изображенията от търсачка и ще ги съхраним като входни данни, които по-късно ще бъдат използвани за обучение на нашия класификатор.

Ние ще използваме bing като наша търсачка за този конкретен случай на употреба. Ще трябва да се регистрирате за когнитивни услуги на Azure (това е напълно безплатно, ако сте студент, ако не, ще трябва да въведете данните на кредитната си карта, но няма да бъдете таксувани за първата година или повече), което по-късно ще ви даде достъп към ключ за търсене в bing.

API за търсене на изображения в Bing

Следното е ценовото ниво на Bing seach api. Както можете да видите, той ви позволява да правите 1K обаждания на месец безплатно, което е много повече от това, от което всеки би се нуждаел за случаи на употреба като този. (щракнете тук за документация на API)

След като имаме ключа, можем да преминем към кодиращата част за това как да извличаме изображения с помощта на този API. Ще използваме ключовата дума като коткаикуче, за дапълзим в резултатите от търсенето.

Първото и най-важно нещо, което трябва да направим, е да импортираме всички предварително дефинирани помощни функции от fast ai.

pip install -Uqq fastbook
import fastbook
fastbook.setup_book()
import requests
from fastai.vision.all import *
from fastai.vision.widgets import *
from pathlib import Path

Изтегляне на изображения чрез Bing

След това използваме API от bing, за да изтеглим всички снимки за котки и кучета за нашия модел. За щастие, заявки е единствената библиотека, която ще бъде полезна тук. fastai има собствена функция за търсене на изображения в bing, но по някаква причина имаше някои грешки (в най-новата версия това е коригирано). Така че направих малко проучване и създадох моя собствена помощна функция, за да приложа това.

Горната функция връща dict, който съдържа цялата информация за търсенето, направено с помощта на дадената ключова дума. Частта, която ни интересува най-много, е URL адресът на тези изображения. Това може да бъде достъпно чрез results.attrgot(‘contentUrl’)къдеторезултатие резултатът от функциятаcustom_search_images_bing.

Направих някои помощни функции, които създават папка, наречена DATA с име на категория (animals) и подпапки като имена на етикети (cat и dog) изтегля изображенията в съответните подпапки въз основа на етикетите.

Функцията download_relevant_images изтегля изображенията в тези подпапки и clean_label_imagesпроверява за повредени изображения в папката и ги изтрива от папката.

Ето! Вече разполагаме с данните, необходими за обучение/фина настройка на нашия модел, готови и настроени да работят точно така!

Обработка на данни и обучение на модела.

За да обучим модел с помощта на библиотека fastai, трябва да дадем зареждащи данниобекткато вход към модела. Зареждане на данни е по същество клас, който съхранява обект на зареждане на данни (train и valid), който помага на модела да се обучава на подмножеството трениране и проверете ефективността чрез кръстосано валидиране с помощта на валидното подмножество. Ако трябваше да направим това без fastai, обикновено бихме използвали

from sklearn.model_selection import train_test_split

Но fastai има предварително дефинирани библиотеки, които правят всичко това автоматично, докато създават обект за зареждане на данни. И така, как да създадем обект за зареждане на данни?

За да превърнем нашите изтеглени данни в DataLoaders обект, трябва да кажем на fastai поне четири неща:

С какви видове данни работим?

Как да получите списъка с елементи?

Как да етикетирате тези елементи?

Как да създадете набора за валидиране?

Ние използваме API за блокиране на данни, за да посочим гореспоменатите неща, за да създадем обект за зареждане на данни.

db = DataBlock( 
blocks=(ImageBlock, CategoryBlock), 
get_items = get_image_files, 
splitter = RandomSplitter(valid_pct=0.2, seed=42), 
get_y = parent_label, 
item_tfms=Resize(128))

блокове:Взема входа като кортеж (структурата на данните (таблични, изображения и т.н.), тип данни (категорични, непрекъснати))

get_items: Това се използва, за да се каже на блока с данни как да получи достъп до данните, създадени от нас. get_image_files е предварително дефинирана бърза функция, която приема входа като променлива Path и извежда списък с променливи Path, съдържащ местоположението на изображенията.

Разделител:използва се за указване на валидния раздел на влака

get_y :как точно картографираме изображенията с етикетите? parent_label е друга функция, която приема етикета като име на parent_folder

item_tfms:Това се използва за трансформиране на всички изтеглени изображения до 128x128 пиксела, за да се запази еднаквостта.

Сега имаме блок от данни, готов да бъде преобразуван в обект за зареждане на данни, който може да бъде въведен в модела за обучение.

Но изчакайте, има ли още нещо, което можем да направим за изображенията, за да подобрим представянето на модела?

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

Различните изображения може да съдържат основния елемент в картината на различни места.

Пример: По-горе са 2 различни снимки на котки. В този отляво котката е разположена от лявата страна, а в дясната - малко вдясно. Тъй като тези вариации присъстват до голяма степен в изображенията, има смисъл естествено произволно да изрязвате изображения, за да уведомите модела, независимо къде присъства котката, картината все още трябва да бъде етикетирана като котка. Това също ни помага да създадем повече точки за данни с ограничените данни, с които разполагаме. Това се постига чрез RandomResizedCrop

db = db.new(        
item_tfms=RandomResizedCrop(224, min_scale=0.5),        batch_tfms=aug_transforms()
)
dls = db.dataloaders(path)

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

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

Изграждане на модел

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

Е, оказва се, че има много по-лесен начин за обучение на модел.

Когато създавате модел, ние използваме инициализация на произволни тегла, дефинираме функция на загуба и продължаваме да обучаваме модела, като променяме теглата, използвайки градиентите, които получаваме чрез диференциране на функцията на загуба. Това отнема много време, за да се изгради точност с течение на времето и може също така да доведе до грешки при използване на малки набори от данни. Вместо това можем да използваме концепцията за Transfer Learning, да използваме архитектурата и теглата, използвани от модели, направени за подобни цели, да заменим последния слой с етикетите, подходящи за нашия случай на употреба и да го обучим отново за n епохи. Една епоха позволява на модела да актуализира тегла въз основа на градиентите, получени от функцията за загуба и въведената скорост на обучение.

cnn_learner: предварително дефинирана бърза функция, използвана за обучение на модели с данни за типа на изображението (която използва концепция за конволюционна невронна мрежа). Предварително обученият модел, използван тук, е resnet18.

Тук, в process_and_train.py,ние създаваме обект за обработка на данни и въвеждаме същия в модела (научаване). След това използваме learn.fine_tune(4), за да обучим модела отново, като използваме новите данни за 4 епохи и след това запазваме модела под името „animals_prediction.pkl“. Забележете, че имаме metrics = error_rate за този конкретен случай на употреба, което е основно броят на класификациите, които правим грешни за общия брой въведени изображения. При стартиране на това получаваме точност над ~99%, което е наистина добро.

Оценяване на модела

Можем да оценим модела и чрез изграждане на матрица на объркване, използвайки следните команди.

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

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

interp.plot_top_losses(5, nrows=1)

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

Модел към приложение

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

Как да направите това достъпно за вашите връстници, за да покажете работата, която сте свършили?

Чрез интернет разбира се! Сега трябва да направим уеб приложение, което може да бъде хоствано в уебсайт, достъпен за всеки, където човек може да качи снимка на котка/куче и ние извеждаме предвидения етикет с необходимите показатели.

Нашият модел се съхранява като „animals_prediction.pkl“. Това е основната информация, необходима за предсказване на класа на картина. Можете да предвидите класа на всяко изображение, като използвате следните команди.

learn_inf = load_learner('animals_prediction.pkl')
learn_inf.predict(path_to_img)

load_learner :Това зарежда съхранения модел, който по-късно се използва за прогнозиране на етикетите на качени изображения с помощта на learn_inf.predict() (което извежда прогнозирания етикет заедно с показателя за вероятност)

Има няколко начина, по които можете да превърнете своя модел в приложение. В това упражнение използвахме flask, който е библиотека на Python за изграждане на уеб приложения.

Има 3 функции, използвани в това приложение (2 от тях са свързани с @app.route())

model_predict() :Тази функция е много проста, просто приема входните данни като img_path и model_path и извежда низ с етикети pred и стойност на вероятността като prob_value.

index() :Това е основната начална страница на уебсайта (нека я наречем базова страница), която изграждаме, която е подкрепена от html файла index.html. Тази уеб страница предоставя бутон за качване, където потребителят може да качва изображения от собствената си система в уеб сървъра, за да използва приложението. След като потребителят щракне върху бутона Predict!, той го пренасочва към базова страница/предсказаниезаедно с въведеното изображение. Тук влиза в действие функцията upload().

upload() :Това приема въведеното изображение, съхранява го локално в сървъра (под името test.jpg) и след това използва изображението като вход към model_predict() , получава изходния низ с етикети и вероятности и го отпечатва под каченото изображение в основната страница.

Ако стартирате следния файл в терминала, можете да проверите локално хостваното приложение във вашия браузър под връзката ( http://127.0.0.1:5000/') .

За статични и html файлове разгледайте моето git repo тук

За да го хоствате глобално, ще трябва да качите това хранилище в Github (Регистрирайте се, ако нямате такова). Можете да качите хранилището чрез опцията за добавяне на файлове, отбелязана на снимката.

След като приключите с качването на файловете в git, трябва да замразите изискванията, като използвате pipreqs, като използвате командата

pipreqs path/to/python_project

Това ще създаде файл requirements.txt, който ще позволи на сървъра (използван за създаване на уебсайта) да разбере какви библиотеки трябва да бъдат инсталирани, преди да стартира приложението. Трябва също така да създадете файл, наречен Procfileкойто се използва за комуникация на уеб сървъра кой файл съдържа приложението.

Сега всичко, което остава, е внедряване в heroku (Ако нямате акаунт в heroku, моля, създайте такъв).

Кликнете върху create new app на таблото за управление на heroku и му дайте име. Отворете приложението, което сте създали, и щракнете върху опцията Deploy. Трябва да можете да видите опция за свързване на вашето git repo с heroku.

Бих посъветвал да отида за ръчно внедряване, само защото не искам моите ангажименти да се отразяват директно върху моето приложение, освен ако не му дам разрешение да го направи или кажа, че ако ангажирате грешен код без проверка, ще бъде трудно да го върна обратно след разгръщане. След като внедряването приключи, Воала! можете да закупите приложението си на адрес https://your-app-name.herokuapp.com/ .

Можете да проверите приложението, което създадох за блога тук.

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

— Чакайте, очаквайте още такива интересни неща скоро. Дотогава сбогом 😉

Моля, харесайте и споделете репото и блога, ако ви е харесало да прочетете това.

P.S. — В случай, че се интересувате, разгледайте кода тук ( Не забравяйте⭐ репото, ако го намерите за полезно😉)