<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Conjunto de datos
Primero, se leen las imágenes para representarlas como un conjunto lineal, en dónde cada pixel es modelado hacia un número entero.
Cabe notar que aquí hay un cambio conceptual acerca de los conjuntos, en dónde en cátedra se tiene que el conjunto de testing es el que se usa para tomar decisiones de hiperparámetros y diseño de las máquinas y es el conjunto de validación el utilizado para elegir entre múltiples máquinas o modelos.
Dado esto, y por consistencia de enunciado, se utilizará la convención dada en esta parte de la tarea
Step1:  Escalamiento
A continuación se presentan dos formas de escalar las imágenes
Step2:  Diseño de redes neuronales
A continuación se presentan propuestas de diseño de redes neuronales para el problema y se selecciona aquel con mejor accuracy sobre el conjunto de validación
Red neuronal 1
Esta red neuronal consiste en la misma red dada en el enunciado, pero que utilizar rmsProps como optimizador
Step3:  Con un accuracy de validación igual a 0.4204
Red neuronal 2
Esta red corresponde a una serie de capas relu con una cantidad de neuronas decreciente y qu siguen potencias de 2. Además, utiliza el mismo optimizador que la red anterior
Step4:  Con un accuracy de validación igual a 0.9341
Red neuronal 3
La misma red neuronal que en 2, pero con menos épocas (60).
Step5:  Con un accuracy de validación igual a 0.7837
Por tanto, la mejor red neuronal corresponde a la segunda
Matriz de confusión
La matriz de confusión de la red neuronal obtenida en el tercer modelo corresponde a
Step6:  Se tiene que mientras más azul es el área, mayor es la dificultad de la red neuronal para clasificar correctamente las clases. Por tanto, se puede observar que a la red le cuesta más clasificar la letra 8 (h) considerando que es en dónde más se tiene conflictos al clasificar.
Cabe notar que es normal que exista una dificultad de clasificación en la diagonal debido a que es dificil distinguir una clase de si misma.
SVM no lineal
Sin procesamiento
La SVM no lineal sin procesamiento toma demasiado tiempo en converger a una solución, por lo que en lugar de buscar hiperparámetros correctos se utilizará una SVM no lineal con parámetro estándar C=0.5 y kernel tipo RBF para obtener algún resultado.
La búsqueda de parámetros se realizará en una SVM con procesamiento.
Step7:  Con accuracy de validación de 0.08
Con procesamiento
Primero, se realizará reducción de dimensionalidad para permitir la búsqueda del mejor hiperparámetro C
Step8:  Que se traduce a un accuracy de validación de 0.9991. Esto indica un posible overfit a los datos de validación, por lo que es de esperar un mal rendimiento al momento de probar los datos de testing.
Árbol de clasificación
Sin procesamiento
Step9:  Con procesamiento
Step10:  Selección de mejor modelo
Utilizando cada máquina con los mejores hiperparámetros y considerando datos con pre procesamiento, se tiene que el mejor modelo estará dado por el accuracy de los datos de testing. Se tiene
<ASSISTANT_TASK:>
Python Code:
import pandas as pd
from sklearn.model_selection import train_test_split
def load_data():
    train = pd.read_csv('data/sign_mnist_train.csv')
    test = pd.read_csv('data/sign_mnist_test.csv')
    (train_set, validation_set) = train_test_split(train, test_size=7000, random_state=8500)
    
    y_tr = train_set['label']
    x_tr = train_set.iloc[:, 1:]
    
    y_t = test['label']
    x_t = test.iloc[:, 1:]
    
    y_v = validation_set['label']
    x_v = validation_set.iloc[:, 1:]
    return(x_tr,x_v,x_t,y_tr,y_v,y_t)
x_tr, x_v, x_t, y_tr, y_v , y_t = load_data()
Explanation: Conjunto de datos
Primero, se leen las imágenes para representarlas como un conjunto lineal, en dónde cada pixel es modelado hacia un número entero.
Cabe notar que aquí hay un cambio conceptual acerca de los conjuntos, en dónde en cátedra se tiene que el conjunto de testing es el que se usa para tomar decisiones de hiperparámetros y diseño de las máquinas y es el conjunto de validación el utilizado para elegir entre múltiples máquinas o modelos.
Dado esto, y por consistencia de enunciado, se utilizará la convención dada en esta parte de la tarea
End of explanation
from sklearn import preprocessing
def scale_by_max_pixel(x_set):
    return x_set/255
def center_and_scale(x_set):
    return preprocessing.scale(x_set)
