Python Deep Learning - Implementazioni

In questa implementazione del Deep learning, il nostro obiettivo è quello di prevedere l'attrito dei clienti o l'abbandono dei dati per una determinata banca, i cui clienti probabilmente lasceranno questo servizio bancario. Il set di dati utilizzato è relativamente piccolo e contiene 10000 righe con 14 colonne. Stiamo usando la distribuzione Anaconda e framework come Theano, TensorFlow e Keras. Keras è costruito sopra Tensorflow e Theano che fungono da backend.

# Artificial Neural Network
# Installing Theano
pip install --upgrade theano

# Installing Tensorflow
pip install –upgrade tensorflow

# Installing Keras
pip install --upgrade keras

Passaggio 1: pre-elaborazione dei dati

In[]:

# Importing the libraries
   import numpy as np
   import matplotlib.pyplot as plt
   import pandas as pd
 
# Importing the database
   dataset = pd.read_csv('Churn_Modelling.csv')

Passo 2

Creiamo matrici delle caratteristiche del dataset e della variabile target, che è la colonna 14, etichettata come "Exited".

L'aspetto iniziale dei dati è come mostrato di seguito:

In[]:
X = dataset.iloc[:, 3:13].values
Y = dataset.iloc[:, 13].values
X

Produzione

Passaggio 3

Y

Produzione

array([1, 0, 1, ..., 1, 1, 0], dtype = int64)

Passaggio 4

Rendiamo l'analisi più semplice codificando variabili stringa. Stiamo utilizzando la funzione ScikitLearn "LabelEncoder" per codificare automaticamente le diverse etichette nelle colonne con valori compresi tra 0 e n_classes-1.

from sklearn.preprocessing import LabelEncoder, OneHotEncoder
labelencoder_X_1 = LabelEncoder() 
X[:,1] = labelencoder_X_1.fit_transform(X[:,1]) 
labelencoder_X_2 = LabelEncoder() 
X[:, 2] = labelencoder_X_2.fit_transform(X[:, 2])
X

Produzione

Nell'output precedente, i nomi dei paesi sono sostituiti da 0, 1 e 2; mentre maschio e femmina sono sostituiti da 0 e 1.

Passaggio 5

Labelling Encoded Data

Usiamo lo stesso ScikitLearn libreria e un'altra funzione chiamata OneHotEncoder per passare semplicemente il numero di colonna creando una variabile fittizia.

onehotencoder = OneHotEncoder(categorical features = [1])
X = onehotencoder.fit_transform(X).toarray()
X = X[:, 1:]
X

Ora, le prime 2 colonne rappresentano il paese e la quarta colonna rappresenta il sesso.

Produzione

Dividiamo sempre i nostri dati in parte di addestramento e test; addestriamo il nostro modello sui dati di addestramento e poi controlliamo l'accuratezza di un modello sui dati di test che aiutano a valutare l'efficienza del modello.

Passaggio 6

Stiamo usando ScikitLearn's train_test_splitfunzione per dividere i nostri dati in training set e test set. Manteniamo il rapporto di divisione treno-test su 80:20.

#Splitting the dataset into the Training set and the Test Set
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2)

Alcune variabili hanno valori in migliaia mentre altre hanno valori in decine o unità. Scaliamo i dati in modo che siano più rappresentativi.

Passaggio 7

In questo codice, stiamo adattando e trasformando i dati di addestramento utilizzando StandardScalerfunzione. Standardizziamo il nostro ridimensionamento in modo da utilizzare lo stesso metodo adattato per trasformare / scalare i dati dei test.

# Feature Scaling
fromsklearn.preprocessing import StandardScaler 
sc = StandardScaler() 
X_train = sc.fit_transform(X_train) 
X_test = sc.transform(X_test)

Produzione

I dati sono ora ridimensionati correttamente. Infine, abbiamo finito con la nostra pre-elaborazione dei dati. Ora inizieremo con il nostro modello.

Passaggio 8

Importiamo qui i moduli richiesti. Abbiamo bisogno del modulo sequenziale per inizializzare la rete neurale e del modulo denso per aggiungere gli strati nascosti.

# Importing the Keras libraries and packages 
import keras 
from keras.models import Sequential 
from keras.layers import Dense

Passaggio 9

