ExamenSustitutorio CC421

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 11

ExamenSustitutorio-CC421

January 7, 2022

0.1 Examen Sustitutorio de Inteligencia Artificial


0.1.1 Instrucciones
• Debes entregar un cuaderno en colab o de jupyter con todas tus respuestas, no se acepta otro
formato ni tampoco archivo comprimidos.
• Debes responder y explicar todos los ítems de las preguntas dadas, de lo contrario la pregunta
se puntua como 0.
• El examen dura 3 horas.
• Evita copiar!.

0.1.2 Pregunta 1 (5 puntos)


En esta parte del examen realizarás un ejercicio práctico de clasificación. Puedes usar tus apuntes
y consultar fuentes externas.
Usaremos el conjunto de datos Breast Cancer Wisconsin (Diagnostic) Data Set preparado por W.N.
Street, W.H. Wolberg and O.L. Mangasarian.
Las características del conjunto de datos han sido calculadas a partir de una imagen digitalizada
de un aspirado con aguja fina (FNA) de una masa mamaria. Describen las características de los
núcleos celulares presentes en la imagen.
Abordarás un problema de clasificación binaria y tratarás de identificar las muestras que corre-
sponden a un tumor maligno de cáncer.
[ ]: import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split, GridSearchCV
import matplotlib.pyplot as plt

df = pd.read_csv('https://raw.githubusercontent.com/jeffheaton/aifh/master/vol1/
,→python-examples/datasets/breast-cancer-wisconsin.csv', na_values='?',␣

,→index_col='id')

df.drop(columns=['shape_uniformity', 'size_uniformity', 'bare_nucleoli',␣


,→'epithelial_size'], inplace=True) # No usaremos estas características

features = df.columns[:-1]
target = df.columns[-1]
print('Features: ', features)

1
print('Target: ', target)
df.head()

Pregunta: (0.5 puntos) Asigna a una variable de nombre X las columnas de características (todas
menos class)

[ ]: # Completa

[ ]: # Completa

[ ]: ### Inicio de tu código


###
### Fin de tu código

#print('Dimensiones de df:', df.shape)


#print('Tipo de X:', type(X))
#print('Dimensiones de X:', X.shape)

Pregunta: (1 punto) Crea una variable de nombre y (minúscula) que tenga valor 1 cuando class
= 4 (tumor maligno) y valor 0 cuando class = 2 (tumor benigno).

[ ]: ### Inicio de tu código


# Completa
# ...
# df['target'].value_counts()/len(df)*100
# Fin de tu código

[ ]: #df.head()

[ ]: # Estandarizamos el dataset
#from sklearn.preprocessing import scale
#X = scale(df.drop(['class','target'],axis=1))

#dataset_normalizado = pd.DataFrame(X, index=df.index, columns=df.columns[0:-2])


#dataset_normalizado['target'] = df['target']
#dataset_normalizado.head()

Pregunta: (0.5 puntos) Separa X y y en un conjunto de entrenamiento y uno de pruebas (20%).


Escribe la proporción del conjunto de prueba.
[ ]: ### Inicio de tu código
### ...
### Complerta
### Fin de tu código

#print('Dimensiones de X_train:', X_train.shape)


#print('Dimensiones de y_train:', len(y_train))
#print('Dimensiones de X_test:', X_test.shape)

2
#print('Dimensiones de y_test:', len(y_test))
# Completa

Pregunta: (0.5 puntos) Entrena un modelo SVM: * Compara el rendimiento de un kernel lineal,
un kernel polinomial de tercer grado y un kernel gausiano. * En todos los casos, aplica primero
estandarización de características, con la media y desviación estándar calculadas según el conjunto
de entrenamiento. * En todos los casos, ajusta el peso de las clases usando la opción que brinda
sklearn. * En todos los casos, usar C=1 y probability=True. * No aplicar aún búsqueda grid.
* Evaluar cada modelo indicando las siguientes métricas tanto para el conjunto de entrenamiento
como para el conjunto de pruebas: Exactitud, Precisión, Exhaustividad, Puntaje F1, y Área bajo
la curva ROC (AUC)

