CNTK - Classificazione della rete neurale

In questo capitolo, studieremo come classificare la rete neurale utilizzando CNTK.

introduzione

La classificazione può essere definita come il processo per prevedere le etichette di output categoriali o le risposte per i dati di input forniti. L'output categorizzato, che sarà basato su ciò che il modello ha appreso in fase di formazione, può avere la forma "Nero" o "Bianco" o "spam" o "no spam".

D'altra parte, matematicamente, è il compito di approssimare una funzione di mappatura diciamo f dalle variabili di input dicono X alle variabili di output dicono Y.

Un classico esempio di problema di classificazione può essere il rilevamento dello spam nelle e-mail. È ovvio che possono esserci solo due categorie di output, "spam" e "no spam".

Per implementare tale classificazione, dobbiamo prima eseguire l'addestramento del classificatore in cui i messaggi di posta elettronica "spam" e "no spam" verranno utilizzati come dati di addestramento. Una volta che il classificatore è stato addestrato con successo, può essere utilizzato per rilevare un'e-mail sconosciuta.

Qui creeremo un 4-5-3 NN utilizzando il set di dati del fiore dell'iride con quanto segue:

  • 4 nodi di input (uno per ogni valore predittore).

  • 5 nodi di elaborazione nascosti.

  • Nodi a 3 uscite (perché ci sono tre possibili specie nel set di dati dell'iride).

Caricamento del set di dati

Useremo il set di dati sui fiori di iris, da cui vogliamo classificare le specie di fiori di iris in base alle proprietà fisiche di larghezza e lunghezza dei sepali e larghezza e lunghezza dei petali. Il set di dati descrive le proprietà fisiche di diverse varietà di fiori di iris -

  • Lunghezza sepale

  • Larghezza del sepalo

  • Lunghezza del petalo

  • Larghezza del petalo

  • Classe ie iris setosa o iris versicolor o iris virginica

abbiamo iris.CSVfile che abbiamo usato prima nei capitoli precedenti anche. Può essere caricato con l'aiuto diPandasbiblioteca. Ma, prima di usarlo o caricarlo per il nostro classificatore, dobbiamo preparare i file di addestramento e di prova, in modo che possa essere utilizzato facilmente con CNTK.

Preparazione di file di formazione e test

Il set di dati Iris è uno dei set di dati più popolari per i progetti ML. Dispone di 150 elementi di dati e i dati grezzi sono i seguenti:

5.1 3.5 1.4 0.2 setosa
4.9 3.0 1.4 0.2 setosa
…
7.0 3.2 4.7 1.4 versicolor
6.4 3.2 4.5 1.5 versicolor
…
6.3 3.3 6.0 2.5 virginica
5.8 2.7 5.1 1.9 virginica

Come detto in precedenza, i primi quattro valori su ciascuna riga descrivono le proprietà fisiche di diverse varietà, cioè lunghezza del sepalo, larghezza del sepalo, lunghezza del petalo, larghezza del petalo dei fiori dell'iride.

Ma dovremmo convertire i dati nel formato, che può essere facilmente utilizzato da CNTK e quel formato è il file .ctf (ne abbiamo creato anche un iris.ctf nella sezione precedente). Apparirà come segue:

|attribs 5.1 3.5 1.4 0.2|species 1 0 0
|attribs 4.9 3.0 1.4 0.2|species 1 0 0
…
|attribs 7.0 3.2 4.7 1.4|species 0 1 0
|attribs 6.4 3.2 4.5 1.5|species 0 1 0
…
|attribs 6.3 3.3 6.0 2.5|species 0 0 1
|attribs 5.8 2.7 5.1 1.9|species 0 0 1

Nei dati sopra, il tag | attribs segna l'inizio del valore dell'elemento e il tag | species i valori dell'etichetta della classe. Possiamo anche usare qualsiasi altro nome di tag del nostro desiderio, anche noi possiamo aggiungere l'ID oggetto. Ad esempio, guarda i seguenti dati:

|ID 001 |attribs 5.1 3.5 1.4 0.2|species 1 0 0 |#setosa
|ID 002 |attribs 4.9 3.0 1.4 0.2|species 1 0 0 |#setosa
…
|ID 051 |attribs 7.0 3.2 4.7 1.4|species 0 1 0 |#versicolor
|ID 052 |attribs 6.4 3.2 4.5 1.5|species 0 1 0 |#versicolor
…

Ci sono un totale di 150 elementi di dati nel set di dati iris e per questo esempio, useremo la regola del set di dati 80-20, ovvero l'80% (120 elementi) elementi di dati a scopo di addestramento e il restante 20% (30 elementi) elementi di dati per il test scopo.

Costruire il modello di classificazione

Innanzitutto, dobbiamo elaborare i file di dati in formato CNTK e per questo useremo la funzione di supporto denominata create_reader come segue -

def create_reader(path, input_dim, output_dim, rnd_order, sweeps):
x_strm = C.io.StreamDef(field='attribs', shape=input_dim, is_sparse=False)
y_strm = C.io.StreamDef(field='species', 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

Ora, dobbiamo impostare gli argomenti dell'architettura per il nostro NN e fornire anche la posizione dei file di dati. Può essere fatto con l'aiuto del seguente codice python -

def main():
print("Using CNTK version = " + str(C.__version__) + "\n")
input_dim = 4
hidden_dim = 5
output_dim = 3
train_file = ".\\...\\" #provide the name of the training file(120 data items)
test_file = ".\\...\\" #provide the name of the test file(30 data items)

Ora, con l'aiuto della seguente riga di codice, il nostro programma creerà l'NN non addestrato -

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)
nnet = oLayer
model = C.ops.softmax(nnet)

Ora, una volta creato il modello doppio non addestrato, dobbiamo impostare un oggetto algoritmo Learner e successivamente utilizzarlo per creare un oggetto di addestramento Trainer. Useremo SGD learner ecross_entropy_with_softmax funzione di perdita -

tr_loss = C.cross_entropy_with_softmax(nnet, Y)
tr_clas = C.classification_error(nnet, Y)
max_iter = 2000
batch_size = 10
learn_rate = 0.01
learner = C.sgd(nnet.parameters, learn_rate)
trainer = C.Trainer(nnet, (tr_loss, tr_clas), [learner])

Codifica l'algoritmo di apprendimento come segue:

max_iter = 2000
batch_size = 10
lr_schedule = C.learning_parameter_schedule_per_sample([(1000, 0.05), (1, 0.01)])
mom_sch = C.momentum_schedule([(100, 0.99), (0, 0.95)], batch_size)
learner = C.fsadagrad(nnet.parameters, lr=lr_schedule, momentum=mom_sch)
trainer = C.Trainer(nnet, (tr_loss, tr_clas), [learner])

Ora, una volta terminato con l'oggetto Trainer, dobbiamo creare una funzione di lettura per leggere i dati di addestramento

rdr = create_reader(train_file, input_dim, output_dim, rnd_order=True, sweeps=C.io.INFINITELY_REPEAT)
iris_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }

