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
[………]