CNTK - regresja sieci neuronowej
Ten rozdział pomoże ci zrozumieć regresję sieci neuronowej w odniesieniu do CNTK.
Wprowadzenie
Jak wiemy, aby przewidzieć wartość liczbową na podstawie jednej lub więcej zmiennych predykcyjnych, używamy regresji. Weźmy przykład przewidywania mediany wartości domu powiedzmy w jednym ze 100 miast. Aby to zrobić, posiadamy dane, które obejmują:
Statystyka przestępczości dla każdego miasta.
Wiek domów w każdym mieście.
Miara odległości od każdego miasta do doskonałej lokalizacji.
Stosunek liczby uczniów do liczby nauczycieli w każdym mieście.
Rasowe statystyki demograficzne dla każdego miasta.
Średnia wartość domu w każdym mieście.
Na podstawie tych pięciu predyktorów chcielibyśmy przewidzieć medianę wartości domu. W tym celu możemy stworzyć model regresji liniowej wzdłuż linii -
Y = a0+a1(crime)+a2(house-age)+(a3)(distance)+(a4)(ratio)+(a5)(racial)
W powyższym równaniu -
Y jest przewidywaną wartością mediany
a0 jest stałą i
a1 do a5 wszystkie są stałymi związanymi z pięcioma predyktorami omówionymi powyżej.
Mamy również alternatywne podejście do korzystania z sieci neuronowej. Stworzy dokładniejszy model prognozowania.
Tutaj utworzymy model regresji sieci neuronowej przy użyciu CNTK.
Ładowanie zbioru danych
Aby zaimplementować regresję sieci neuronowej za pomocą CNTK, użyjemy zestawu danych wartości domu w Bostonie. Zestaw danych można pobrać z repozytorium UCI Machine Learning Repository, które jest dostępne pod adresemhttps://archive.ics.uci.edu/ml/machine-learning-databases/housing/. Ten zbiór danych zawiera łącznie 14 zmiennych i 506 instancji.
Ale w naszym programie wdrożeniowym użyjemy sześciu z 14 zmiennych i 100 instancji. Na 6, 5 jako predyktory i jeden jako wartość do przewidzenia. Ze 100 instancji będziemy używać 80 do celów szkoleniowych i 20 do celów testowych. Wartość, którą chcemy przewidzieć, to mediana ceny domu w mieście. Zobaczmy pięć predyktorów, których będziemy używać -
Crime per capita in the town - Spodziewalibyśmy się, że z tym predyktorem zostaną skojarzone mniejsze wartości.
Proportion of owner - lokale zamieszkane zbudowane przed 1940 rokiem - Spodziewalibyśmy się, że z tym predyktorem będą powiązane mniejsze wartości, ponieważ większa wartość oznacza starszy dom.
Weighed distance of the town to five Boston employment centers.
Area school pupil-to-teacher ratio.
An indirect metric of the proportion of black residents in the town.
Przygotowywanie plików szkoleniowych i testowych
Tak jak wcześniej, najpierw musimy przekonwertować surowe dane do formatu CNTK. Zamierzamy użyć pierwszych 80 elementów danych do celów szkoleniowych, więc rozdzielany tabulatorami format CNTK jest następujący -
|predictors 1.612820 96.90 3.76 21.00 248.31 |medval 13.50
|predictors 0.064170 68.20 3.36 19.20 396.90 |medval 18.90
|predictors 0.097440 61.40 3.38 19.20 377.56 |medval 20.00
. . .
Kolejnych 20 pozycji, również przekonwertowanych do formatu CNTK, posłuży do testów.
Konstruowanie modelu regresji
Najpierw musimy przetworzyć pliki danych w formacie CNTK iw tym celu użyjemy funkcji pomocniczej o nazwie create_reader w następujący sposób -
def create_reader(path, input_dim, output_dim, rnd_order, sweeps):
x_strm = C.io.StreamDef(field='predictors', shape=input_dim, is_sparse=False)
y_strm = C.io.StreamDef(field='medval', shape=output_dim, is_sparse=False)
streams = C.io.StreamDefs(x_src=x_strm, y_src=y_strm)
deserial = C.io.CTFDeserializer(path, streams)
mb_src = C.io.MinibatchSource(deserial, randomize=rnd_order, max_sweeps=sweeps)
return mb_src
Następnie musimy utworzyć funkcję pomocniczą, która akceptuje obiekt mini-wsadowy CNTK i oblicza niestandardową metrykę dokładności.
def mb_accuracy(mb, x_var, y_var, model, delta):
num_correct = 0
num_wrong = 0
x_mat = mb[x_var].asarray()
y_mat = mb[y_var].asarray()
for i in range(mb[x_var].shape[0]):
v = model.eval(x_mat[i])
y = y_mat[i]
if np.abs(v[0,0] – y[0,0]) < delta:
num_correct += 1
else:
num_wrong += 1
return (num_correct * 100.0)/(num_correct + num_wrong)
Teraz musimy ustawić argumenty architektury dla naszego NN, a także podać lokalizację plików danych. Można to zrobić za pomocą następującego kodu Pythona -
def main():
print("Using CNTK version = " + str(C.__version__) + "\n")
input_dim = 5
hidden_dim = 20
output_dim = 1
train_file = ".\\...\\" #provide the name of the training file(80 data items)
test_file = ".\\...\\" #provide the name of the test file(20 data items)
Teraz przy pomocy następującego wiersza kodu nasz program utworzy nieprzeszkolony NN -
X = C.ops.input_variable(input_dim, np.float32)
Y = C.ops.input_variable(output_dim, np.float32)
with C.layers.default_options(init=C.initializer.uniform(scale=0.01, seed=1)):
hLayer = C.layers.Dense(hidden_dim, activation=C.ops.tanh, name='hidLayer')(X)
oLayer = C.layers.Dense(output_dim, activation=None, name='outLayer')(hLayer)
model = C.ops.alias(oLayer)
Teraz, kiedy już stworzyliśmy podwójny nietrenowany model, musimy skonfigurować obiekt algorytmu ucznia. Będziemy używać uczącego się SGD isquared_error funkcja straty -
tr_loss = C.squared_error(model, Y)
max_iter = 3000
batch_size = 5
base_learn_rate = 0.02
sch=C.learning_parameter_schedule([base_learn_rate, base_learn_rate/2], minibatch_size=batch_size, epoch_size=int((max_iter*batch_size)/2))
learner = C.sgd(model.parameters, sch)
trainer = C.Trainer(model, (tr_loss), [learner])
Teraz, gdy skończymy z obiektem algorytmu uczenia się, musimy utworzyć funkcję czytnika, aby odczytać dane szkoleniowe -
rdr = create_reader(train_file, input_dim, output_dim, rnd_order=True, sweeps=C.io.INFINITELY_REPEAT)
boston_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
Nadszedł czas, aby wyszkolić nasz model NN -
for i in range(0, max_iter):
curr_batch = rdr.next_minibatch(batch_size, input_map=boston_input_map) trainer.train_minibatch(curr_batch)
if i % int(max_iter/10) == 0:
mcee = trainer.previous_minibatch_loss_average
acc = mb_accuracy(curr_batch, X, Y, model, delta=3.00)
print("batch %4d: mean squared error = %8.4f, accuracy = %5.2f%% " \ % (i, mcee, acc))
Po zakończeniu uczenia oceńmy model przy użyciu elementów danych testowych -
print("\nEvaluating test data \n")
rdr = create_reader(test_file, input_dim, output_dim, rnd_order=False, sweeps=1)
boston_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
num_test = 20
all_test = rdr.next_minibatch(num_test, input_map=boston_input_map)
acc = mb_accuracy(all_test, X, Y, model, delta=3.00)
print("Prediction accuracy = %0.2f%%" % acc)
Po ocenie dokładności naszego wytrenowanego modelu NN będziemy go używać do prognozowania niewidocznych danych -
np.set_printoptions(precision = 2, suppress=True)
unknown = np.array([[0.09, 50.00, 4.5, 17.00, 350.00], dtype=np.float32)
print("\nPredicting median home value for feature/predictor values: ")
print(unknown[0])
pred_prob = model.eval({X: unknown)
print("\nPredicted value is: ")
print(“$%0.2f (x1000)” %pred_value[0,0])
Kompletny model regresji
import numpy as np
import cntk as C
def create_reader(path, input_dim, output_dim, rnd_order, sweeps):
x_strm = C.io.StreamDef(field='predictors', shape=input_dim, is_sparse=False)
y_strm = C.io.StreamDef(field='medval', shape=output_dim, is_sparse=False)
streams = C.io.StreamDefs(x_src=x_strm, y_src=y_strm)
deserial = C.io.CTFDeserializer(path, streams)
mb_src = C.io.MinibatchSource(deserial, randomize=rnd_order, max_sweeps=sweeps)
return mb_src
def mb_accuracy(mb, x_var, y_var, model, delta):
num_correct = 0
num_wrong = 0
x_mat = mb[x_var].asarray()
y_mat = mb[y_var].asarray()
for i in range(mb[x_var].shape[0]):
v = model.eval(x_mat[i])
y = y_mat[i]
if np.abs(v[0,0] – y[0,0]) < delta:
num_correct += 1
else:
num_wrong += 1
return (num_correct * 100.0)/(num_correct + num_wrong)
def main():
print("Using CNTK version = " + str(C.__version__) + "\n")
input_dim = 5
hidden_dim = 20
output_dim = 1
train_file = ".\\...\\" #provide the name of the training file(80 data items)
test_file = ".\\...\\" #provide the name of the test file(20 data items)
X = C.ops.input_variable(input_dim, np.float32)
Y = C.ops.input_variable(output_dim, np.float32)
with C.layers.default_options(init=C.initializer.uniform(scale=0.01, seed=1)):
hLayer = C.layers.Dense(hidden_dim, activation=C.ops.tanh, name='hidLayer')(X)
oLayer = C.layers.Dense(output_dim, activation=None, name='outLayer')(hLayer)
model = C.ops.alias(oLayer)
tr_loss = C.squared_error(model, Y)
max_iter = 3000
batch_size = 5
base_learn_rate = 0.02
sch = C.learning_parameter_schedule([base_learn_rate, base_learn_rate/2], minibatch_size=batch_size, epoch_size=int((max_iter*batch_size)/2))
learner = C.sgd(model.parameters, sch)
trainer = C.Trainer(model, (tr_loss), [learner])
rdr = create_reader(train_file, input_dim, output_dim, rnd_order=True, sweeps=C.io.INFINITELY_REPEAT)
boston_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
for i in range(0, max_iter):
curr_batch = rdr.next_minibatch(batch_size, input_map=boston_input_map) trainer.train_minibatch(curr_batch)
if i % int(max_iter/10) == 0:
mcee = trainer.previous_minibatch_loss_average
acc = mb_accuracy(curr_batch, X, Y, model, delta=3.00)
print("batch %4d: mean squared error = %8.4f, accuracy = %5.2f%% " \ % (i, mcee, acc))
print("\nEvaluating test data \n")
rdr = create_reader(test_file, input_dim, output_dim, rnd_order=False, sweeps=1)
boston_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
num_test = 20
all_test = rdr.next_minibatch(num_test, input_map=boston_input_map)
acc = mb_accuracy(all_test, X, Y, model, delta=3.00)
print("Prediction accuracy = %0.2f%%" % acc)
np.set_printoptions(precision = 2, suppress=True)
unknown = np.array([[0.09, 50.00, 4.5, 17.00, 350.00], dtype=np.float32)
print("\nPredicting median home value for feature/predictor values: ")
print(unknown[0])
pred_prob = model.eval({X: unknown)
print("\nPredicted value is: ")
print(“$%0.2f (x1000)” %pred_value[0,0])
if __name__== ”__main__”:
main()
Wynik
Using CNTK version = 2.7
batch 0: mean squared error = 385.6727, accuracy = 0.00%
batch 300: mean squared error = 41.6229, accuracy = 20.00%
batch 600: mean squared error = 28.7667, accuracy = 40.00%
batch 900: mean squared error = 48.6435, accuracy = 40.00%
batch 1200: mean squared error = 77.9562, accuracy = 80.00%
batch 1500: mean squared error = 7.8342, accuracy = 60.00%
batch 1800: mean squared error = 47.7062, accuracy = 60.00%
batch 2100: mean squared error = 40.5068, accuracy = 40.00%
batch 2400: mean squared error = 46.5023, accuracy = 40.00%
batch 2700: mean squared error = 15.6235, accuracy = 60.00%
Evaluating test data
Prediction accuracy = 64.00%
Predicting median home value for feature/predictor values:
[0.09 50. 4.5 17. 350.]
Predicted value is:
$21.02(x1000)
Zapisywanie wytrenowanego modelu
Ten zbiór danych dotyczących wartości Boston Home zawiera tylko 506 pozycji danych (spośród których pozyliśmy tylko 100). W związku z tym wytrenowanie modelu regresora NN zajęłoby tylko kilka sekund, ale uczenie na dużym zestawie danych zawierającym sto lub tysiące elementów danych może zająć godziny lub nawet dni.
Możemy zapisać nasz model, dzięki czemu nie będziemy musieli zachowywać go od nowa. Z pomocą śledzenia kodu Pythona możemy zapisać nasz wyszkolony NN -
nn_regressor = “.\\neuralregressor.model” #provide the name of the file
model.save(nn_regressor, format=C.ModelFormat.CNTKv2)
Poniżej przedstawiono argumenty funkcji save () użytej powyżej -
Nazwa pliku jest pierwszym argumentem save()funkcjonować. Można go również zapisać wraz ze ścieżką do pliku.
Kolejnym parametrem jest format parametr, który ma wartość domyślną C.ModelFormat.CNTKv2.
Ładowanie wytrenowanego modelu
Po zapisaniu wytrenowanego modelu bardzo łatwo jest go załadować. Musimy tylko użyć funkcji load (). Sprawdźmy to w poniższym przykładzie -
import numpy as np
import cntk as C
model = C.ops.functions.Function.load(“.\\neuralregressor.model”)
np.set_printoptions(precision = 2, suppress=True)
unknown = np.array([[0.09, 50.00, 4.5, 17.00, 350.00], dtype=np.float32)
print("\nPredicting area median home value for feature/predictor values: ")
print(unknown[0])
pred_prob = model.eval({X: unknown)
print("\nPredicted value is: ")
print(“$%0.2f (x1000)” %pred_value[0,0])
Zaletą zapisanego modelu jest to, że po załadowaniu zapisanego modelu można go używać dokładnie tak, jakby model został właśnie wytrenowany.