Clasificación de Imágenes usando SVM: Un Enfoque Eficiente
Cuando trabajamos con clasificación de imágenes, a menudo recurrimos a redes neuronales profundas (DNN) o convolucionales (CNN). Sin embargo, estos modelos pueden resultar complicados, lentos y difíciles de entrenar, especialmente cuando no contamos con datasets grandes. En este artículo, exploraremos una alternativa más sencilla pero potente: Support Vector Machines (SVM), comparando el rendimiento de dos tipos de kernels: lineal y RBF.
¿Por qué usar SVM?
Las SVM son ideales para datasets de tamaño moderado, ya que su enfoque se basa en encontrar el hiperplano que separa de manera óptima las clases en el espacio de características. Este método es rápido de entrenar en comparación con una red neuronal, y puede ofrecer muy buenos resultados sin necesidad de configuraciones complicadas.
Paso 1: Configura tu entorno de trabajo
Si ya has seguido los pasos del artículo pasado para configurar tu entorno con Anaconda y Spyder, simplemente añade los paquetes adicionales que usaremos:
#Si ya tienes el entorno y las librerías, salta este paso
conda activate vision_artificial
pip install opencv-contrib-python
pip install scikit-learn
pip install scikit-image
pip install numpy
pip install matplotlib
pip install seaborn
Esto instalará las herramientas necesarias para la clasificación de imágenes.
Paso 2: Carga y preprocesa las imágenes
Para simplificar, usaremos el dataset de dígitos proporcionado por scikit-learn
. Este dataset contiene imágenes en escala de grises de 8×8 píxeles, lo que nos permitirá enfocarnos en cómo funciona una SVM en tareas de clasificación de imágenes.
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import classification_report, confusion_matrix
import matplotlib.pyplot as plt
import seaborn as sns
# Cargar el dataset de dígitos
digits = datasets.load_digits()
# Dividir datos en características (X) y etiquetas (y)
X = digits.data
y = digits.target
# Dividir en conjunto de entrenamiento y prueba
XTrain, XTest, yTrain, yTest = train_test_split(X, y, test_size=0.3, random_state=42)
# Escalar los datos
scaler = StandardScaler()
XTrain = scaler.fit_transform(XTrain)
XTest = scaler.transform(XTest)
Paso 3: Entrenar el modelo SVM con kernel lineal
A continuación, entrenaremos la SVM utilizando un kernel lineal, que es el más simple de todos y suficiente para este ejemplo.
# Inicializar el clasificador SVM con kernel lineal
svmModelLinear = SVC(kernel='linear')
# Entrenar el modelo
svmModelLinear.fit(XTrain, yTrain)
# Predecir en el conjunto de prueba
yPredLinear = svmModelLinear.predict(XTest)
Paso 4: Evaluar el rendimiento del modelo lineal
Evaluamos el rendimiento del modelo con el kernel lineal.
# Evaluar el rendimiento del modelo lineal
print("Resultados con Kernel Lineal:")
print(classification_report(yTest, yPredLinear))
# Matriz de confusión para el modelo lineal
confMatrixLinear = confusion_matrix(yTest, yPredLinear)
plt.figure(figsize=(8, 6))
sns.heatmap(confMatrixLinear, annot=True, fmt='d', cmap='Blues', xticklabels=digits.target_names, yticklabels=digits.target_names)
plt.title('Matriz de Confusión - Kernel Lineal')
plt.xlabel('Predicción')
plt.ylabel('Realidad')
plt.show()
# Visualizar algunas imágenes con las predicciones
plt.figure(figsize=(10, 4))
for index, (image, prediction) in enumerate(zip(XTest[0:4], yPredLinear[0:4])):
plt.subplot(1, 4, index + 1)
plt.imshow(image.reshape(8, 8), cmap=plt.cm.gray_r, interpolation='nearest')
plt.title(f'Predicción: {prediction}')
plt.show()
Clase | Precision | Recall | F1-Score | Support |
0 | 0.98 | 1.00 | 0.99 | 53 |
1 | 0.98 | 0.98 | 0.98 | 50 |
2 | 0.98 | 1.00 | 0.99 | 47 |
3 | 0.96 | 0.96 | 0.96 | 54 |
4 | 1.00 | 1.00 | 1.00 | 60 |
5 | 0.97 | 0.95 | 0.96 | 66 |
6 | 0.98 | 0.98 | 0.98 | 53 |
7 | 1.00 | 0.98 | 0.99 | 55 |
8 | 0.95 | 0.95 | 0.95 | 43 |
9 | 0.97 | 0.97 | 0.97 | 59 |
Accuracy | 0.98 | 540 | ||
Macro avg | 0.98 | 0.98 | 0.98 | 540 |
Weighted avg | 0.98 | 0.98 | 0.98 | 540 |
Paso 5: Entrenar el modelo SVM con kernel RBF
Ahora entrenaremos la SVM usando un kernel RBF (Radial Basis Function), que es más flexible y puede capturar patrones no lineales en los datos.
# Inicializar el clasificador SVM con kernel RBF
svmModelRbf = SVC(kernel='rbf')
# Entrenar el modelo
svmModelRbf.fit(XTrain, yTrain)
# Predecir en el conjunto de prueba
yPredRbf = svmModelRbf.predict(XTest)
Paso 6: Evaluar el rendimiento del modelo RBF
Ahora evaluamos el rendimiento del modelo con el kernel RBF.
# Evaluar el rendimiento del modelo RBF
print("Resultados con Kernel RBF:")
print(classification_report(yTest, yPredRbf))
# Matriz de confusión para el modelo RBF
confMatrixRbf = confusion_matrix(yTest, yPredRbf)
plt.figure(figsize=(8, 6))
sns.heatmap(confMatrixRbf, annot=True, fmt='d', cmap='Blues', xticklabels=digits.target_names, yticklabels=digits.target_names)
plt.title('Matriz de Confusión - Kernel RBF')
plt.xlabel('Predicción')
plt.ylabel('Realidad')
plt.show()
# Visualizar algunas imágenes con las predicciones
plt.figure(figsize=(10, 4))
for index, (image, prediction) in enumerate(zip(XTest[0:4], yPredRbf[0:4])):
plt.subplot(1, 4, index + 1)
plt.imshow(image.reshape(8, 8), cmap=plt.cm.gray_r, interpolation='nearest')
plt.title(f'Predicción: {prediction}')
plt.show()
Clase | Precision | Recall | F1-Score | Support |
0 | 1.00 | 1.00 | 1.00 | 53 |
1 | 1.00 | 1.00 | 1.00 | 50 |
2 | 0.94 | 1.00 | 0.97 | 47 |
3 | 0.98 | 0.94 | 0.96 | 54 |
4 | 0.98 | 1.00 | 0.99 | 60 |
5 | 0.97 | 1.00 | 0.99 | 66 |
6 | 0.98 | 1.00 | 0.99 | 53 |
7 | 1.00 | 0.96 | 0.98 | 55 |
8 | 0.95 | 0.95 | 0.95 | 43 |
9 | 0.98 | 0.93 | 0.96 | 59 |
Accuracy | 0.98 | 540 | ||
Macro avg | 0.98 | 0.98 | 0.98 | 540 |
Weighted avg | 0.98 | 0.98 | 0.98 | 540 |
Comparación de Resultados
Clase | Precision Linear | Precision RBF | Recall Linear | Recall RBF | F1-Score Linear | F1-Score RBF | Support Linear | Support RBF |
0 | 0.98 | 1.00 | 1.0 | 1.00 | 0.99 | 1.00 | 53 | 53 |
1 | 0.98 | 1.00 | 0.98 | 1.00 | 0.98 | 1.00 | 50 | 50 |
2 | 0.98 | 0.94 | 1.00 | 1.00 | 0.99 | 0.97 | 47 | 47 |
3 | 0.96 | 0.98 | 0.96 | 0.94 | 0.96 | 0.96 | 54 | 54 |
4 | 1.00 | 0.98 | 1.00 | 1.00 | 1.00 | 0.99 | 60 | 60 |
5 | 0.97 | 0.97 | 0.95 | 1.00 | 0.96 | 0.99 | 66 | 66 |
6 | 0.98 | 0.98 | 0.98 | 1.00 | 0.98 | 0.99 | 53 | 53 |
7 | 1.00 | 1.00 | 0.98 | 0.96 | 0.99 | 0.98 | 55 | 55 |
8 | 0.95 | 0.95 | 0.95 | 0.95 | 0.95 | 0.95 | 43 | 43 |
9 | 0.97 | 0.98 | 0.97 | 0.93 | 0.97 | 0.96 | 59 | 59 |
Accuracy | 0.98 | 0.98 | 540 | 540 | ||||
Macro avg | 0.98 | 0.98 | 0.98 | 0.98 | 0.98 | 0.98 | 540 | 540 |
Weighted avg | 0.98 | 0.98 | 0.98 | 0.98 | 0.98 | 0.98 | 540 | 540 |
Al evaluar los resultados obtenidos con ambos kernels, podemos observar que, en general, ambos modelos ofrecen un rendimiento similar, pero con algunas diferencias en las métricas de precisión, recall y f1-score.
Resultados con Kernel Lineal
El modelo SVM con kernel lineal mostró un rendimiento notable, con las siguientes métricas:
- Precisión: La precisión general fue de 0.98, lo que indica que el 98% de las predicciones fueron correctas.
- Recall: La métrica de recall también fue excelente, con un valor de 0.98, lo que significa que el modelo identificó correctamente el 98% de las instancias relevantes en el conjunto de prueba.
- F1-Score: La media ponderada del f1-score fue de 0.98, reflejando un equilibrio adecuado entre precisión y recall.
Resultados con Kernel Lineal
El modelo SVM con kernel RBF también alcanzó un rendimiento excepcional, con métricas similares:
- Precisión: La precisión general fue también de 0.98.
- Recall: El recall promedio se mantuvo en 0.98, lo que indica una identificación eficaz de las instancias relevantes.
- F1-Score: La media ponderada del f1-score se situó en 0.98, similar al modelo lineal.
Conclusiones
Ambos modelos, tanto el de kernel lineal como el RBF, lograron una accuracy del 98% en el conjunto de prueba. Sin embargo, el modelo con kernel RBF mostró un ligero mejor rendimiento en más clases, lo que sugiere que puede ser más eficaz en capturar patrones complejos en los datos. En cambio, el kernel lineal es más sencillo y puede ser preferido en contextos donde se busque rapidez y simplicidad.
Esta comparación resalta la efectividad de las SVM en la clasificación de imágenes y su capacidad para ofrecer resultados competitivos con diferentes enfoques de kernel.
No te pierdas ningún post