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

Бързи кучета срещу котки

Ето един процес от край до край, за да получите най-съвременния резултат за кучета срещу котки:

PATH = "data/dogscats/"

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

Забележка: Не сме задали pre_compue=True. Това е пряк път, който кешира някои от междинните стъпки, които не трябва да се преизчисляват всеки път и могат да бъдат пропуснати. Когато pre_compute=True, увеличаването на данните не работи.

learn.unfreeze() 
learn.bn_freeze(True) 
%time learn.fit([1e-5, 1e-4,1e-2], 1, cycle_len=1)

bn_freeze — Ако използвате по-голям по-дълбок модел като ResNet50 или ResNext101, т.е. нещо с номер, по-голям от 34 в набор от данни, който е много подобен на ImageNet, т.е. странични снимки на стандартен обект, чийто размер е подобен на ImageNet между 200–500 пиксела, трябва да добавите този ред. Това кара пълзящите средни за нормализиране на пакета да не се актуализират.

Използване на други библиотеки — Keras

Точно както fast ai седи върху pytorch, keras се намира върху TensorFlow, MXNet, CNTK и т.н.

Трябва да инсталирате Keras или tensorflow като бекенд:

pip install tensorflow-gpu keras

Внос:

import numpy as np
from keras.preprocessing.image import ImageDataGenerator
from keras.preprocessing import image
from keras.layers import Dropout, Flatten, Dense
from keras.applications import ResNet50
from keras.models import Model, Sequential
from keras.layers import Dense, GlobalAveragePooling2D
from keras import backend as K
from keras.applications.resnet50 import preprocess_input

Път на данните:

PATH = "data/dogscats/"
sz=224
batch_size=64
train_data_dir = f'{PATH}train'
validation_data_dir = f'{PATH}valid'

Keras използва идеята за папка за влак и папка за валидиране с подпапки с имена на етикети.

Keras изисква много повече код и много повече параметри, които трябва да бъдат зададени.

train_datagen = ImageDataGenerator(preprocessing_function=preprocess_input,
    shear_range=0.2, zoom_range=0.2, horizontal_flip=True)
test_datagen = ImageDataGenerator(preprocessing_function=preprocess_input)
train_generator = train_datagen.flow_from_directory(train_data_dir,
    target_size=(sz, sz),
    batch_size=batch_size, class_mode='binary')
validation_generator = test_datagen.flow_from_directory(validation_data_dir,
    shuffle=False,
    target_size=(sz, sz),
    batch_size=batch_size, class_mode='binary')

Вместо да създавате един обект с данни, в Keras вие дефинирате DataGenerator, което указва как да генерирате данните, също така указвате какъв вид увеличаване на данните искаме да направи (shear_range=0.2, zoom_range=0.2, horizontal_flip=True) и също какъв вид нормализиране (preprocessing_function=preprocess_input)да направи. С други думи, в Fast .ai, можем просто да кажем „каквото изисква ResNet50, просто го направете за мен, моля“, но в Keras трябва да знаете какво се очаква. Няма стандартен набор от разширения.

train_generator — генерира изображения, като гледа от директория, задава размера на изображенията и размера на мини партидите и класа. Когато тренирате, вие произволно пренареждате изображенията, показват, че са показани в различен ред, за да ги направите произволни чрез разбъркване.

class_mode= ‘binary’ — ако имате 2 възможни изхода, използвайте двоичен код, ако е няколко, кажете ‘categorical’

train_generator — генерира изображения, като гледа от директория, задава размера на изображенията и размера на мини партидите.

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

Създаване на модел

base_model = ResNet50(weights='imagenet', include_top=False)
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
predictions = Dense(1, activation='sigmoid')(x)

Използваме ResNet50, тъй като keras няма ResNet34. За keras не можете да му кажете да създаде модел, подходящ за определен набор от данни. Трябва да го направите на ръка.

Първо създайте base_model, след това изградете слоеве, които искате да добавите към него, т.е. x в този случай добавяме 3 слоя.

Замразяване на слоеве и компилиране на модел

model = Model(inputs=base_model.input, outputs=predictions)
for layer in base_model.layers: layer.trainable = False
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy'])

layer.trainable=False — преминете през слоевете и замразете с помощта на .trainable = False