[ ]: #X_train.describe()

[ ]: #from sklearn.svm import SVC

[ ]: #model_1 = SVC(kernel='linear', C=1, probability=True)


#model_1.fit(X_train, y_train)

[ ]: from sklearn.metrics import recall_score, precision_score, f1_score,␣


,→roc_auc_score, plot_roc_curve, plot_confusion_matrix,␣

,→plot_precision_recall_curve

resultados = {}
# Código obtenido a utilizar
def save_and_show_resultados(descripcion, model, resultados, X_train, X_test,␣
,→y_train, y_test):

y_train_pred = model.predict(X_train)
y_train_pred_proba = model.predict_proba(X_train)[:,1]
y_test_pred = model.predict(X_test)
y_test_pred_proba = model.predict_proba(X_test)[:,1]

resultados.update( { descripcion: {
('Entrenamiento', 'Exactitud'): model.score(X_train, y_train),
('Entrenamiento', 'Precisión'): precision_score(y_train, y_train_pred,␣
,→zero_division=0),

('Entrenamiento', 'Exhaustividad'): recall_score(y_train, y_train_pred),


('Entrenamiento', 'F1'): f1_score(y_train, y_train_pred),
('Entrenamiento', 'AUC'): roc_auc_score(y_train, y_train_pred_proba),
('Pruebas', 'Exactitud'): model.score(X_test, y_test),
('Pruebas', 'Precisión'): precision_score(y_test, y_test_pred,␣
,→zero_division=0),

('Pruebas', 'Exhaustividad'): recall_score(y_test, y_test_pred),


('Pruebas', 'F1'): f1_score(y_test, y_test_pred),
('Pruebas', 'AUC'): roc_auc_score(y_test, y_test_pred_proba)
} } )
display(pd.DataFrame.from_dict(resultados, orient='index'))

3
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
fig.suptitle(f'{descripcion} (Conjunto de Pruebas)')
plot_confusion_matrix(model, X_test, y_test, ax=axes[0], values_format='d')
plot_roc_curve(model, X_test, y_test, ax=axes[1], name=descripcion)
plot_precision_recall_curve(model, X_test, y_test, ax=axes[2],␣
,→name=descripcion)

[ ]: #save_and_show_resultados('SVM Lineal', model_1, resultados, X_train, X_test,␣


,→y_train, y_test)

[ ]: #model_2 = SVC(kernel='rbf', C=1, gamma=50, probability=True)


# Completa

[ ]: #save_and_show_resultados('SVM Gausiano', model_2, resultados, X_train, X_test,␣


,→y_train, y_test)

[ ]: # model_3 = SVC(kernel='poly', C=1, degree=3, probability=True)


# Completa

[ ]: #save_and_show_resultados('SVM Polinómico de grado 3', model_3, resultados,␣


,→X_train, X_test, y_train, y_test)

Pregunta: (1 punto) Utiliza la clase GridSearchCV de sklearn para ajustar el SVM de kernel
gaussiano: * Aplica primero estandarización de características, con la media y desviación estándar
calculadas según el conjunto de entrenamiento. * En todos los casos, ajusta el peso de las clases
usando la opción que brinda sklearn. * Explora con valores de C: [0.1, 1, 10] y gamma: [0.1,
1, 10] * Indicar cuáles fueron los mejores valores obtenidos para C y para gamma. * Evaluar cada
modelo indicando las siguientes métricas: Exactitud, Precisión, Exhaustividad, Puntaje F1, y Área
bajo la curva ROC (AUC)

[ ]: #train_tune = dataset_normalizado
#target = 'target'
#predictors = [x for x in train_tune.columns if x not in [target]]

#param_test1 = {
# ...
# ...
#}
# Completa
# ...
# Mejores valores:
# Completa

[ ]: #model_s = SVC(kernel='rbf', C=0.1, gamma=0.1, probability=True)


#model_s.fit(X_train, y_train)

4
[ ]: #save_and_show_resultados('SVM Gausiano con GridSearchCV', model_s, resultados,␣
,→X_train, X_test, y_train, y_test)

