Aprendizaje profundo de Python: implementaciones
En esta implementación de aprendizaje profundo, nuestro objetivo es predecir la pérdida de clientes o los datos agitados para un determinado banco, qué clientes es probable que abandonen este servicio bancario. El conjunto de datos utilizado es relativamente pequeño y contiene 10000 filas con 14 columnas. Estamos utilizando la distribución de Anaconda y marcos como Theano, TensorFlow y Keras. Keras se basa en Tensorflow y Theano, que funcionan como backends.
# Artificial Neural Network
# Installing Theano
pip install --upgrade theano
# Installing Tensorflow
pip install –upgrade tensorflow
# Installing Keras
pip install --upgrade keras
Paso 1: preprocesamiento de datos
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')
Paso 2
Creamos matrices de las características del conjunto de datos y la variable objetivo, que es la columna 14, etiquetada como "Salido".
El aspecto inicial de los datos es el que se muestra a continuación:
In[]:
X = dataset.iloc[:, 3:13].values
Y = dataset.iloc[:, 13].values
X
Salida
Paso 3
Y
Salida
array([1, 0, 1, ..., 1, 1, 0], dtype = int64)
Etapa 4
Simplificamos el análisis codificando variables de cadena. Estamos usando la función ScikitLearn 'LabelEncoder' para codificar automáticamente las diferentes etiquetas en las columnas con valores entre 0 y 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
Salida
En el resultado anterior, los nombres de los países se reemplazan por 0, 1 y 2; mientras que macho y hembra se reemplazan por 0 y 1.
Paso 5
Labelling Encoded Data
Usamos lo mismo ScikitLearn biblioteca y otra función llamada OneHotEncoder simplemente pasar el número de columna creando una variable ficticia.
onehotencoder = OneHotEncoder(categorical features = [1])
X = onehotencoder.fit_transform(X).toarray()
X = X[:, 1:]
X
Ahora, las 2 primeras columnas representan el país y la cuarta columna representa el género.
Salida
Siempre dividimos nuestros datos en parte de entrenamiento y prueba; entrenamos nuestro modelo en datos de entrenamiento y luego verificamos la precisión de un modelo en los datos de prueba que ayudan a evaluar la eficiencia del modelo.
Paso 6
Estamos usando ScikitLearn's train_test_splitfunción para dividir nuestros datos en conjunto de entrenamiento y conjunto de prueba. Mantenemos la relación de división de tren a prueba en 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)
Algunas variables tienen valores en miles, mientras que otras tienen valores en decenas o unidades. Escalamos los datos para que sean más representativos.
Paso 7
En este código, estamos ajustando y transformando los datos de entrenamiento usando el StandardScalerfunción. Estandarizamos nuestro escalado para que usemos el mismo método ajustado para transformar / escalar datos de prueba.
# Feature Scaling
fromsklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
Salida
Los datos ahora se escalan correctamente. Finalmente, hemos terminado con nuestro procesamiento previo de datos. Ahora, comenzaremos con nuestro modelo.
Paso 8
Importamos los módulos necesarios aquí. Necesitamos el módulo secuencial para inicializar la red neuronal y el módulo denso para agregar las capas ocultas.
# Importing the Keras libraries and packages
import keras
from keras.models import Sequential
from keras.layers import Dense
Paso 9
Nombraremos el modelo como Clasificador ya que nuestro objetivo es clasificar la rotación de clientes. Luego usamos el módulo Sequential para la inicialización.
#Initializing Neural Network
classifier = Sequential()
Paso 10
Agregamos las capas ocultas una por una usando la función densa. En el código siguiente, veremos muchos argumentos.
Nuestro primer parámetro es output_dim. Es la cantidad de nodos que agregamos a esta capa.inites la inicialización del estocástico gradiente decente. En una red neuronal asignamos pesos a cada nodo. En la inicialización, los pesos deben estar cerca de cero e inicializamos aleatoriamente los pesos usando la función uniforme. losinput_dimEl parámetro es necesario solo para la primera capa, ya que el modelo no conoce el número de nuestras variables de entrada. Aquí el número total de variables de entrada es 11. En la segunda capa, el modelo conoce automáticamente el número de variables de entrada de la primera capa oculta.
Ejecute la siguiente línea de código para agregar la capa de entrada y la primera capa oculta:
classifier.add(Dense(units = 6, kernel_initializer = 'uniform',
activation = 'relu', input_dim = 11))
Ejecute la siguiente línea de código para agregar la segunda capa oculta:
classifier.add(Dense(units = 6, kernel_initializer = 'uniform',
activation = 'relu'))
Ejecute la siguiente línea de código para agregar la capa de salida:
classifier.add(Dense(units = 1, kernel_initializer = 'uniform',
activation = 'sigmoid'))
Paso 11
Compiling the ANN
Hemos agregado múltiples capas a nuestro clasificador hasta ahora. Ahora los compilaremos usando elcompilemétodo. Los argumentos agregados en el control de compilación final completan la red neuronal, por lo que debemos tener cuidado en este paso.
Aquí hay una breve explicación de los argumentos.
El primer argumento es OptimizerEste es un algoritmo que se utiliza para encontrar el conjunto óptimo de pesos. Este algoritmo se llamaStochastic Gradient Descent (SGD). Aquí estamos usando uno entre varios tipos, llamado 'optimizador de Adam'. El SGD depende de la pérdida, por lo que nuestro segundo parámetro es la pérdida. Si nuestra variable dependiente es binaria, usamos la función de pérdida logarítmica llamada‘binary_crossentropy’, y si nuestra variable dependiente tiene más de dos categorías en la salida, usamos ‘categorical_crossentropy’. Queremos mejorar el rendimiento de nuestra red neuronal basándonos enaccuracy, entonces agregamos metrics como precisión.
# Compiling Neural Network
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
Paso 12
Es necesario ejecutar varios códigos en este paso.
Adaptación de la ANN al conjunto de entrenamiento
Ahora entrenamos nuestro modelo con los datos de entrenamiento. Usamos elfitmétodo para adaptarse a nuestro modelo. También optimizamos los pesos para mejorar la eficiencia del modelo. Para ello, tenemos que actualizar los pesos.Batch size es el número de observaciones después de las cuales actualizamos los pesos. Epoches el número total de iteraciones. Los valores de tamaño de lote y época se eligen mediante el método de prueba y error.
classifier.fit(X_train, y_train, batch_size = 10, epochs = 50)
Hacer predicciones y evaluar el modelo
# Predicting the Test set results
y_pred = classifier.predict(X_test)
y_pred = (y_pred > 0.5)
Predecir una única observación nueva
# 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
Paso 13
Predicting the test set result
El resultado de la predicción le dará la probabilidad de que el cliente abandone la empresa. Convertiremos esa probabilidad en 0 y 1 binarios.
# 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)
Paso 14
Este es el último paso en el que evaluamos el rendimiento de nuestro modelo. Ya tenemos resultados originales y, por lo tanto, podemos construir una matriz de confusión para verificar la precisión de nuestro modelo.
Making the Confusion Matrix
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test, y_pred)
print (cm)
Salida
loss: 0.3384 acc: 0.8605
[ [1541 54]
[230 175] ]
A partir de la matriz de confusión, la precisión de nuestro modelo se puede calcular como:
Accuracy = 1541+175/2000=0.858
We achieved 85.8% accuracy, lo que es bueno.
El algoritmo de propagación hacia adelante
En esta sección, aprenderemos cómo escribir código para hacer la propagación (predicción) hacia adelante para una red neuronal simple:
Cada punto de datos es un cliente. La primera entrada es cuántas cuentas tienen y la segunda entrada es cuántos hijos tienen. El modelo predecirá cuántas transacciones realizará el usuario en el próximo año.
Los datos de entrada se cargan previamente como datos de entrada y los pesos están en un diccionario llamado pesos. La matriz de pesos para el primer nodo en la capa oculta está en pesos ['nodo_0'], y para el segundo nodo en la capa oculta está en pesos ['nodo_1'] respectivamente.
Los pesos que ingresan al nodo de salida están disponibles en pesos.
La función de activación lineal rectificada
Una "función de activación" es una función que trabaja en cada nodo. Transforma la entrada del nodo en alguna salida.
La función de activación lineal rectificada (llamada ReLU ) se utiliza ampliamente en redes de muy alto rendimiento. Esta función toma un solo número como entrada, devolviendo 0 si la entrada es negativa y entrada como salida si la entrada es positiva.
A continuación se muestran algunos ejemplos:
- relu (4) = 4
- relu (-2) = 0
Completamos la definición de la función relu ()
- Usamos la función max () para calcular el valor de la salida de relu ().
- Aplicamos la función relu () a node_0_input para calcular node_0_output.
- Aplicamos la función relu () a node_1_input para calcular 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
Salida
0.9950547536867305
-3
Aplicar la red a muchas observaciones / filas de datos
En esta sección, aprenderemos cómo definir una función llamada predict_with_network (). Esta función generará predicciones para múltiples observaciones de datos, tomadas de la red anterior como input_data. Se están utilizando los pesos dados en la red anterior. También se está utilizando la definición de la función relu ().
Definamos una función llamada predict_with_network () que acepta dos argumentos, input_data_row y weights, y devuelve una predicción de la red como salida.
Calculamos los valores de entrada y salida para cada nodo, almacenándolos como: node_0_input, node_0_output, node_1_input y node_1_output.
Para calcular el valor de entrada de un nodo, multiplicamos las matrices relevantes juntas y calculamos su suma.
Para calcular el valor de salida de un nodo, aplicamos la función relu () al valor de entrada del nodo. Usamos un 'bucle for' para iterar sobre input_data -
También usamos nuestro predict_with_network () para generar predicciones para cada fila de input_data - input_data_row. También adjuntamos cada predicción a los resultados.
# 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
Salida
[0, 12]
Aquí hemos utilizado la función relu donde relu (26) = 26 y relu (-13) = 0 y así sucesivamente.
Redes neuronales profundas de múltiples capas
Aquí estamos escribiendo código para hacer propagación hacia adelante para una red neuronal con dos capas ocultas. Cada capa oculta tiene dos nodos. Los datos de entrada se han precargado comoinput_data. Los nodos de la primera capa oculta se denominan nodo_0_0 y nodo_0_1.
Sus pesos están precargados como pesos ['nodo_0_0'] y pesos ['nodo_0_1'] respectivamente.
Los nodos de la segunda capa oculta se denominan node_1_0 and node_1_1. Sus pesos están precargados comoweights['node_1_0'] y weights['node_1_1'] respectivamente.
Luego creamos una salida de modelo a partir de los nodos ocultos usando pesos precargados como weights['output'].
Calculamos node_0_0_input usando sus pesos ponderaciones ['node_0_0'] y los input_data dados. Luego aplique la función relu () para obtener node_0_0_output.
Hacemos lo mismo que el anterior para node_0_1_input para obtener node_0_1_output.
Calculamos node_1_0_input usando sus pesos ponderaciones ['node_1_0'] y las salidas de la primera capa oculta: hidden_0_outputs. Luego aplicamos la función relu () para obtener node_1_0_output.
Hacemos lo mismo que arriba para node_1_1_input para obtener node_1_1_output.
Calculamos model_output usando pesos ['output'] y los resultados de la segunda capa oculta hidden_1_outputs array. No aplicamos la función relu () a esta salida.
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)
Salida
364