Chiameremo il modello Classifier poiché il nostro obiettivo è classificare il tasso di abbandono dei clienti. Quindi usiamo il modulo sequenziale per l'inizializzazione.

#Initializing Neural Network 
classifier = Sequential()

Passaggio 10

Aggiungiamo gli strati nascosti uno per uno usando la funzione densa. Nel codice seguente vedremo molti argomenti.

Il nostro primo parametro è output_dim. È il numero di nodi che aggiungiamo a questo livello.initè l'inizializzazione dello Stochastic Gradient Decent. In una rete neurale assegniamo pesi a ciascun nodo. All'inizializzazione, i pesi dovrebbero essere vicini allo zero e inizializziamo casualmente i pesi utilizzando la funzione uniform. Ilinput_dimparametro è necessario solo per il primo livello, poiché il modello non conosce il numero delle nostre variabili di input. Qui il numero totale di variabili di input è 11. Nel secondo livello, il modello conosce automaticamente il numero di variabili di input dal primo livello nascosto.

Esegui la seguente riga di codice per aggiungere il livello di input e il primo livello nascosto -

classifier.add(Dense(units = 6, kernel_initializer = 'uniform', 
activation = 'relu', input_dim = 11))

Esegui la seguente riga di codice per aggiungere il secondo livello nascosto -

classifier.add(Dense(units = 6, kernel_initializer = 'uniform', 
activation = 'relu'))

Esegui la seguente riga di codice per aggiungere il livello di output:

classifier.add(Dense(units = 1, kernel_initializer = 'uniform', 
activation = 'sigmoid'))

Passaggio 11

Compiling the ANN

Finora abbiamo aggiunto più livelli al nostro classificatore. Ora li compileremo usando ilcompilemetodo. Gli argomenti aggiunti nel controllo finale della compilazione completano la rete neurale, quindi dobbiamo fare attenzione in questo passaggio.

Ecco una breve spiegazione degli argomenti.

Il primo argomento è OptimizerQuesto è un algoritmo utilizzato per trovare l'insieme ottimale di pesi. Questo algoritmo è chiamatoStochastic Gradient Descent (SGD). Qui ne stiamo usando uno tra diversi tipi, chiamato "ottimizzatore di Adam". L'SGD dipende dalla perdita, quindi il nostro secondo parametro è la perdita. Se la nostra variabile dipendente è binaria, usiamo la funzione di perdita logaritmica chiamata‘binary_crossentropy’e se la nostra variabile dipendente ha più di due categorie in output, allora usiamo ‘categorical_crossentropy’. Vogliamo migliorare le prestazioni della nostra rete neurale basata suaccuracy, quindi aggiungiamo metrics come accuratezza.

# Compiling Neural Network 
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])

Passaggio 12

In questa fase è necessario eseguire una serie di codici.

Adattare l'ANN al set di addestramento

Ora addestriamo il nostro modello sui dati di addestramento. Noi usiamo ilfitmetodo per adattarsi al nostro modello. Ottimizziamo anche i pesi per migliorare l'efficienza del modello. Per questo, dobbiamo aggiornare i pesi.Batch size è il numero di osservazioni dopo le quali aggiorniamo i pesi. Epochè il numero totale di iterazioni. I valori della dimensione del lotto e dell'epoca vengono scelti dal metodo per tentativi ed errori.

classifier.fit(X_train, y_train, batch_size = 10, epochs = 50)

Fare previsioni e valutare il modello

# Predicting the Test set results
y_pred = classifier.predict(X_test)
y_pred = (y_pred > 0.5)

Prevedere un'unica nuova osservazione

