CNTK - w pamięci i duże zbiory danych
W tym rozdziale dowiemy się, jak pracować z zapisanymi w pamięci i dużymi zbiorami danych w CNTK.
Trening z małymi zestawami danych w pamięci
Kiedy mówimy o podawaniu danych do trenera CNTK, może być wiele sposobów, ale będzie to zależeć od rozmiaru zbioru danych i formatu danych. Zestawy danych mogą być małymi w pamięci lub dużymi zbiorami danych.
W tej sekcji będziemy pracować z zestawami danych w pamięci. W tym celu użyjemy następujących dwóch frameworków -
- Numpy
- Pandas
Korzystanie z tablic Numpy
Tutaj będziemy pracować z losowo wygenerowanym zbiorem danych w CNTK. W tym przykładzie zamierzamy symulować dane dotyczące problemu klasyfikacji binarnej. Załóżmy, że mamy zestaw obserwacji z 4 cechami i chcemy przewidzieć dwie możliwe etykiety za pomocą naszego modelu uczenia głębokiego.
Przykład implementacji
W tym celu najpierw musimy wygenerować zestaw etykiet zawierający jedną gorącą wektorową reprezentację etykiet, które chcemy przewidzieć. Można to zrobić za pomocą następujących kroków -
Step 1 - Zaimportuj numpy pakiet w następujący sposób -
import numpy as np
num_samples = 20000
Step 2 - Następnie wygeneruj mapowanie etykiety za pomocą np.eye działają w następujący sposób -
label_mapping = np.eye(2)
Step 3 - Teraz używając np.random.choice funkcji, zbierz 20000 losowych próbek w następujący sposób -
y = label_mapping[np.random.choice(2,num_samples)].astype(np.float32)
Step 4 - Teraz w końcu, używając funkcji np.random.random, wygeneruj tablicę losowych wartości zmiennoprzecinkowych w następujący sposób -
x = np.random.random(size=(num_samples, 4)).astype(np.float32)
Kiedy już wygenerujemy tablicę losowych wartości zmiennoprzecinkowych, musimy przekonwertować je na 32-bitowe liczby zmiennoprzecinkowe, aby można je było dopasować do formatu oczekiwanego przez CNTK. Wykonajmy poniższe kroki, aby to zrobić -
Step 5 - Zaimportuj funkcje warstwy gęstej i sekwencyjnej z modułu cntk.layers w następujący sposób -
from cntk.layers import Dense, Sequential
Step 6- Teraz musimy zaimportować funkcję aktywacji dla warstw w sieci. Zaimportujmysigmoid jako funkcja aktywacji -
from cntk import input_variable, default_options
from cntk.ops import sigmoid
Step 7- Teraz musimy zaimportować funkcję strat, aby wytrenować sieć. Importujmybinary_cross_entropy jako funkcja straty -
from cntk.losses import binary_cross_entropy
Step 8- Następnie musimy zdefiniować domyślne opcje sieci. Tutaj zapewnimysigmoidfunkcja aktywacji jako ustawienie domyślne. Utwórz również model, korzystając z funkcji warstwy sekwencyjnej w następujący sposób -
with default_options(activation=sigmoid):
model = Sequential([Dense(6),Dense(2)])
Step 9 - Następnie zainicjalizuj plik input_variable z 4 wejściami służącymi jako wejście dla sieci.
features = input_variable(4)
Step 10 - Teraz, aby go ukończyć, musimy podłączyć zmienne funkcji do NN.
z = model(features)
Więc teraz mamy NN, z pomocą następujących kroków, wytrenujmy go przy użyciu zestawu danych w pamięci -
Step 11 - Aby wytrenować ten NN, najpierw musimy zaimportować uczestnika z cntk.learnersmoduł. Sprowadzimysgd uczeń w następujący sposób -
from cntk.learners import sgd
Step 12 - Wraz z tym importem ProgressPrinter od cntk.logging moduł również.
from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)
Step 13 - Następnie zdefiniuj nową zmienną wejściową dla etykiet w następujący sposób -
labels = input_variable(2)
Step 14 - Aby wytrenować model NN, musimy następnie zdefiniować stratę za pomocą binary_cross_entropyfunkcjonować. Podaj również model z i zmienną etykiety.
loss = binary_cross_entropy(z, labels)
Step 15 - Następnie zainicjuj plik sgd uczeń w następujący sposób -
learner = sgd(z.parameters, lr=0.1)
Step 16- W końcu wywołaj metodę pociągu na funkcji straty. Podaj również dane wejściowe, pliksgd uczeń i progress_printer.−
training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=[progress_writer])
Kompletny przykład wdrożenia
import numpy as np
num_samples = 20000
label_mapping = np.eye(2)
y = label_mapping[np.random.choice(2,num_samples)].astype(np.float32)
x = np.random.random(size=(num_samples, 4)).astype(np.float32)
from cntk.layers import Dense, Sequential
from cntk import input_variable, default_options
from cntk.ops import sigmoid
from cntk.losses import binary_cross_entropy
with default_options(activation=sigmoid):
model = Sequential([Dense(6),Dense(2)])
features = input_variable(4)
z = model(features)
from cntk.learners import sgd
from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)
labels = input_variable(2)
loss = binary_cross_entropy(z, labels)
learner = sgd(z.parameters, lr=0.1)
training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=[progress_writer])
Wynik
Build info:
Built time: *** ** **** 21:40:10
Last modified date: *** *** ** 21:08:46 2019
Build type: Release
Build target: CPU-only
With ASGD: yes
Math lib: mkl
Build Branch: HEAD
Build SHA1:ae9c9c7c5f9e6072cc9c94c254f816dbdc1c5be6 (modified)
MPI distribution: Microsoft MPI
MPI version: 7.0.12437.6
-------------------------------------------------------------------
average since average since examples
loss last metric last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.52 1.52 0 0 32
1.51 1.51 0 0 96
1.48 1.46 0 0 224
1.45 1.42 0 0 480
1.42 1.4 0 0 992
1.41 1.39 0 0 2016
1.4 1.39 0 0 4064
1.39 1.39 0 0 8160
1.39 1.39 0 0 16352
Korzystanie z Pandas DataFrames
Tablice Numpy są bardzo ograniczone pod względem tego, co mogą zawierać i są jednym z najbardziej podstawowych sposobów przechowywania danych. Na przykład pojedyncza tablica n-wymiarowa może zawierać dane jednego typu. Ale z drugiej strony w wielu rzeczywistych przypadkach potrzebujemy biblioteki, która może obsługiwać więcej niż jeden typ danych w jednym zestawie danych.
Jedna z bibliotek Pythona o nazwie Pandas ułatwia pracę z tego rodzaju zbiorami danych. Wprowadza koncepcję DataFrame (DF) i pozwala nam ładować zestawy danych z dysku przechowywane w różnych formatach jako DF. Na przykład możemy czytać DF zapisane jako CSV, JSON, Excel itp.
Więcej szczegółów na temat biblioteki Python Pandas można znaleźć pod adresem https://www.tutorialspoint.com/python_pandas/index.htm.
Przykład implementacji
W tym przykładzie posłużymy się przykładem klasyfikacji trzech możliwych gatunków kwiatów tęczówki na podstawie czterech właściwości. Stworzyliśmy ten model głębokiego uczenia się również w poprzednich sekcjach. Model wygląda następująco -
from cntk.layers import Dense, Sequential
from cntk import input_variable, default_options
from cntk.ops import sigmoid, log_softmax
from cntk.losses import binary_cross_entropy
model = Sequential([
Dense(4, activation=sigmoid),
Dense(3, activation=log_softmax)
])
features = input_variable(4)
z = model(features)
Powyższy model zawiera jedną ukrytą warstwę i warstwę wyjściową z trzema neuronami, aby dopasować liczbę klas, które możemy przewidzieć.
Następnie użyjemy train metoda i lossfunkcję uczenia sieci. W tym celu najpierw musimy załadować i wstępnie przetworzyć zestaw danych tęczówki, tak aby pasował do oczekiwanego układu i formatu danych dla sieci NN. Można to zrobić za pomocą następujących kroków -
Step 1 - Zaimportuj numpy i Pandas pakiet w następujący sposób -
import numpy as np
import pandas as pd
Step 2 - Następnie użyj read_csv funkcja załadowania zbioru danych do pamięci -
df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’,
‘petal_length’, ‘petal_width’, ‘species’], index_col=False)
Step 3 - Teraz musimy stworzyć słownik, który będzie mapował etykiety w zbiorze danych wraz z ich reprezentacją numeryczną.
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
Step 4 - Teraz używając iloc indeksator w DataFrame, wybierz pierwsze cztery kolumny w następujący sposób -
x = df_source.iloc[:, :4].values
Step 5−Następnie musimy wybrać kolumny gatunków jako etykiety zbioru danych. Można to zrobić w następujący sposób -
y = df_source[‘species’].values
Step 6 - Teraz musimy zmapować etykiety w zbiorze danych, co można zrobić za pomocą label_mapping. Użyj równieżone_hot kodowanie, aby przekonwertować je na jedno gorące tablice kodowania.
y = np.array([one_hot(label_mapping[v], 3) for v in y])
Step 7 - Następnie, aby użyć funkcji i zmapowanych etykiet z CNTK, musimy przekonwertować je oba na elementy zmiennoprzecinkowe -
x= x.astype(np.float32)
y= y.astype(np.float32)
Jak wiemy, etykiety są przechowywane w zbiorze danych jako ciągi i CNTK nie może pracować z tymi ciągami. Z tego powodu potrzebuje zakodowanych na gorąco wektorów reprezentujących etykiety. W tym celu możemy zdefiniować funkcję powiedzone_hot w następujący sposób -
def one_hot(index, length):
result = np.zeros(length)
result[index] = index
return result
Teraz mamy tablicę numpy w odpowiednim formacie, z pomocą poniższych kroków możemy ich użyć do wytrenowania naszego modelu -
Step 8- Najpierw musimy zaimportować funkcję strat, aby wytrenować sieć. Importujmybinary_cross_entropy_with_softmax jako funkcja straty -
from cntk.losses import binary_cross_entropy_with_softmax
Step 9 - Aby wytrenować ten NN, musimy także zaimportować uczestnika z cntk.learnersmoduł. Sprowadzimysgd uczeń w następujący sposób -
from cntk.learners import sgd
Step 10 - Wraz z tym importem ProgressPrinter od cntk.logging moduł również.
from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)
Step 11 - Następnie zdefiniuj nową zmienną wejściową dla etykiet w następujący sposób -
labels = input_variable(3)
Step 12 - Aby wytrenować model NN, musimy następnie zdefiniować stratę za pomocą binary_cross_entropy_with_softmaxfunkcjonować. Podaj również model z i zmienną etykiety.
loss = binary_cross_entropy_with_softmax (z, labels)
Step 13 - Następnie zainicjalizuj plik sgd uczeń w następujący sposób -
learner = sgd(z.parameters, 0.1)
Step 14- W końcu wywołaj metodę pociągu na funkcji straty. Podaj również dane wejściowe, pliksgd uczeń i progress_printer.
training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=
[progress_writer],minibatch_size=16,max_epochs=5)
Kompletny przykład wdrożenia
from cntk.layers import Dense, Sequential
from cntk import input_variable, default_options
from cntk.ops import sigmoid, log_softmax
from cntk.losses import binary_cross_entropy
model = Sequential([
Dense(4, activation=sigmoid),
Dense(3, activation=log_softmax)
])
features = input_variable(4)
z = model(features)
import numpy as np
import pandas as pd
df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
x = df_source.iloc[:, :4].values
y = df_source[‘species’].values
y = np.array([one_hot(label_mapping[v], 3) for v in y])
x= x.astype(np.float32)
y= y.astype(np.float32)
def one_hot(index, length):
result = np.zeros(length)
result[index] = index
return result
from cntk.losses import binary_cross_entropy_with_softmax
from cntk.learners import sgd
from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)
labels = input_variable(3)
loss = binary_cross_entropy_with_softmax (z, labels)
learner = sgd(z.parameters, 0.1)
training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=[progress_writer],minibatch_size=16,max_epochs=5)
Wynik
Build info:
Built time: *** ** **** 21:40:10
Last modified date: *** *** ** 21:08:46 2019
Build type: Release
Build target: CPU-only
With ASGD: yes
Math lib: mkl
Build Branch: HEAD
Build SHA1:ae9c9c7c5f9e6072cc9c94c254f816dbdc1c5be6 (modified)
MPI distribution: Microsoft MPI
MPI version: 7.0.12437.6
-------------------------------------------------------------------
average since average since examples
loss last metric last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.1 1.1 0 0 16
0.835 0.704 0 0 32
1.993 1.11 0 0 48
1.14 1.14 0 0 112
[………]
Szkolenie z dużymi zbiorami danych
W poprzedniej sekcji pracowaliśmy z małymi zestawami danych w pamięci przy użyciu Numpy i pand, ale nie wszystkie zestawy danych są tak małe. W szczególności zbiory danych zawierające obrazy, filmy, próbki dźwięków są duże.MinibatchSourceto komponent, który może ładować dane w kawałkach, dostarczany przez CNTK do pracy z tak dużymi zbiorami danych. Niektóre funkcjeMinibatchSource komponenty są następujące -
MinibatchSource może zapobiec nadmiernemu dopasowaniu NN przez automatyczne losowanie próbek odczytywanych ze źródła danych.
Posiada wbudowany potok transformacji, który może służyć do rozszerzania danych.
Ładuje dane w wątku w tle niezależnym od procesu uczenia.
W kolejnych sekcjach zamierzamy zbadać, jak używać źródła minibatch z danymi o braku pamięci do pracy z dużymi zestawami danych. Zbadamy również, jak możemy go użyć do karmienia w celu szkolenia NN.
Tworzenie instancji MinibatchSource
W poprzedniej sekcji użyliśmy przykładu kwiatu tęczówki i pracowaliśmy z małym zbiorem danych w pamięci przy użyciu Pandas DataFrames. Tutaj zastąpimy kod, który korzysta z danych z pandy DF, naMinibatchSource. Najpierw musimy utworzyć wystąpienieMinibatchSource za pomocą następujących kroków -
Przykład implementacji
Step 1 - Najpierw z cntk.io Moduł importuje komponenty do źródła minibatch w następujący sposób -
from cntk.io import StreamDef, StreamDefs, MinibatchSource, CTFDeserializer,
INFINITY_REPEAT
Step 2 - Teraz używając StreamDef class, utwórz definicję strumienia dla etykiet.
labels_stream = StreamDef(field=’labels’, shape=3, is_sparse=False)
Step 3 - Następnie utwórz, aby odczytać funkcje złożone z pliku wejściowego, utwórz kolejną instancję StreamDef następująco.
feature_stream = StreamDef(field=’features’, shape=4, is_sparse=False)
Step 4 - Teraz musimy to zapewnić iris.ctf plik jako dane wejściowe i zainicjuj plik deserializer w następujący sposób -
deserializer = CTFDeserializer(‘iris.ctf’, StreamDefs(labels=
label_stream, features=features_stream)
Step 5 - Nareszcie musimy stworzyć instancję minisourceBatch używając deserializer w następujący sposób -
Minibatch_source = MinibatchSource(deserializer, randomize=True)
Tworzenie instancji MinibatchSource - pełny przykład implementacji
from cntk.io import StreamDef, StreamDefs, MinibatchSource, CTFDeserializer, INFINITY_REPEAT
labels_stream = StreamDef(field=’labels’, shape=3, is_sparse=False)
feature_stream = StreamDef(field=’features’, shape=4, is_sparse=False)
deserializer = CTFDeserializer(‘iris.ctf’, StreamDefs(labels=label_stream, features=features_stream)
Minibatch_source = MinibatchSource(deserializer, randomize=True)
Tworzenie pliku MCTF
Jak widzieliście powyżej, pobieramy dane z pliku „iris.ctf”. Ma format pliku o nazwie CNTK Text Format (CTF). Utworzenie pliku CTF jest obowiązkowe, aby uzyskać dane dlaMinibatchSourceprzykład, który stworzyliśmy powyżej. Zobaczmy, jak możemy utworzyć plik CTF.
Przykład implementacji
Step 1 - Najpierw musimy zaimportować pandy i paczki numpy w następujący sposób -
import pandas as pd
import numpy as np
Step 2- Następnie musimy załadować do pamięci nasz plik z danymi, czyli iris.csv. Następnie umieść go wdf_source zmienna.
df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)
Step 3 - Teraz używając ilocindeksator jako funkcje, weź zawartość pierwszych czterech kolumn. Wykorzystaj również dane z kolumny Gatunki w następujący sposób -
features = df_source.iloc[: , :4].values
labels = df_source[‘species’].values
Step 4- Następnie musimy utworzyć mapowanie między nazwą etykiety a jej reprezentacją numeryczną. Można to zrobić, tworząclabel_mapping w następujący sposób -
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
Step 5 - Teraz przekonwertuj etykiety na zestaw jeden-gorących zakodowanych wektorów w następujący sposób -
labels = [one_hot(label_mapping[v], 3) for v in labels]
Teraz, tak jak poprzednio, utwórz funkcję narzędzia o nazwie one_hotzakodować etykiety. Można to zrobić w następujący sposób -
def one_hot(index, length):
result = np.zeros(length)
result[index] = 1
return result
Ponieważ załadowaliśmy i wstępnie przetworzyliśmy dane, czas zapisać je na dysku w formacie pliku CTF. Możemy to zrobić za pomocą następującego kodu Pythona -
With open(‘iris.ctf’, ‘w’) as output_file:
for index in range(0, feature.shape[0]):
feature_values = ‘ ‘.join([str(x) for x in np.nditer(features[index])])
label_values = ‘ ‘.join([str(x) for x in np.nditer(labels[index])])
output_file.write(‘features {} | labels {} \n’.format(feature_values, label_values))
Tworzenie pliku MCTF - przykład pełnego wdrożenia
import pandas as pd
import numpy as np
df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)
features = df_source.iloc[: , :4].values
labels = df_source[‘species’].values
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
labels = [one_hot(label_mapping[v], 3) for v in labels]
def one_hot(index, length):
result = np.zeros(length)
result[index] = 1
return result
With open(‘iris.ctf’, ‘w’) as output_file:
for index in range(0, feature.shape[0]):
feature_values = ‘ ‘.join([str(x) for x in np.nditer(features[index])])
label_values = ‘ ‘.join([str(x) for x in np.nditer(labels[index])])
output_file.write(‘features {} | labels {} \n’.format(feature_values, label_values))
Dostarczanie danych
Po utworzeniu MinibatchSource,na przykład, musimy go wyszkolić. Możemy użyć tej samej logiki treningowej, która była używana podczas pracy z małymi zestawami danych w pamięci. Tutaj użyjemyMinibatchSource przykład jako dane wejściowe dla metody pociągu w funkcji straty w następujący sposób -
Przykład implementacji
Step 1 - Aby zarejestrować wynik sesji szkoleniowej, najpierw zaimportuj ProgressPrinter z cntk.logging moduł w następujący sposób -
from cntk.logging import ProgressPrinter
Step 2 - Następnie, aby skonfigurować sesję treningową, zaimportuj plik trainer i training_session od cntk.train moduł w następujący sposób -
from cntk.train import Trainer,
Step 3 - Teraz musimy zdefiniować jakiś zestaw stałych, takich jak minibatch_size, samples_per_epoch i num_epochs w następujący sposób -
minbatch_size = 16
samples_per_epoch = 150
num_epochs = 30
Step 4 - Następnie, aby wiedzieć, jak CNTK odczytuje dane podczas uczenia, musimy zdefiniować mapowanie między zmienną wejściową dla sieci a strumieniami w źródle minibatch.
input_map = {
features: minibatch.source.streams.features,
labels: minibatch.source.streams.features
}
Step 5 - Następnie, aby zarejestrować dane wyjściowe procesu uczenia, zainicjuj plik progress_printer zmienna z nowym ProgressPrinter przykład w następujący sposób -
progress_writer = ProgressPrinter(0)
Step 6 - W końcu musimy wywołać metodę pociągu na stracie w następujący sposób -
train_history = loss.train(minibatch_source,
parameter_learners=[learner],
model_inputs_to_streams=input_map,
callbacks=[progress_writer],
epoch_size=samples_per_epoch,
max_epochs=num_epochs)
Dostarczanie danych - kompletny przykład wdrożenia
from cntk.logging import ProgressPrinter
from cntk.train import Trainer, training_session
minbatch_size = 16
samples_per_epoch = 150
num_epochs = 30
input_map = {
features: minibatch.source.streams.features,
labels: minibatch.source.streams.features
}
progress_writer = ProgressPrinter(0)
train_history = loss.train(minibatch_source,
parameter_learners=[learner],
model_inputs_to_streams=input_map,
callbacks=[progress_writer],
epoch_size=samples_per_epoch,
max_epochs=num_epochs)
Wynik
-------------------------------------------------------------------
average since average since examples
loss last metric last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.21 1.21 0 0 32
1.15 0.12 0 0 96
[………]