Explanation: Escalamiento
A continuación se presentan dos formas de escalar las imágenes
End of explanation
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.optimizers import SGD
from keras.utils.np_utils import to_categorical
# Creación de red secuencial
model1 = Sequential()
model1.add(Dense(30, input_dim=x_tr.shape[1], init='uniform', activation='relu'))
model1.add(Dense(30, init='uniform', activation='relu'))
model1.add(Dense(25, init='uniform', activation='softmax'))
model1.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
model1.fit(x_tr.values, to_categorical(y_tr), nb_epoch=100, batch_size=128, verbose=1,
validation_data=(x_v.values,to_categorical(y_v)))
Explanation: Diseño de redes neuronales
A continuación se presentan propuestas de diseño de redes neuronales para el problema y se selecciona aquel con mejor accuracy sobre el conjunto de validación
Red neuronal 1
Esta red neuronal consiste en la misma red dada en el enunciado, pero que utilizar rmsProps como optimizador
End of explanation
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.optimizers import SGD
from keras.utils.np_utils import to_categorical
# Creación de red secuencial
model2 = Sequential()
model2.add(Dense(512, input_dim=x_tr.shape[1], init='uniform', activation='relu'))
model2.add(Dense(256, init='uniform', activation='relu'))
model2.add(Dense(128, init='uniform', activation='relu'))
model2.add(Dense(64, init='uniform', activation='relu'))
model2.add(Dense(32, init='uniform', activation='relu'))
model2.add(Dense(25, init='uniform', activation='softmax'))
model2.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
model2.fit(x_tr.values, to_categorical(y_tr), nb_epoch=100, batch_size=128, verbose=1,
validation_data=(x_v.values,to_categorical(y_v)))
Explanation: Con un accuracy de validación igual a 0.4204
Red neuronal 2
Esta red corresponde a una serie de capas relu con una cantidad de neuronas decreciente y qu siguen potencias de 2. Además, utiliza el mismo optimizador que la red anterior
End of explanation
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.optimizers import SGD
from keras.utils.np_utils import to_categorical
# Creación de red secuencial
model3 = Sequential()
model3.add(Dense(512, input_dim=x_tr.shape[1], init='uniform', activation='relu'))
model3.add(Dense(256, init='uniform', activation='relu'))
model3.add(Dense(128, init='uniform', activation='relu'))
model3.add(Dense(64, init='uniform', activation='relu'))
model3.add(Dense(32, init='uniform', activation='relu'))
model3.add(Dense(25, init='uniform', activation='softmax'))
model3.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
model3.fit(x_tr.values, to_categorical(y_tr), nb_epoch=60, batch_size=128, verbose=1,
validation_data=(x_v.values,to_categorical(y_v)))
Explanation: Con un accuracy de validación igual a 0.9341
Red neuronal 3
La misma red neuronal que en 2, pero con menos épocas (60).
End of explanation
import itertools
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm, datasets
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
y_t_predict = model2.predict_classes(x_t.values)
cm = confusion_matrix(y_t, y_t_predict)
    
plt.figure(figsize=(15, 15))
plt.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues)
plt.colorbar()
plt.show()
Explanation: Con un accuracy de validación igual a 0.7837
Por tanto, la mejor red neuronal corresponde a la segunda
Matriz de confusión
La matriz de confusión de la red neuronal obtenida en el tercer modelo corresponde a:
End of explanation
from sklearn.svm import SVC as SVM
from sklearn.metrics import accuracy_score
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import f1_score
def train_svm(param):
    model = SVM()
    model.set_params(C=param, kernel='rbf')
    model.fit(x_tr, y_tr)
    y_tr_pred = model.predict(x_tr)
    y_v_pred = model.predict(x_v)
    train_error = (1-accuracy_score(y_tr, y_tr_pred))
    test_error = (1-accuracy_score(y_v, y_v_pred))
    
    return (train_error, test_error)
def graph_svm_range(params):
    train_errors = []
    test_errors = []
    for depth in params:
        print('Trying param %f' % depth)
        (train, test) = train_svm(depth)
        train_errors.append(train)
        test_errors.append(test)
    plt.figure(figsize=(10, 8))
    plt.plot(params, train_errors, label="Train Error")
    plt.plot(params, test_errors, label="Test Error")
    plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
    plt.xlabel('RBF')
    plt.ylabel('Error')
    plt.show()
    