# Predicting a single new observation
"""Our goal is to predict if the customer with the following data will leave the bank:
Geography: Spain
Credit Score: 500
Gender: Female
Age: 40
Tenure: 3
Balance: 50000
Number of Products: 2
Has Credit Card: Yes
Is Active Member: Yes

Passaggio 13

Predicting the test set result

Il risultato della previsione ti darà la probabilità che il cliente lasci l'azienda. Convertiremo quella probabilità in binari 0 e 1.

# Predicting the Test set results 
y_pred = classifier.predict(X_test) 
y_pred = (y_pred > 0.5)
new_prediction = classifier.predict(sc.transform
(np.array([[0.0, 0, 500, 1, 40, 3, 50000, 2, 1, 1, 40000]])))
new_prediction = (new_prediction > 0.5)

Passaggio 14

Questo è l'ultimo passaggio in cui valutiamo le prestazioni del nostro modello. Abbiamo già risultati originali e quindi possiamo costruire una matrice di confusione per verificare l'accuratezza del nostro modello.

Making the Confusion Matrix

from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test, y_pred)
print (cm)

Produzione

loss: 0.3384 acc: 0.8605
[ [1541 54]
[230 175] ]

Dalla matrice di confusione, l'accuratezza del nostro modello può essere calcolata come:

Accuracy = 1541+175/2000=0.858

We achieved 85.8% accuracy, che è buono.

L'algoritmo di propagazione in avanti

In questa sezione impareremo come scrivere codice per eseguire la propagazione in avanti (previsione) per una semplice rete neurale -

Ogni punto dati è un cliente. Il primo input è quanti account hanno e il secondo input è quanti figli hanno. Il modello prevederà quante transazioni l'utente farà nel prossimo anno.

I dati di input sono precaricati come dati di input e i pesi sono in un dizionario chiamato pesi. L'array di pesi per il primo nodo nello strato nascosto è espresso in pesi ['node_0'], e per il secondo nodo nello strato nascosto sono rispettivamente in pesi ['nodo_1'].

I pesi che alimentano il nodo di output sono disponibili in pesi.

La funzione di attivazione lineare rettificata

Una "funzione di attivazione" è una funzione che opera su ogni nodo. Trasforma l'input del nodo in un output.

La funzione di attivazione lineare rettificata (denominata ReLU ) è ampiamente utilizzata in reti ad altissime prestazioni. Questa funzione accetta un singolo numero come input, restituendo 0 se l'input è negativo e input come output se l'input è positivo.

Ecco alcuni esempi:

  • relu (4) = 4
  • relu (-2) = 0

Completiamo la definizione della funzione relu () -

  • Usiamo la funzione max () per calcolare il valore per l'output di relu ().
  • Applichiamo la funzione relu () a node_0_input per calcolare node_0_output.
  • Applichiamo la funzione relu () a node_1_input per calcolare node_1_output.
import numpy as np
input_data = np.array([-1, 2])
weights = {
   'node_0': np.array([3, 3]),
   'node_1': np.array([1, 5]),
   'output': np.array([2, -1])
}
node_0_input = (input_data * weights['node_0']).sum()
node_0_output = np.tanh(node_0_input)
node_1_input = (input_data * weights['node_1']).sum()
node_1_output = np.tanh(node_1_input)
hidden_layer_output = np.array(node_0_output, node_1_output)
output =(hidden_layer_output * weights['output']).sum()
print(output)

def relu(input):
   '''Define your relu activation function here'''
   # Calculate the value for the output of the relu function: output
   output = max(input,0)
      # Return the value just calculated
   return(output)
# Calculate node 0 value: node_0_output
node_0_input = (input_data * weights['node_0']).sum()
node_0_output = relu(node_0_input)

# Calculate node 1 value: node_1_output
node_1_input = (input_data * weights['node_1']).sum()
node_1_output = relu(node_1_input)

# Put node values into array: hidden_layer_outputs
hidden_layer_outputs = np.array([node_0_output, node_1_output])

# Calculate model output (do not apply relu)
odel_output = (hidden_layer_outputs * weights['output']).sum()
print(model_output)# Print model output

Produzione

0.9950547536867305
-3

Applicazione della rete a molte osservazioni / righe di dati

In questa sezione, impareremo come definire una funzione chiamata prediction_with_network (). Questa funzione genererà previsioni per più osservazioni di dati, prese dalla rete sopra presa come input_data. Vengono utilizzati i pesi indicati nella rete sopra. Viene utilizzata anche la definizione della funzione relu ().

Definiamo una funzione chiamata prediction_with_network () che accetta due argomenti - input_data_row e weights - e restituisce una previsione dalla rete come output.

Calcoliamo i valori di input e output per ogni nodo, memorizzandoli come: node_0_input, node_0_output, node_1_input e node_1_output.

Per calcolare il valore di input di un nodo, moltiplichiamo insieme gli array rilevanti e calcoliamo la loro somma.

Per calcolare il valore di output di un nodo, applichiamo la funzione relu () al valore di input del nodo. Usiamo un 'ciclo for' per iterare su input_data -

Usiamo anche il nostro prediction_with_network () per generare previsioni per ogni riga di input_data - input_data_row. Inoltre aggiungiamo ogni previsione ai risultati.

# Define predict_with_network()
def predict_with_network(input_data_row, weights):
   # Calculate node 0 value
   node_0_input = (input_data_row * weights['node_0']).sum()
   node_0_output = relu(node_0_input)
   
   # Calculate node 1 value
   node_1_input = (input_data_row * weights['node_1']).sum()
   node_1_output = relu(node_1_input)
   
   # Put node values into array: hidden_layer_outputs
   hidden_layer_outputs = np.array([node_0_output, node_1_output])
   
   # Calculate model output
   input_to_final_layer = (hidden_layer_outputs*weights['output']).sum()
   model_output = relu(input_to_final_layer)
# Return model output
   return(model_output)

# Create empty list to store prediction results
results = []
for input_data_row in input_data:
   # Append prediction to results
   results.append(predict_with_network(input_data_row, weights))
print(results)# Print results

Produzione

[0, 12]

Qui abbiamo usato la funzione relu dove relu (26) = 26 e relu (-13) = 0 e così via.

Reti neurali multistrato profonde

Qui stiamo scrivendo il codice per eseguire la propagazione in avanti per una rete neurale con due livelli nascosti. Ogni livello nascosto ha due nodi. I dati di input sono stati precaricati comeinput_data. I nodi nel primo livello nascosto sono chiamati node_0_0 e node_0_1.

I loro pesi sono precaricati rispettivamente come pesi ['node_0_0'] e pesi ['node_0_1'].

Vengono chiamati i nodi nel secondo livello nascosto node_1_0 and node_1_1. I loro pesi sono precaricati comeweights['node_1_0'] e weights['node_1_1'] rispettivamente.

Creiamo quindi un output del modello dai nodi nascosti utilizzando pesi precaricati come weights['output'].

Calcoliamo node_0_0_input usando i suoi pesi pesi ['node_0_0'] ei dati input_data. Quindi applica la funzione relu () per ottenere node_0_0_output.

Facciamo lo stesso come sopra per node_0_1_input per ottenere node_0_1_output.

Calcoliamo node_1_0_input usando i suoi pesi pesi ['node_1_0'] e gli output dal primo livello nascosto - hidden_0_outputs. Quindi applichiamo la funzione relu () per ottenere node_1_0_output.

Facciamo lo stesso come sopra per node_1_1_input per ottenere node_1_1_output.

Calcoliamo model_output usando i pesi ['output'] e gli output del secondo livello nascosto hidden_1_outputs array. Non applichiamo la funzione relu () a questo output.

import numpy as np
input_data = np.array([3, 5])
weights = {
   'node_0_0': np.array([2, 4]),
   'node_0_1': np.array([4, -5]),
   'node_1_0': np.array([-1, 1]),
   'node_1_1': np.array([2, 2]),
   'output': np.array([2, 7])
}
def predict_with_network(input_data):
   # Calculate node 0 in the first hidden layer
   node_0_0_input = (input_data * weights['node_0_0']).sum()
   node_0_0_output = relu(node_0_0_input)
   
   # Calculate node 1 in the first hidden layer
   node_0_1_input = (input_data*weights['node_0_1']).sum()
   node_0_1_output = relu(node_0_1_input)
   
   # Put node values into array: hidden_0_outputs
   hidden_0_outputs = np.array([node_0_0_output, node_0_1_output])
   
   # Calculate node 0 in the second hidden layer
   node_1_0_input = (hidden_0_outputs*weights['node_1_0']).sum()
   node_1_0_output = relu(node_1_0_input)
   
   # Calculate node 1 in the second hidden layer
   node_1_1_input = (hidden_0_outputs*weights['node_1_1']).sum()
   node_1_1_output = relu(node_1_1_input)
   
   # Put node values into array: hidden_1_outputs
   hidden_1_outputs = np.array([node_1_0_output, node_1_1_output])
   
   # Calculate model output: model_output
   model_output = (hidden_1_outputs*weights['output']).sum()
      # Return model_output
   return(model_output)
output = predict_with_network(input_data)
print(output)

Produzione

364