Pregunta: (0.5 puntos) Entrena un modelo de clasificación K-NN:


• Aplica primero estandarización de características, con la media y desviación estándar calcu-
ladas según el conjunto de entrenamiento.
• En todos los casos, ajusta el peso de las clases usando la opción que brinda sklearn.
• Utiliza la clase GridSearchCV de sklearn para determinar el mejor valor de k: [3, 5, 7]
• Indicar cuál fue el mejor valor de k obtenido.
• Evaluar el modelo indicando las siguientes métricas tanto para el conjunto de entrenamiento
como para el conjunto de pruebas: Exactitud, Precisión, Exhaustividad, Puntaje F1, y Área
bajo la curva ROC (AUC)

[ ]: #from sklearn.neighbors import KNeighborsClassifier

[ ]: #param_test2 = {
# 'n_neighbors':[3,5,7]
#}
# Completa
# Mejor K:

[ ]: # Usa el mejor K
# Completa

[ ]: #save_and_show_resultados('KNN con 7 vecinos', knn, resultados, X_train,␣


,→X_test, y_train, y_test)

Pregunta: (1 punto) Entrena un modelo de tu elección, que esté basado en árboles de decisión,
bagging o boosting: * Evalúalo del mismo modo que los anteriores. * Haz un gráfico de barras con
las características más importantes reportadas por el algoritmo.
[ ]: ## Tu código

Sugerencia: Para que esta pregunta sea evaluada correctamente, debes comentar y discutir los
resultados obtenidos con los modelos entrenados:
• Comparar los resultados
• Identificar casos de overfitting.
• Elegir al mejor modelo según la experimentación.
• Indicar qué pasos seguiría para mejorar los resultados.

0.1.3 Pregunta 2 (4 puntos)


Recuerda: que para que la pregunte puntue debes responder todos los ítems.
Responde las siguientes preguntas:
1. Supongamos que un modelo de IA tiene N neuronas y M parámetros entrenables. Para
un minibatch de muestras B, calcula los requisitos de memoria para el entrenamiento y la

5
inferencia.
2. Indica las ventajas de los grafos de cálculo dinámico sobre los grafos de cálculo estático.
3. Supongamos que estás tratando de navegar por un mundo lleno de peligros desconocidos como
abismos, fuego, atolladeros, grandes arañas, etc., en busca de tesoros, y usa dos algoritmos A
y B para encontrar la política óptima. El algoritmo A devuelve una política casi óptima, que
parece mantenerlo más seguro al alejarlo de los peligros. Dado que un algoritmo es Sarsa y
el otro es Q-learning, especifique cuál de A y B es Q-learning.
4. Explica la equivalencia entre el algoritmo de regresión lineal y el aprendizaje de una neurona
lineal.
[ ]: ## Tus respuestas

0.1.4 Pregunta 3 (5 puntos)

[ ]: import matplotlib.pyplot as plt


import numpy as np

def dosEspirales(N):
np.random.seed(1)
n = np.sqrt(np.random.rand(N,1)) * 780 * (2*np.pi)/360
x = -np.cos(n)*n
y = np.sin(n)*n
return (np.vstack((np.hstack((x,y)),np.hstack((-x,-y)))),
np.hstack((np.ones(N)*-1,np.ones(N))))

X, y = dosEspirales(300)
fig = plt.figure(figsize=(6,6))

plt.plot(X[1,0],X[1,1],'+', color='#648fff', label='Clase positiva')


plt.plot(X[2,1],X[2,1],'_', color='#fe6100', label='Clase negativa')

for i in range(len(y)):
x1 = X[i,0]
x2 = X[i,1]
if (y[i] == 1):
plt.plot(x1,x2,'+', color='#648fff')
else:
plt.plot(x1,x2,'k_', color='#fe6100')
plt.xlabel('$x_1$')
plt.ylabel('$x_2$')
plt.legend()
plt.title('Datos de dos espirales')
plt.axis()
plt.show()

Verificación de pasos