train_svm(0.5)
Explanation: Se tiene que mientras más azul es el área, mayor es la dificultad de la red neuronal para clasificar correctamente las clases. Por tanto, se puede observar que a la red le cuesta más clasificar la letra 8 (h) considerando que es en dónde más se tiene conflictos al clasificar.
Cabe notar que es normal que exista una dificultad de clasificación en la diagonal debido a que es dificil distinguir una clase de si misma.
SVM no lineal
Sin procesamiento
La SVM no lineal sin procesamiento toma demasiado tiempo en converger a una solución, por lo que en lugar de buscar hiperparámetros correctos se utilizará una SVM no lineal con parámetro estándar C=0.5 y kernel tipo RBF para obtener algún resultado.
La búsqueda de parámetros se realizará en una SVM con procesamiento.
End of explanation
from sklearn.decomposition import PCA
import numpy as np
x_tr_scaled = center_and_scale(x_tr)
x_t_scaled = center_and_scale(x_t)
x_v_scaled = center_and_scale(x_v)
pca_model = PCA(n_components=150)
pca_model.fit(x_tr_scaled)
x_tr_dim = pca_model.transform(x_tr_scaled)
x_t_dim = pca_model.transform(x_tr_scaled)
x_v_dim = pca_model.transform(x_v_scaled)
def train_svm(param, x_tr, y_tr, x_v, y_v):
    model = SVM()
    model.set_params(C=param, kernel='rbf')
    model.fit(x_tr, y_tr)
    y_tr_pred = model.predict(x_tr)
    y_v_pred = model.predict(x_v)
    train_error = (1-accuracy_score(y_tr, y_tr_pred))
    test_error = (1-accuracy_score(y_v, y_v_pred))
    
    return (train_error, test_error)
def graph_svm_range(params, x_tr, y_tr, x_v, y_v):
    train_errors = []
    test_errors = []
    for depth in params:
        print('Trying param %f' % depth)
        (train, test) = train_svm(depth, x_tr, y_tr, x_v, y_v)
        train_errors.append(train)
        test_errors.append(test)
    plt.figure(figsize=(10, 8))
    plt.plot(params, train_errors, label="Train Error")
    plt.plot(params, test_errors, label="Test Error")
    plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
    plt.xlabel('RBF')
    plt.ylabel('Error')
    plt.show()
params = np.arange(0.001, 1.0, 0.25)
graph_svm_range(params, x_tr_dim, y_tr, x_v_dim, y_v)
train_svm(0.75, x_tr_dim, y_tr, x_v_dim, y_v)
Explanation: Con accuracy de validación de 0.08
Con procesamiento
Primero, se realizará reducción de dimensionalidad para permitir la búsqueda del mejor hiperparámetro C
End of explanation
from sklearn.tree import DecisionTreeClassifier as Tree
from sklearn.metrics import accuracy_score
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import f1_score
def train_tree(depth, x_tr, y_tr, x_v, y_v):
    # Entrenar el árbol
    model = Tree()
    model.set_params(max_depth=depth, criterion='gini', splitter='best')
    model.fit(x_tr, y_tr)
    y_tr_pred = model.predict(x_tr)
    y_v_pred = model.predict(x_v)
    train_error = (accuracy_score(y_tr, y_tr_pred))
    test_error = (accuracy_score(y_v, y_v_pred))
    return (train_error, test_error)
def graph_tree_range(params, x_tr, y_tr, x_v, y_v):
    train_errors = []
    test_errors = []
    for depth in params:
        print('Trying depth %d' % depth)
        (train, test) = train_tree(depth, x_tr, y_tr, x_v, y_v)
        train_errors.append(train)
        test_errors.append(test)
    plt.figure(figsize=(10, 8))
    plt.plot(params, train_errors, label="Train accuracy")
    plt.plot(params, test_errors, label="Validation accuracy")
    plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
    plt.xlabel('Profundidad del árbol')
    plt.ylabel('Error')
    plt.show()
    
params = np.arange(1, 30, 1)
graph_tree_range(params, x_tr, y_tr, x_v, y_v)
Explanation: Que se traduce a un accuracy de validación de 0.9991. Esto indica un posible overfit a los datos de validación, por lo que es de esperar un mal rendimiento al momento de probar los datos de testing.
Árbol de clasificación
Sin procesamiento
End of explanation
x_tr_scaled = center_and_scale(x_tr)
x_t_scaled = center_and_scale(x_t)
x_v_scaled = center_and_scale(x_v)
params = np.arange(1, 30, 1)
graph_tree_range(params, x_tr_scaled, y_tr, x_v_scaled, y_v)
Explanation: Con procesamiento
End of explanation
from sklearn.metrics import accuracy_score
# Neural network
y_t_pred = model3.predict_classes(x_t.values)
print("Accuracy red neuronal: %f" % accuracy_score(y_t, y_t_pred))
tree_accuracy = train_tree(30, x_tr_scaled, y_tr, x_t_scaled, y_t)
print("Accuracy decision tree: %f" % tree_accuracy[1])
x_t_dim = pca_model.transform(x_t_scaled)
svm_errors = train_svm(0.75, x_tr_dim, y_tr, x_t_dim, y_t)
svm_errors
svm_acc = (svm_errors[1] - 1)*-1
print("Accuracy SVM: %f" % svm_acc)
Explanation: Selección de mejor modelo
Utilizando cada máquina con los mejores hiperparámetros y considerando datos con pre procesamiento, se tiene que el mejor modelo estará dado por el accuracy de los datos de testing. Se tiene:
End of explanation
<END_TASK>