<jupyter_start><jupyter_text>Acámica DS-COR3 - Ejercicio de Redes Neuronales Junio 2019  DescripciónEl objetivo de este notebook es ejercitar el ajuste de una Red Neuronal básica sobre un conjunto de datos de dígitos manuscritos de MNIST. En este caso se utilizará Keras como librería para modelar un perceptrón multicapa (MLP), que además provee el dataset a ser utilizado. El notebook está basado en un [ejemplo provisto por Keras](https://github.com/keras-team/keras/blob/master/examples/mnist_mlp.py), por lo cual el ejercicio es seguir paso a paso el desarrollo del mismo y probar ciertos cambios propuestos por los items marcados como **\*\*PREGUNTAS\*\***, así como documentar el efecto de aplicar esos cambios. **Recursos**:  - https://github.com/keras-team/keras/blob/master/examples/mnist_mlp.py- https://medium.com/@mjbhobe/mnist-digits-classification-with-keras-ed6c2374bd0e- https://www.kaggle.com/adityaecdrid/mnist-with-keras-for-beginners-99457- https://towardsdatascience.com/deep-learning-tips-and-tricks-1ef708ec5f53<jupyter_code># Dependencias
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop
from keras.utils import to_categorical<jupyter_output>Using TensorFlow backend.<jupyter_text>Data preparation<jupyter_code># Cargar datasets de MNIST, en conjuntos de train y test
(x_train, y_train), (x_test, y_test) = mnist.load_data()

# Flatten de matrices de 28x28 a vectores de 784 elementos
x_train = x_train.reshape(len(x_train), 784)
x_test = x_test.reshape(len(x_test), 784)

# Casting de int a float
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')

# Min Max scaling: Rango [0, 255] -> [0, 1]
# **PREGUNTA**: Qué efecto tiene en el entrenamiento no hacerlo? 
x_train /= 255
x_test /= 255

# Por último, separar un conj de validación para monitoreo
# Dado que ya está shuffled, se puede tomar los primeros N
x_valid = x_train[-10000:, :]
y_valid = y_train[-10000:]
x_train = x_train[:-10000, :]
y_train = y_train[:-10000]

print(x_train.shape[0], 'train samples')
print(x_valid.shape[0], 'valid samples')
print(x_test.shape[0], 'test samples')
num_classes = 10

# Convertir etiquetas: vector de 10 categorías en matriz binaria de 10 elementos
# De esta forma, ahora el modelo provee como salida una probabilidad por cada clase
y_train = to_categorical(y_train, num_classes)
y_valid = to_categorical(y_valid, num_classes)
y_test = to_categorical(y_test, num_classes)<jupyter_output><empty_output><jupyter_text>Modeling<jupyter_code># Primero se define la ARQUITECTURA
# **PREGUNTAS:**
# 1. Qué pasa si aumento / reduzco la cantidad de neuronas en la primer capa?
# 2. Qué efecto tiene agregar 2 capas de 512 neuronas?
# 3. Qué ocurre si elimino las capas de DropOut?
# 4. Qué efecto tiene cambiar las activaciones de 'relu' a 'tanh'
# 5. Probar agregar una capa de BatchNormalization luego de la primer capa oculta. Qué ocurre y por qué?

model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(784,)))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(num_classes, activation='softmax'))

model.summary()
# Luego definimos la OPTIMIZACIÓN
# **PREGUNTAS:**
# 1. Qué efecto tiene usar un optimizador de tasa fija como SGD
# 2. Qué ocurre si se aumenta la tasa de aprendizaje (parámetro 'lr')
# 3. Qué pasa si uso un batch_size de 10? y uno de 500?
# 4. Analizar la evolución del loss en train y valid, en términos de las épocas (probar hasta 100) 

batch_size = 128
epochs = 20

model.compile(loss='categorical_crossentropy',
              optimizer=RMSprop(),
              metrics=['accuracy'])
# Ajustar el modelo!
history = model.fit(x_train, y_train,
                    batch_size=batch_size,
                    epochs=epochs,
                    verbose=1,
                    validation_data=(x_valid, y_valid))

# Finalmente evaluamos los resultados en test
# **PREGUNTAS**
# 1. Puede haber inconveniente de utilizar "accuracy" para interpretar el desempeño? 
#    (Pensar en cant de clases, desbalance en los datos, etc)
# 2. Calcular precision, recall y f1-score sobre test e interpretar resultados
# 3. Cómo se compara el loss en test con el de train? Qué podría indicar?

score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])<jupyter_output>Test loss: 0.12511385221116994
Test accuracy: 0.9824
{'fraction_non_alphanumeric': 0.09868274168341147, 'fraction_numerical': 0.033712882339807994, 'mean_word_length': 4.707006369426751, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 12, 'https://': 5, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '564205', 'license': 'MIT', 'n_tokens_mistral': 1726, 'n_tokens_neox': 1590, 'n_words': 490, 'path': 'notebooks/s16_neural/DeepLearning_MNIST_Keras.ipynb', 'repo_name': 'leferrad/acamica-ds-cor', 'size': '4479'}