6
[ ]: print(X[0])
yv = np.zeros(X.shape)
yv[y==1,0]=1
yv[y==-1,1]=1
print(yv[0])
np.random.seed(1)
w1 = 2.0*np.random.random((2, 3))-1.0
w2 = 2.0*np.random.random((3, 2))-1.0
print(w1)
print(w2)

print(X[0].dot(w1))
print(1.0/(1.0+np.exp(-X[0].dot(w1))))

z1 = X[0].dot(w1)
o1 = 1.0/(1.0+np.exp(-X[0].dot(w1)))
print(o1.dot(w2))
o2 = 1.0/(1.0+np.exp(-o1.dot(w2)))
print(o2)

print(- ([1,0] - o2))


print(o1.dot(w2) * (1- o1.dot(w2)))

a=np.array([[-0.52476045, 0.50415211]])
b=np.array([[-0.10894822, 0.01633295]])
c=np.array([[3.79325728e-02, 3.64802735e-01, 1.20447478e-05]])
print(a*b)
np.set_printoptions(suppress=True)
print(c.T.dot(a*b))

print(w2 - (0.001 * (c.T.dot(a*b))))

print((a*b).dot(w2.T))

print(o1*(1-z1))

p=X[0].reshape((1,2))
q=(a*b).dot(w2.T)
r=o1*(1-z1)
print(p.T*(q*r))

print(w1-(0.001*(p.T*(q*r))))
np.set_printoptions(suppress=False)

from sklearn.preprocessing import StandardScaler


X_std = X

7
X = StandardScaler().fit_transform(X_std)

Realicemos la retropropagación sobre el conjunto de los datos.


1. Realizaremos un paso inicial en el que inicializamos aleatoriamente los pesos de la red.
2. El siguiente paso sería el forward. En este paso, la entrada„ se presenta en la capa de entrada
y se propaga hacia adelante en la red hasta que observamos el vector resultante en la capa
de salida.
3. Cálculo de la pérdida total.
4. Es importante pensar en esta pérdida en términos de su derivada, ya que queremos ajustar
los pesos de la red en términos del gradiente dado por esta función de pérdida. Por lo tanto,
podemos hacer pequeños cambios que no afectan en absoluto el resultado general del proceso
de aprendizaje, pero pueden resultar en buenas derivadas. Hay que utilizar regularización.
5. El siguiente paso es realizar la retropropagación. El objetivo es ajustar los pesos en proporción
a la pérdida y en una dirección que la reduzca. Se debe comenzar resolviendo la primera
derivada parcial. Podemos hacerlo utilizando la conocida regla de la cadena que nos permite
descomponer la derivada principal en piezas que representan el mismo proceso.
[ ]: def sigmoid(z, grad=False):
if grad:
return z*(1.0-z)
return 1.0/(1.0+np.exp(-z))

def tanh(z, grad=True):


if grad:
return (1.0-z*z)
return (1.0-np.exp(-z))/(1.0+np.exp(-z))

def inferencia(data, pesos):


o1 = sigmoid(np.matmul(data, pesos[0]))
logits = np.matmul(o1, pesos[1])
probs = np.exp(logits)/np.sum(np.exp(logits), axis=1, keepdims=True)
return np.argmax(probs, axis=1)

N = 50

dim_entrada = int(X.shape[1])
dim_oculta = 3
dim_salida = 2
num_epocas = 100000
tasa_aprendizaje= 1e-3
reg_coeff = 1e-3
perdidas = []
exactitudes=[]

8
# Inicializacion:
np.random.seed(1)
w1 = 2.0*np.random.random((dim_entrada,dim_oculta))-1.0
w2 = 2.0*np.random.random((dim_oculta, dim_salida))-1.0

#Calibracion
w1 /= np.sqrt(dim_entrada)
w2 /= np.sqrt(dim_oculta)
for i in range(num_epocas):
index = np.arange(X.shape[0])
np.random.shuffle(index)
index = index[:N]

# -----------------------------------------------------------------------------
# Implementación del forward
# Completa

#-----------------------------------------------------------------------------
# Definicion de la funcion de perdida: MSE + regularizacion ridge
# ...