Ora è il momento di addestrare il nostro modello NN−

for i in range(0, max_iter):
curr_batch = rdr.next_minibatch(batch_size, input_map=iris_input_map) trainer.train_minibatch(curr_batch)
if i % 500 == 0:
mcee = trainer.previous_minibatch_loss_average
macc = (1.0 - trainer.previous_minibatch_evaluation_average) * 100
print("batch %4d: mean loss = %0.4f, accuracy = %0.2f%% " \ % (i, mcee, macc))

Una volta terminato l'addestramento, valutiamo il modello utilizzando elementi di dati di test:

print("\nEvaluating test data \n")
rdr = create_reader(test_file, input_dim, output_dim, rnd_order=False, sweeps=1)
iris_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
num_test = 30
all_test = rdr.next_minibatch(num_test, input_map=iris_input_map) acc = (1.0 - trainer.test_minibatch(all_test)) * 100
print("Classification accuracy = %0.2f%%" % acc)

Dopo aver valutato l'accuratezza del nostro modello NN addestrato, lo useremo per fare una previsione su dati invisibili -

np.set_printoptions(precision = 1, suppress=True)
unknown = np.array([[6.4, 3.2, 4.5, 1.5]], dtype=np.float32)
print("\nPredicting Iris species for input features: ")
print(unknown[0]) pred_prob = model.eval(unknown)
np.set_printoptions(precision = 4, suppress=True)
print("Prediction probabilities are: ")
print(pred_prob[0])

