-
Notifications
You must be signed in to change notification settings - Fork 1
/
utils.py
257 lines (198 loc) · 8.49 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
import os
import numpy as np
import matplotlib.pyplot as plt
import itertools
from sklearn.metrics import confusion_matrix
import random
import matplotlib.image as mpimg
def plot_decision_boundary(model, X, y):
"""
Imprime la toma de decisión del modelo
Esta función ha sido adaptada de
1. CS231n - https://cs231n.github.io/neural-networks-case-study/
2. Made with ML basics - https://github.com/GokuMohandas/MadeWithML/blob/main/notebooks/08_Neural_Networks.ipynb
"""
# Define los ejes de decisión del plot y crea un meshgrid (un meshgrid recibe las matrices de coordenadas de los vectores de coordenadas)
x_min, x_max = np.array(X).min() - 0.1, 1
y_min, y_max = 0, np.array(X).max() + 0.1
xx, yy = np.meshgrid(np.linspace(x_min, x_max, 100), # linspace regresa un espacio con numeros separados
np.linspace(y_min, y_max, 100))
# Crea los valores de X (Vamos a predecir sobre estos)
x_in = np.c_[xx.ravel(), yy.ravel()] # stacking de arreglos de 2D https://numpy.org/devdocs/reference/generated/numpy.c_.html
# Crea predicciones
y_pred = model.predict(x_in)
# Revisa si es un problema de multiclase
if model.output_shape[-1] > 1: # revisa si la dimensión final del output del modelo. is es mas grande a 1, es multiclase
print("doing multiclass classification...")
# Realizamos un reshape de las predicciones para poder graficarlas
y_pred = np.argmax(y_pred, axis=1).reshape(xx.shape)
else:
print("doing binary classifcation...")
y_pred = np.round(np.max(y_pred, axis=1)).reshape(xx.shape)
# Imprime boundary
plt.contourf(xx, yy, y_pred, cmap=plt.cm.RdYlBu, alpha=0.7)
plt.scatter(np.array(X)[:, 0], np.array(X)[:, 1], c=y, s=40, cmap=plt.cm.RdYlBu)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
def plot_boundaries(model, X_train, y_train, X_test, y_test):
plt.figure(figsize=(12, 6)) # establece size de figura
plt.subplot(1, 2, 1) # subplot 1 (en set de train)
plt.title("Train")
plot_decision_boundary(model, X=X_train, y=y_train)
plt.subplot(1, 2, 2) # subplot 2 (en set de test)
plt.title("Test") # titulo
plot_decision_boundary(model, X=X_test, y=y_test)
plt.show()
def plot_decision_boundary_circles(model, X, y):
"""
Imprime la toma de decisión del modelo
Esta función ha sido adaptada de
1. CS231n - https://cs231n.github.io/neural-networks-case-study/
2. Made with ML basics - https://github.com/GokuMohandas/MadeWithML/blob/main/notebooks/08_Neural_Networks.ipynb
"""
# Define los ejes de decisión del plot y crea un meshgrid (un meshgrid recibe las matrices de coordenadas de los vectores de coordenadas)
x_min, x_max = X[:, 0].min() - 0.1, X[:, 0].max() + 0.1
y_min, y_max = X[:, 1].min() - 0.1, X[:, 1].max() + 0.1
xx, yy = np.meshgrid(np.linspace(x_min, x_max, 100),
np.linspace(y_min, y_max, 100))
# Crea los valores de X (Vamos a predecir sobre estos)
x_in = np.c_[xx.ravel(), yy.ravel()] # revisa si la dimensión final del output del modelo. is es mas grande a 1, es multiclase
# Realizamos un reshape de las predicciones para poder graficarlas
y_pred = model.predict(x_in)
# Revisa si hay problemas de multiclase
if model.output_shape[-1] > 1: # revisa si la dimensión final del output del modelo. is es mas grande a 1, es multiclase
print("doing multiclass classification...")
# Reshape
y_pred = np.argmax(y_pred, axis=1).reshape(xx.shape)
else:
print("doing binary classifcation...")
y_pred = np.round(np.max(y_pred, axis=1)).reshape(xx.shape)
# Imprime boundary
plt.contourf(xx, yy, y_pred, cmap=plt.cm.RdYlBu, alpha=0.7)
plt.scatter(X[:, 0], X[:, 1], c=y, s=40, cmap=plt.cm.RdYlBu)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
def plot_boundaries_circles(model, X_train, y_train, X_test, y_test):
plt.figure(figsize=(12, 6)) # establece size de figura
plt.subplot(1, 2, 1) # subplot 1 (en set de train)
plt.title("Train")
plot_decision_boundary_circles(model, X=X_train, y=y_train)
plt.subplot(1, 2, 2) # subplot 2 (en set de test)
plt.title("Test") # titulo
plot_decision_boundary_circles(model, X=X_test, y=y_test)
plt.show()
def plot_loss_curves(history):
"""
Regresa plot de cada una de las curvas de pérdida
"""
loss = history.history['loss']
val_loss = history.history['val_loss']
accuracy = history.history['accuracy']
val_accuracy = history.history['val_accuracy']
epochs = range(len(history.history['loss']))
# Pérdida
plt.plot(epochs, loss, label='training_loss')
plt.plot(epochs, val_loss, label='val_loss')
plt.title('Loss')
plt.xlabel('Epochs')
plt.legend()
# Accuracy
plt.figure()
plt.plot(epochs, accuracy, label='training_accuracy')
plt.plot(epochs, val_accuracy, label='val_accuracy')
plt.title('Accuracy')
plt.xlabel('Epochs')
plt.legend();
def make_confusion_matrix(y_true, y_pred, classes=None, figsize=(10, 10), text_size=15):
"""
Crea una matriz de confusion comparando las predicciones y las y_true
Si el argumento de clases se ha ocupado, la matriz de confusión se etiquetara, sino,
se devolverán n numeros correspondientes a n clases
Args:
y_true: Etiquetas reales
y_pred: Arreglo de etiquetas de predicción (tienen que ser del mismo shape que y_true)
classes: Arreglo con nombre de clases
figsize: Tamaño de la figura
text_size: Tamaó de texto
Returns:
Plot de matriz de confusión
"""
# Crea matriz de confusión
cm = confusion_matrix(y_true, y_pred)
cm_norm = cm.astype("float") / cm.sum(axis=1)[:, np.newaxis] # normalize it
n_classes = cm.shape[0] # find the number of classes we're dealing with
# Plot
fig, ax = plt.subplots(figsize=figsize)
cax = ax.matshow(cm, cmap=plt.cm.Blues)
fig.colorbar(cax)
# Si existe lista de clases
if classes:
labels = classes
else:
labels = np.arange(cm.shape[0])
# Etiquetas de los ejes
ax.set(title="Confusion Matrix",
xlabel="Predicted label",
ylabel="True label",
xticks=np.arange(n_classes), # Creación de ejes
yticks=np.arange(n_classes),
xticklabels=labels,
yticklabels=labels)
# Etiquetas del eje
ax.xaxis.set_label_position("bottom")
ax.xaxis.tick_bottom()
# Umbral de colores diferentes
threshold = (cm.max() + cm.min()) / 2.
# Texto de cada celda
for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
plt.text(j, i, f"{cm[i, j]} ({cm_norm[i, j]*100:.1f}%)",
horizontalalignment="center",
color="white" if cm[i, j] > threshold else "black",
size=text_size)
def view_random_image(target_dir, target_class):
# Establece el folder objetivo
target_folder = target_dir+target_class
# Obten una muestra aleatoria del dataset
random_image = random.sample(os.listdir(target_folder), 1)
# Lee la imagen y haz un plot usando matplotlib
img = mpimg.imread(target_folder + "/" + random_image[0])
plt.imshow(img) # muestra imagen
plt.title(target_class) # clase como titulo
plt.axis("off");
print(f"Image shape: {img.shape}") # Imprime shape de la imagen
return img
def compare_historys(original_history, new_history, initial_epochs=5):
"""
Compara la historia de dos modelos
"""
# Obtiene las métricas originales
acc = original_history.history["accuracy"]
loss = original_history.history["loss"]
print(len(acc))
val_acc = original_history.history["val_accuracy"]
val_loss = original_history.history["val_loss"]
# Combina la historia original con la nueva
total_acc = acc + new_history.history["accuracy"]
total_loss = loss + new_history.history["loss"]
total_val_acc = val_acc + new_history.history["val_accuracy"]
total_val_loss = val_loss + new_history.history["val_loss"]
print(len(total_acc))
print(total_acc)
# Crea plots
plt.figure(figsize=(8, 8))
plt.subplot(2, 1, 1)
plt.plot(total_acc, label='Training Accuracy')
plt.plot(total_val_acc, label='Validation Accuracy')
plt.plot([initial_epochs-1, initial_epochs-1],
plt.ylim(), label='Start Fine Tuning')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
plt.subplot(2, 1, 2)
plt.plot(total_loss, label='Training Loss')
plt.plot(total_val_loss, label='Validation Loss')
plt.plot([initial_epochs-1, initial_epochs-1],
plt.ylim(), label='Start Fine Tuning')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.xlabel('epoch')
plt.show()