#-----------------------------------------------------------------------------
# Implementación del backward

#....

## Actualizacion de pesos

#...

Para verificar el correcto funcionamiento debes utilizar. No te olvides de explicar el resultado.


[ ]: #print(o2[0], yv[index][0])
#plt.hist(o2[:,0])

[ ]: #plt.figure()
#for k in range(len(perdidas)):
# if k%1000==0:
# plt.plot(losses[k][0], losses[k][1], 'k.')
#plt.show()

#plt.figure()
#for k in range(len(accuracies)):
# if k%1000==0:
# plt.plot(accuracies[k][0], accuracies[k][1], 'k.')
#plt.show()

9
[ ]: def probas1(data, pesos):
o1 = sigmoid(np.matmul(data, pesos[0]))
logits = np.matmul(o1, pesos[1])
return logits

y_pred = inferencia(X, [w1, w2])


y_actual = np.argmax(yv, axis=1)

x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5


y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
np.arange(y_min, y_max, 0.02))

Z = probas1(np.c_[xx.ravel(), yy.ravel()], [w1, w2])[:, 1]


Z = Z.reshape(xx.shape)
cm = plt.cm.bwr

fig = plt.figure(figsize=(6,6))

plt.contourf(xx, yy, Z, cmap=cm, alpha=.25)

plt.plot(X[1,0],X[1,1],'+', color='#648fff', label='Clase positiva')


plt.plot(X[2,1],X[2,1],'_', color='#fe6100', label='Clase negativa')

for i in range(len(y)):
x1 = X[i,0]
x2 = X[i,1]
if y[i]==1:
if (y_pred[i] == 0):
plt.plot(x1,x2,'+', color='#648fff')
else:
plt.plot(x1,x2,'k.', alpha=0.25)
else:
if (y_pred[i] == 1):
plt.plot(x1,x2,'_', color='#fe6100')
else:
plt.plot(x1,x2,'k.', alpha=0.25)

exactitud = np.sum(np.equal(y_pred,y_actual))/len(y_actual)

plt.axis()
plt.xlim(min(X[:,0])-0.1, max(X[:,0])+0.1)
plt.ylim(min(X[:,1])-0.1, max(X[:,1])+0.1)
plt.xlabel('$x_1$')
plt.ylabel('$x_2$')
plt.legend()

10
plt.title('MLP entrenado en un conjunto de datos en espiral. Exactitud:␣
,→'+str(exactitud))

plt.show()

El gráfico resultante, no es la respuesta pedida, solo es una forma de evaluación. Cuando completes
el código, el gráfico debe ser parecido pero no igual y debes explicar los resultados.
[ ]: ## Tu respuesta

0.1.5 Pregunta 4 ( 6 puntos)


1. Para la clasificación binaria, ¿cómo se expresa el voto mayoritario para la decisión del clasi-
ficador combinado en el boosting?
2. Dados los siguientes puntos: 2, 4, 10, 12, 3, 20, 30, 11, 25. Suponga que k = 3 y que
elegimos al azar las medias iniciales µ1 = 2, µ2 = 4 y µ3 = 6. Muestra los clusters obtenidos
mediante el algoritmo de K-medias después de una iteración y muestra las nuevas medias
para la siguiente iteración. (No usar código)
3. Recuerda que ¬x es la negación de la variable booleana x.
• Muestra que un solo perceptrón puede aprender la función booleana y = x1 ∧ ¬x2 , con
x1 , x2 ∈ {0, 1}.
• La misma pregunta anterior para la función booleana y = x1 ∨ ¬x2 , con x1 , x2 ∈ {0, 1}.
• Muestra que un perceptrón con una entrada booleana, x, puede aprender la función de ne-
gación y = ¬x. ¿Qué pasa con una neurona lineal (su función de activación ϕ(x) = x)?.
• Muestra que un perceptrón con tres entradas booleanas, x1 , x2 , x3 , puede aprender x1 ∧x2 ∧x3 .
¿Qué pasa con x1 ∨ x2 ∨ x3 ?.
[ ]: ## Tus respuestas

[ ]:

11

También podría gustarte