Modello di classificazione completo

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='attribs', shape=input_dim, is_sparse=False)
y_strm = C.io.StreamDef(field='species', 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 main():
print("Using CNTK version = " + str(C.__version__) + "\n")
input_dim = 4
hidden_dim = 5
output_dim = 3
train_file = ".\\...\\" #provide the name of the training file(120 data items)
test_file = ".\\...\\" #provide the name of the test file(30 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)
nnet = oLayer
model = C.ops.softmax(nnet)
tr_loss = C.cross_entropy_with_softmax(nnet, Y)
tr_clas = C.classification_error(nnet, Y)
max_iter = 2000
batch_size = 10
learn_rate = 0.01
learner = C.sgd(nnet.parameters, learn_rate)
trainer = C.Trainer(nnet, (tr_loss, tr_clas), [learner])
max_iter = 2000
batch_size = 10
lr_schedule = C.learning_parameter_schedule_per_sample([(1000, 0.05), (1, 0.01)])
mom_sch = C.momentum_schedule([(100, 0.99), (0, 0.95)], batch_size)
learner = C.fsadagrad(nnet.parameters, lr=lr_schedule, momentum=mom_sch)
trainer = C.Trainer(nnet, (tr_loss, tr_clas), [learner])
rdr = create_reader(train_file, input_dim, output_dim, rnd_order=True, sweeps=C.io.INFINITELY_REPEAT)
iris_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=iris_input_map) trainer.train_minibatch(curr_batch)
if i % 500 == 0:
mcee = trainer.previous_minibatch_loss_average
macc = (1.0 - trainer.previous_minibatch_evaluation_average) * 100
print("batch %4d: mean loss = %0.4f, accuracy = %0.2f%% " \ % (i, mcee, macc))
print("\nEvaluating test data \n")
rdr = create_reader(test_file, input_dim, output_dim, rnd_order=False, sweeps=1)
iris_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
num_test = 30
all_test = rdr.next_minibatch(num_test, input_map=iris_input_map) acc = (1.0 - trainer.test_minibatch(all_test)) * 100
print("Classification accuracy = %0.2f%%" % acc)
np.set_printoptions(precision = 1, suppress=True)
unknown = np.array([[7.0, 3.2, 4.7, 1.4]], dtype=np.float32)
print("\nPredicting species for input features: ")
print(unknown[0])
pred_prob = model.eval(unknown)
np.set_printoptions(precision = 4, suppress=True)
print("Prediction probabilities: ")
print(pred_prob[0])
if __name__== ”__main__”:
main()

Produzione

Using CNTK version = 2.7
batch 0: mean loss = 1.0986, mean accuracy = 40.00%
batch 500: mean loss = 0.6677, mean accuracy = 80.00%
batch 1000: mean loss = 0.5332, mean accuracy = 70.00%
batch 1500: mean loss = 0.2408, mean accuracy = 100.00%
Evaluating test data
Classification accuracy = 94.58%
Predicting species for input features:
[7.0 3.2 4.7 1.4]
Prediction probabilities:
[0.0847 0.736 0.113]

Salvataggio del modello addestrato

Questo set di dati Iris ha solo 150 elementi di dati, quindi occorrerebbero solo pochi secondi per addestrare il modello di classificazione NN, ma l'addestramento su un set di dati di grandi dimensioni con centinaia o migliaia di elementi di dati può richiedere ore o addirittura giorni.

Possiamo salvare il nostro modello in modo da non doverlo conservare da zero. Con l'aiuto del seguente codice Python, possiamo salvare il nostro NN addestrato -

nn_classifier = “.\\neuralclassifier.model” #provide the name of the file
model.save(nn_classifier, format=C.ModelFormat.CNTKv2)

Di seguito sono riportati gli argomenti di save() funzione usata sopra -

  • Il nome del file è il primo argomento di save()funzione. Può anche essere scritto insieme al percorso del file.

  • Un altro parametro è il format parametro che ha un valore predefinito C.ModelFormat.CNTKv2.

Caricamento del modello addestrato

Dopo aver salvato il modello addestrato, è molto facile caricare quel modello. Abbiamo solo bisogno di usare il fileload ()funzione. Controlliamo questo nel seguente esempio:

import numpy as np
import cntk as C
model = C.ops.functions.Function.load(“.\\neuralclassifier.model”)
np.set_printoptions(precision = 1, suppress=True)
unknown = np.array([[7.0, 3.2, 4.7, 1.4]], dtype=np.float32)
print("\nPredicting species for input features: ")
print(unknown[0])
pred_prob = model.eval(unknown)
np.set_printoptions(precision = 4, suppress=True)
print("Prediction probabilities: ")
print(pred_prob[0])

Il vantaggio del modello salvato è che, una volta caricato un modello salvato, può essere utilizzato esattamente come se il modello fosse appena stato addestrato.