Компилиране на модел чрез предаване на optimizer, който искате да използвате, loss за търсене и metric за използване.

Монтаж

%%time
model.fit_generator(train_generator, train_generator.n // batch_size, epochs=3, workers=4,
        validation_data=validation_generator, validation_steps=validation_generator.n // batch_size)

Обадете се на fit_generator и предайте train_generator и validation _generator

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

Фина настройка

Размразете някои слоеве, компилирайте и след това поберете отново.

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

split_at = 140
for layer in model.layers[:split_at]: layer.trainable = False
for layer in model.layers[split_at:]: layer.trainable = True
model.compile(optimizer='rmsprop', loss='binary_crossentropy',
    metrics=['accuracy'])
%%time
model.fit_generator(train_generator, train_generator.n // batch_size, epochs=1, workers=3,
        validation_data=validation_generator, validation_steps=validation_generator.n // batch_size)

След фина настройка трябва да компилирате отново модела, след което да го направите.

Изпращане на резултати на Kaggle

В състезание по kaggle това е част, наречена оценка, която описва как ще бъде оценено състезанието:

За набори от данни, където етикетите са в различни папки, използвайте ImageClassifierData.from_paths. Ако имате aCSV файл с етикети, използвайте ImageClassifierData.from_csv.

За да създадете изпращане, трябва да използвате:

data.classes : съдържа всички различни класове

data.test_ds.fnames : съдържа имена на тестови файлове

Добра идея е да използвате тестово увеличаване на времето (TTA). Използвайки is_test=True, той ще ви даде прогнози за тестовия набор, а не за валидиращия.

log_preds, y = learn.TTA(is_test=True) 
probs = np.exp(log_preds)

Повечето модели на PyTorch ще ви върнат дневника на прогнозите, така че трябва да направите np.exp(log_preds), за да получите вероятността.

probs.shape #(n_images, n_classes(breeds))
(10357, 120)

Преобразувайки матрицата във формата kaggle, използваме рамка от данни на pandas:

df = pd.DataFrame(probs)
df.columns = data.classes

Създайте рамка с данни на pandas и предайте матрицата (probs). Задайте имената на колоните да бъдат data.classes

df.insert(0, 'id', [o[5:-4] for o in data.test_ds.fnames])

Вмъкнете нова колона на позиция нула с име id, която съдържа имената на файловете. Ето как изглежда името на файла. test/ab2520c527e61f197be228208af48191.jpg’ . Премахнете първите 5 и последните 4 букви, за да получите идентификаторите.

Разглеждане на рамката с данни:

SUBM = f'{PATH}/subm/'
os.makedirs(SUBM, exist_ok=True)
df.to_csv(f'{SUBM}subm.gz', compression='gzip', index=False)

Обадете се на df.to_csv, за да създадете CSV файл и да го компресирате с помощта на compression=’gzip’. Това записва файла в услугата. Можете да използвате kaggle CLI, за да изпратите, като използвате тази команда$ kg submissions или да я изтеглите на вашия компютър и да я качите в kaggle, за да направите това, като използвате FileLink(f’{SUBM}subm.gz’). Което ще ви даде връзка за изтегляне на файла от сървъра на вашия компютър.

Индивидуална прогноза

Пускане на едно изображение през модел, за да получите прогноза.

отваряне на първия файл в набора за валидиране:

fn = data.val_ds.fnames[0]
fn
'train/000bec180eb18c7604dcecc8fe0dba07.jpg'
Image.open(PATH + fn).resize((150, 150))

Изпълнение на прогнозата:

trn_tfms, val_tfms = tfms_from_model(arch, sz)
im = val_tfms(open_image(PATH + fn)) # open_image() returns numpy.ndarray
preds = learn.predict_array(im[None])
np.argmax(preds)

Изображението трябва да се трансформира. tfms_from_model връща трансформации за обучение и трансформации за валидиране. В този случай ще използваме валидираща трансформация.

Всичко, което се предава или връща от модел, обикновено се приема, че е в минипартида. Тук имаме само едно изображение, но трябва да го превърнем в мини-партида от едно изображение. С други думи, трябва да създадем тензор, който не е просто [rows, columns, channels], а [number of images, rows, columns, channels]. Чрез индексиране в масив с im[None], който добавя допълнителна единична ос към началото, като по този начин го превръща от изображение в мини партида изображения.

Теория на конволюционната невронна мрежа

Ето видео за визуализация на невронна мрежа Convolution от Otavio Good, създател на Word Lens.

Ако въведете изображение, компютърът го разпознава като числа (пиксели).

Входен слой

Тези данни за изображение номер 7 са от базата данни MNIST и ние предполагаме, че използвате модел преди влака за класификацията.

Скрит слой 1

Скритият слой е това, което трансформира входовете, за да различи по-сложни характеристики от данните за изходния слой, за да направи по-добра оценка.

Ние прилагаме филтър/ядро, което открива хоризонтални ръбове предимно 3X3. Забележете, 1’s отгоре и 0’s в средата и -1’s в долната част на ядрото A:

 1,   1,   1
 0,   0,   0
-1,  -1,  -1

Ако филтърът се умножи с входа, ние разпределяме високи числа за високите числа, тъй като се умножават по 1 и почти нищо за ниските числа, тъй като те се умножават по 0 или -1. По този начин ни дава изход от първата конволюция, наречена активиране, което е основно число, което се изчислява чрез вземане на някакво число от входа, след което се прилага някакъв вид линейна операция, т.е. конволюционно ядро ​​за изчисляване изход (активирането).

Conv1 показва активирането и на двете, след като се вземе секцията 3x3 на входа и се умножи по конволюционното ядро.

приемаме, че мрежата е обучена и в края на обучението е създала „конволюционен филтър“ с A, който има 9 числа в него.

Конволюцията е нещо, при което имаме малка матрица почти винаги 3x3 в задълбочено обучение и умножаваме всеки елемент от тази матрица по всеки елемент от 3x3 секция на изображение и ги добавяме всички заедно, за да получим резултата от тази конволюция в един момент.

нека приложим втори конволюционен филтър B, който също има 9 числа. Филтър B намира вертикалния ръб и го извежда като скрит слой.

1,   0,  -1
1,   0,  -1
1,   0,  -1

Pytorch не ги съхранява като 2 отделни 9-цифрени масива, той ги съхранява като тензори. които са многомерни масиви. Допълнителната ос ни позволява да подреждаме допълнителни филтри заедно. Филтърът и ядрото означават същото, което се отнася и за матрицата 3x3.

Скритият слой (conv1) е с размер две, тъй като има 2 филтъра/ядра.

След това ще приложим друг филтър, т.е. филтър C в скрит слой 2, който е две 2x3x3 ядра, след което ще приложим коригирана линейна единица (ReLu), за да елиминираме негативите. По този начин се създава втори скрит слой conv2.

Ректифицирана линейна единица (ReLU) - е нелинейност, която изхвърля негативите.

Архитектура

Архитектурата означава колко голямо е вашето ядро ​​на първи слой, колко филтъра има в ядрото ви на първи слой и т.н. Имаме 3x3 в слой едно и 3x3 в слой 2, тази архитектура започва с две 3x3 конволюционни ядра. Вторият слой има две ядра 2x3x3.

Максимално обединяване

Това означава замяна на най-високата стойност в изходна матрица с максималната. напр. 2x2 максимално обединяване. Забележка: не се припокрива, като по този начин намалява разделителната способност.

По-долу е максималния обединен слой:

Резултатът от максималния пул се напасва върху плътни тежести на напълно свързан слой.

Напълно свързан слойизбира всяко отделно максимално обединено активиране и му дава тегло и избира сумата от произведението на максималното обединено активиране и теглата на 2-те нива на триизмерния тензор. за да поставите плътно активиране

Това е различно от конволюция, при конволюция преминаваме през активиране няколко наведнъж, като използваме 3x3 ядра. Но в напълно свързан слой създаваме голяма матрица за тегло, равна на целия вход.

Архитектурите, които използват интензивно напълно свързани слоеве, могат да имат много тежести, следователно могат да имат проблеми с пренастройването и да бъдат бавни. Например VGG има до 19 слоя, съдържа напълно свързани слоеве с 4096 тегла, свързани с 4096 скрити активации на слоя по този начин (4096 x 4096 x брой ядра), което е почти 300 милиона тегла.

Ами ако имахме 3 канала на входа, каква би била формата на филтъра? ако имахме 3 канала на входа, щеше да изглежда точно като conv1, който има 2 канала, следователно 2 филтъра, следователно 2 филтъра на канал.

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

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

Softmax

Предсказване дали изображението е котка, куче, самолет, риба или сграда.

От напълно свързания слой ще имаме 5 числа. Имайте предвид, че в последния слой няма Relu, така че можем да имаме негативи. Искате да превърнете 5-те числа във вероятности от 0 до 1 и да ги съпоставите, ако е котка, куче, самолет, риба или сграда. Вероятностите на 5-те класа трябва да са между 0 и 1 и сумата на всички трябва да е 1. За да направим това, използваме функция за активиране, това е функция, приложена към активации. той приема едно число и изплюва друго число.

Трябва да подредим линейна и нелинейна функция заедно, за да направим задълбочено обучение. Нелинейността, която използваме след всеки скрит слой, е ReLu. Функцията за активиране е нелинейна функция.

Активирането на Softmax се извършва в последния слой. softmax изхвърля числа между 0 и 1, които също дават сбор до 1.

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

Правим e^-0.36, за да получим exp, след което добавяме всички тях, за да получим 51.31. За да получим softmax, разделяме на 51.31 и получаваме 0.01. Сборът на softmax трябва да възлиза на 1.

Характеристика на exp е, че ако дадено число (output) е малко по-голямо от другото, то има тенденция да направи exp дори много по-голямо. Softmax има тенденция да избира едно нещо силно, т.е. разпределя към един клас висока вероятност.

Какъв тип функция за активиране използваме, ако искаме да класифицираме картината като котка и куче? Softmax не обича да предвижда множество неща. То иска да избере едно нещо. Една от причините, поради които може да искаме да направим това, е да направим класификация с множество етикети.

Планетарно състезание: Разбиране на Амазонка от космоса

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

антропоморфизиране на вашите функции за активиране (дайте индивидуалност)softmax има тенденция да избира едно конкретно нещо.

Библиотеката Fast.ai автоматично ще превключи в режим с множество етикети, ако има повече от един етикет. Така че не е нужно да правите нищо. Но ето какво се случва зад сцената:

from planet import f2 
metrics=[f2] 
f_model = resnet34
label_csv = f'{PATH}train_v2.csv'
n = len(list(open(label_csv)))-1
val_idxs = get_cv_idxs(n)
def get_data(sz):
    tfms = tfms_from_model(f_model, sz,aug_tfms=transforms_top_down,
max_zoom=1.05)
    return ImageClassifierData.from_csv(PATH, 'train-jpg',label_csv, tfms=tfms,suffix='.jpg', val_idxs=val_idxs, test_name='test-jpg')
data = get_data(256) #gets images of 256x256

ние използваме from_csv, тъй като класификацията с множество етикети не може да се извърши с подхода в стил Keras, където подпапката е името на етикета.

transform_top_down : прави повече от просто вертикално обръщане. Има 8 възможни симетрии за квадрат. Може да се завърта на 0, 90, 180, 270 градуса и за всеки от тях може да се обръща (двустеннагрупа от осем)

x,y = next(iter(data.val_dl))

Използвайки ds (набор от данни), можем да получим индивидуално изображение.

dl е програма за зареждане на данни, която ще ви даде мини-партида, по-специално трансформирана мини-партида. С товарач на данни не можете да поискате конкретна мини-партида, можете да получите обратно само next мини-партида. В Python се нарича „генератор“ или „итератор“.

PyTorch наистина използва съвременните методологии на Python. ако познавате добре Python, PyTorch идва много естествено. Ако не познавате добре Python, PyTorch е добра причина да научите добре Python.

x е мини-пакет от изображения, y е мини-пакет от етикети. Печат y:

Това ви дава размер на партидата от 64 по подразбиране и 17, които са възможните класове.

нека да разгледаме етикетите на изображенията 0:

list(zip(data.classes, y[0]))

[('agriculture', 1.0),
 ('artisinal_mine', 0.0),
 ('bare_ground', 0.0),
 ('blooming', 0.0),
 ('blow_down', 0.0),
 ('clear', 1.0),
 ('cloudy', 0.0),
 ('conventional_mine', 0.0),
 ('cultivation', 0.0),
 ('habitation', 0.0),
 ('haze', 0.0),
 ('partly_cloudy', 0.0),
 ('primary', 1.0),
 ('road', 0.0),
 ('selective_logging', 0.0),
 ('slash_burn', 1.0),
 ('water', 1.0)]

Това е селско стопанство, ясно, първичен slash_burn и вода.

PyTorch и fast.ai превръщат етикетите в one-hot-encoded етикети. Ако действителният етикет е куче, той ще изглежда така:

вземаме softmax и сравняваме с actuals, за да предвидим действително. Разликата между actuals и softmax, обобщени заедно, ни дава грешката, т.е. функция на загубата.

One-hot-encoding е ужасно неефективно за сортиране, така че ще съхраняваме index стойност (единично цяло число), вместо 0 и 1 за целевата стойност (y). Ако погледнете y стойностите за състезанието за породи кучета, вие спечелихте всъщност не виждате големи списъци с 1 и 0, но ще видите едно цяло число.

PyTorch вътрешно преобразува индекса в един горещо кодиран вектор (въпреки че буквално никога няма да го видите). PyTorch има различни функции за загуба за тези, които са горещо кодирани и други, които не са – но тези подробности са скрити от библиотеката fast.ai, така че не е нужно да се притеснявате за това. Но страхотното нещо, което трябва да осъзнаем, е, че ние правим абсолютно едно и също нещо както за класификацията с един етикет, така и за класификацията с няколко етикета.

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

Забележка: изображенията са само матрици от числа. Изображението беше размито, така че правейки го по-видимо („осветявайки го малко“), ние умножаваме по *1.4.

Добре е да експериментирате с изображения като това, защото тези изображения изобщо не приличат на ImageNet. По-голямата част от нещата, които правите, включващи конволюционна невронна мрежа, всъщност няма да бъдат нищо подобно на ImageNet, те ще бъдат медицински изображения, класифициране на различни видове стоманени тръби, сателитни изображения и т.н.

sz=64
data = get_data(sz)
data = data.resize(int(sz*1.3), 'tmp')

Няма да използваме sz=64 за състезания с котки и кучета, защото започнахме с предварително обучена мрежа ImageNet, която започва почти перфектно. Ако обучим отново целия комплект с изображения 64 на 64, ще унищожим тежестите, които вече са много добри. Не забравяйте, че повечето модели на ImageNet са обучени с изображения 224 на 224 или 299 на 299.

Няма изображения в мрежата за изображения, които да изглеждат като сателитното изображение по-горе. Единствената полезна част от imageNet е първият слой, който намира ръбове и градиенти, вторият слой, който намира текстура и повтарящи се модели.

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

learn = ConvLearner.pretrained(f_model, data, metrics=metrics)
lrf=learn.lr_find()
learn.sched.plot()

монтаж

[lr/9, lr/3, lr]се използва, защото изображенията са различни от изображението на ImageNet и по-ранните слоеве вероятно не са толкова близки до това, което трябва да бъдат.

начертаване на загубата:

нека удвоим размера на нашия размер на изображението първо до 128, след това да го поберем, след това отново да удвоим до 256, което ще ви отведе до 93,5% точност:

Увеличаването на тестовото време ни довежда до 93,6%:

data = data.resize(int(sz*1.3), 'tmp')

Какво прави това?

когато указваме какви трансформации да приложим, предаваме размер:

tfms = tfms_from_model(f_model, sz,
        aug_tfms=transforms_top_down, max_zoom=1.05)

Едно нещо, което прави товарачът на данни, е да преоразмерява изображенията при поискване. Това няма нищо общо с data.resize. Ако първоначалното входно изображение е 1000 на 1000, четенето на този JPEG и преоразмеряването му до 64 на 64 отнема повече време, отколкото обучението на конволюционната мрежа.

data.resize му казва, че няма да използваме изображения, по-големи от sz*1.3, така че преминете веднъж и създайте нови JPEG файлове с този размер, които са правоъгълни, така че нови JPEG файлове, чийто най-малък ръб е с размерsz*1.3 централно изрязан. Това работи като пакетните скриптове, които преоразмеряват изображенията. Ще ви спести много време. data.resize е функция за ускоряване на удобството.

metrics=[f2]

Вместо accuacy използвахме F-beta, това е начин за претегляне на фалшивите отрицателни и фалшивите положителни резултати. Причината да го използваме е, че това конкретно състезание на Kaggle иска да го използва. Разгледайте planet.py, за да видите как можете да създадете своя собствена функция за измерване с помощта на Skitlearn. Това е, което се разпечатва накрая. След всяка епоха[ 0. 0.08932 0.08218 0.9324 ]

Функция за активиране за класификация с множество етикети

Fast.ai проверява етикетите, за да види дали изображението има повече от един етикет към него и автоматично избира функцията за активиране.

Функцията за активиране за класификация с множество етикети се нарича сигмоид.

За да намерите сигмоида, изберете exp, разделете го на 1+exp, т.е.:

0.01/1+0.01 = 0.01
0.08/1+0.08 = 0.07 

Това позволява да се прогнозират няколко неща наведнъж. Ако нещо е по-малко от 0, сигмоидът е по-малък от 0,5, ако повече от 0 е по-голям от 0,5.

Защо не започнем да тренираме с диференцирана скорост на обучение, вместо да тренираме само последните слоеве? Можете да пропуснете обучението само на последния слой и да преминете направо към диференцирани нива на обучение, но вероятно не искате. Всички конволюционни слоеве съдържат предварително обучени тегла, така че не са произволни — за неща, които са близки до ImageNet, те са наистина добри; за неща, които не са близки до ImageNet, те са по-добри от нищо. Всички наши напълно свързани слоеве обаче са напълно произволни. Следователно винаги бихте искали да направите напълно свързаните тежести по-добри от произволните, като първо ги тренирате малко. В противен случай, ако отидете направо на размразяване, тогава всъщност ще се занимавате с теглата на ранните слоеве, когато по-късните все още са произволни - което вероятно не е това, което искате.

Когато размразите какво се опитвате да промените? Tядрото (филтър) и тегла. това, което означава обучение, е настройка на филтрите и плътните тежести. плътните тегла са за напълно свързания слой, а филтрите/теглата на ядрото за конволюцията. Активациите от друга страна се изчисляват от теглата и предишните активации или входове на слоеве.

Как да получите размер на изображението 64 на 64? Tтова зависи от трансформациите по подразбиране, нашата трансформация взема най-малките ръбове, намалява мащаба и изрязва централно за него, но когато използва увеличаване на данни, го избира на случаен принцип.

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

Когато използвате диференциалните скорости на обучение, тези три скорости на обучение разпределят ли се равномерно между слоевете? Библиотеката fast.ai има концепция за „групи слоеве“. В нещо като ResNet50 има стотици слоеве и вероятно не искате да пишете стотици скорости на обучение, така че библиотеката решава вместо вас как да ги разделите и последният винаги се отнася само до напълно свързаните слоеве, които сме инициализирали на случаен принцип и добави, че останалите нива на обучение са разделени по средата на слоевете.

Визуализация на слоевете

learn.summary()
[('Conv2d-1',
  OrderedDict([('input_shape', [-1, 3, 64, 64]),
               ('output_shape', [-1, 64, 32, 32]),
               ('trainable', False),
               ('nb_params', 9408)])),
 ('BatchNorm2d-2',
  OrderedDict([('input_shape', [-1, 64, 32, 32]),
               ('output_shape', [-1, 64, 32, 32]),
               ('trainable', False),
               ('nb_params', 128)])),
 ('ReLU-3',
  OrderedDict([('input_shape', [-1, 64, 32, 32]),
               ('output_shape', [-1, 64, 32, 32]),
               ('nb_params', 0)])),
 ('MaxPool2d-4',
  OrderedDict([('input_shape', [-1, 64, 32, 32]),
               ('output_shape', [-1, 64, 16, 16]),
               ('nb_params', 0)])),
 ('Conv2d-5',
  OrderedDict([('input_shape', [-1, 64, 16, 16]),
               ('output_shape', [-1, 64, 16, 16]),
               ('trainable', False),
               ('nb_params', 36864)]))
 ...

conv2d-1 е името на слоя.

‘input_shape’, [-1, 3, 64, 64] — PyTorch изброява канал 3 преди размера на изображението 64, 64. Някои от изчисленията на GPU се изпълняват по-бързо, когато са в този ред. Това е 4-измерна мини партида.

-1 означава колко голям е размерът на партидата, който може да бъде променен. Keras използва None

‘output_shape’ , [-1, 64, 32, 32] 64 е броят на ядките, 32 на 32 е крачката. работи като maxpooling, променя размера.

Инструментът за търсене на скорост на обучение за много малък набор от данни върна странни числа и графиката беше празна. Устройството за търсене на скорост на обучение ще премине през мини-партида наведнъж. Ако имате малък набор от данни, просто няма достатъчно мини-партиди. Така че номерът е да направите партидата много малка.

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

Има два вида набор от данни.

Неструктуриран — Аудио, изображения, текст на естествен език, където всички неща вътре в обекта са от един и същи вид — пиксели, амплитуда на вълновата форма или думи.

Структуриран— Отчет за печалбата и загубата, информация за потребител на Facebook, където всяка колона е структурно различна. „Структурирани“ се отнася до колонни данни, каквито можете да намерите в база данни или електронна таблица, където различните колони представляват различни видове неща, а всеки ред представлява наблюдение.

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

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

Пример:

прогнозиране на продажби за голяма верига за хранителни стоки. "тук"

Прогнозирайте продажбите, като използвате данни за магазини, промоции и конкуренти. "тук"

Разпродажба на магазин Rossmann

Внос:

from fastai.structured import *
from fastai.column_data import *
np.set_printoptions(threshold=50, edgeitems=20)

PATH='data/rossmann/'

structured — не е специфичен за PyTorch и също се използва в курсове за машинно обучение, правещи произволни гори без PyTorch изобщо. Може да се използва самостоятелно без други части на библиотеката Fast.ai.

fastai.column_data — позволява ни да правим Fast.ai и PyTorch неща с колонно структурирани данни.

За структурирани данни трябва често да използваме Pandas. Не съм запознат с Pandas, тук (Python за анализ на данни) е добра книга от автора на Pandas.

Създайте набори от данни

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

Има много предварителна обработка на данни, този бележник съдържа целия конвейер от победителя на трето място („Вграждане на обекти на категориални променливи“). Обработката на данни не е разгледана в този курс, но е разгледана в курса за машинно обучение в някои подробности, тъй като инженерството на функции е много важно.

Разглеждане на CSV файлове:

StoreType — често получавате набори от данни, където някои колони съдържат „код“. Наистина няма значение какво означава кодът. Стойте далеч от научаването твърде много за това и първо вижте какво казват данните. След това по-късно погледнете речника на данните, който често се предоставя с данните.

Съединяване на маси

Това е релационен набор от данни и сте съединили доста таблици заедно — което е лесно да се направи с Pandas, използвайки merge:

fast.ai предоставя и следното:

add_datepart(train, "Date", drop=False)

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

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

Запазване на целия структуриран файл, който съдържа данните:

joined.to_feather(f'{PATH}joined')

to_feather : Записва кадър с данни на Pandas във формат „перо“, който го приема, докато се намира в RAM, и го изхвърля на диска. Така че наистина е много бързо. Конкуренцията за хранителни стоки в Еквадор има 350 милиона записа, така че ще ви е грижа колко време отнема спестяването с помощта на перо, отнема 6 секунди.

Данните съдържат колко от определен артикул е бил продаден на определена дата в магазин. Целта е да се предвиди колко от тези артикули ще бъдат продадени в определен магазин на бъдеща дата.

Следващ урок

Разделяме колоните на два вида: категорични и непрекъснати.

Категорична променлива: е, че store_id 1 и store_id 2 не са числено свързани помежду си. те са категории. Дни от седмицата; Понеделник (ден 0) и вторник (ден 1) и т.н. Категоричните данни ще бъдат горещо кодирани и

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

стъпки:

  1. Създайте набор за валидиране.
  2. ColumnarModelData.from_data_frame е начинът, по който зареждаме данни за колони. основната концепция на API е същата като при разпознаването на изображения.
  3. .get_learner
  4. .lr_find(), за да намерим най-добрата ни скорост на обучение и да я начертаем.
  5. .fit с metric
  6. .fit с cycle_len

Благодаря за четенето! следвайте @itsmuriuki.

Обратно към ученето!