Clasificación Inteligente con Computer Vision
Conjunto de Datos de Fríjoles Secos
En esta investigación se utilizaron siete tipos diferentes de fríjoles secos, considerando características como forma, tipo y estructura según el mercado. Se desarrolló un sistema de visión por computador para distinguir siete variedades registradas de fríjoles con características similares, con el fin de lograr una clasificación uniforme de semillas. Para el modelo de clasificación, se capturaron imágenes de 13.611 granos de 7 tipos distintos de fríjoles registrados, utilizando una cámara de alta resolución. Estas imágenes fueron sometidas a procesos de segmentación y extracción de características, obteniendo un total de 16 atributos: 12 dimensiones y 4 formas.
- Área (A): El área de una zona de fríjol y el número de píxeles dentro de sus límites.
- Perímetro (P): Circunferencia del fríjol, definida como la longitud de su borde.
- Longitud del eje mayor (L): Distancia entre los extremos de la línea más larga que puede trazarse en el fríjol.
- Longitud del eje menor (l): Línea más larga que puede trazarse perpendicular al eje mayor.
- Relación de aspecto (K): Relación entre el eje mayor y el menor.
- Excentricidad (Ec): Excentricidad de la elipse con los mismos momentos que la región del fríjol.
- Área convexa (C): Píxeles en el polígono convexo más pequeño que contiene el fríjol.
- Diámetro equivalente (Ed): Diámetro de un círculo con la misma área que el fríjol.
- Extensión (Ex): Relación entre los píxeles del cuadro delimitador y el área del fríjol.
- Solidez (S): Relación entre los píxeles del casco convexo y los del fríjol (también llamada convexidad).
- Redondez (R): Calculada como (4πA) / (P^2).
- Compacidad (CO): Medida de redondez: Ed / L.
- Factor de forma 1 (SF1)
- Factor de forma 2 (SF2)
- Factor de forma 3 (SF3)
- Factor de forma 4 (SF4)
1# Librerías necesarias
2import numpy as np
3import pandas as pd
4import matplotlib.pyplot as plt
5import seaborn as sns
6from sklearn.linear_model import LogisticRegression
7from sklearn.model_selection import train_test_split
8from sklearn.metrics import confusion_matrix, accuracy_score, ConfusionMatrixDisplay
9from sklearn.preprocessing import MinMaxScaler
10from sklearn import metrics
11from sklearn.preprocessing import StandardScaler
12from sklearn.metrics import classification_report
13from imblearn.under_sampling import RandomUnderSampler # Hacer undersampling
14
15sns.set() # Estilo visual para seaborn
16
17# Montar Google Drive
18from google.colab import drive
19drive.mount('/content/drive')
20
21# Ruta del archivo CSV
22ruta_archivo = '/content/drive/My Drive/db/Dry_Bean.csv'
23
24# Cargar el archivo CSV
25df = pd.read_csv(ruta_archivo)
1# Mostramos la información del dataset
2df.info()
3
4# Output:
5# <class 'pandas.core.frame.DataFrame'>
6# RangeIndex: 13611 entries, 0 to 13610
7# Data columns (total 17 columns):
8# # Column Non-Null Count Dtype
9# --- ------ -------------- -----
10# 0 Area 13611 non-null int64
11# 1 Perimeter 13611 non-null float64
12# 2 MajorAxisLength 13611 non-null float64
13# 3 MinorAxisLength 13611 non-null float64
14# 4 AspectRation 13611 non-null float64
15# 5 Eccentricity 13611 non-null float64
16# 6 ConvexArea 13611 non-null int64
17# 7 EquivDiameter 13611 non-null float64
18# 8 Extent 13611 non-null float64
19# 9 Solidity 13611 non-null float64
20# 10 roundness 13611 non-null float64
21# 11 Compactness 13611 non-null float64
22# 12 ShapeFactor1 13611 non-null float64
23# 13 ShapeFactor2 13611 non-null float64
24# 14 ShapeFactor3 13611 non-null float64
25# 15 ShapeFactor4 13611 non-null float64
26# 16 Class 13611 non-null object
27# dtypes: float64(14), int64(2), object(1)
28# memory usage: 1.8+ MB
1# Vemos la distribución de las categorías
2sns.countplot(x='Class', data=df, hue='Class')
3plt.xticks(rotation=45)
4plt.show()
5
6# Output: Muestra un gráfico de barras donde cada barra representa la cantidad de ejemplos por clase en el dataset.
7# Las clases están en el eje X, la cantidad de ejemplos en el eje Y. Cada barra tiene un color distinto gracias al 'hue'.
1# Hacen un undersampling - o sea balanceo de categorías en la variable dependiente
2# Undersampling => disminuir todas las categorías a la mínima, para un mejor equilibrio de categorías
3from imblearn.under_sampling import RandomUnderSampler
4
5undersampling = RandomUnderSampler(random_state=42)
6
7x = df.drop('Class', axis=1)
8y = df.Class
9
10# Hacemos el undersampling de las categorías
11x_under, y_under = undersampling.fit_resample(x, y)
12
13# Vemos la distribución de las categorías balanceadas
14y_undeExample = pd.DataFrame(y_under, columns=['Class'])
15sns.countplot(x='Class', data=y_undeExample, hue='Class')
16plt.xticks(rotation=45)
17plt.show()
18
19# Output: Muestra un gráfico de barras con todas las clases ahora equilibradas (todas con igual número de muestras).
1# Reconocimiento de la data perdida
2print('Original => ', df.shape, ' Undersampling => ', x_under.shape)
3# Output:
4# Original => (13543, 17) Undersampling => (3654, 16)
5
6# Pasamos nuestra variable dependiente categórica a numérica
7y_under.replace(['BARBUNYA', 'BOMBAY', 'CALI', 'DERMASON', 'HOROZ', 'SEKER', 'SIRA'],
8 [1, 2, 3, 4, 5, 6, 7], inplace=True)
9
10# Vemos la nueva clasificación
11print(list(np.unique(y_under)))
12# Output:
13# [1, 2, 3, 4, 5, 6, 7]
14
15# Análisis exploratorio
16
17# Unimos de nuevo los datos
18df_data = x_under.copy()
19df_data['Class'] = y_under
20
21# Sacamos la correlación de las variables
22corr = df_data.corr()
23
24# Correlación de las variables
25plt.figure(figsize=(15, 10))
26sns.heatmap(corr, annot=True)
27plt.show()
28
29# Output: Se muestra un mapa de calor (heatmap) con los coeficientes de correlación entre todas las variables, incluyendo la variable 'Class'.
1# Eliminamos las variables que están altamente correlacionadas para eliminar la multicolinealidad y evitar el overfitting
2x_under.drop(['ConvexArea', 'EquivDiameter', 'Class'], axis=1, inplace=True)
3
4# Visualización de las relaciones entre variables con respecto a la clase
5sns.pairplot(df_data, hue='Class')
6plt.show()
7
8# Output: Se genera una matriz de gráficos de dispersión (pairplot) donde se observan las relaciones entre pares de variables diferenciadas por clase. Esto ayuda a visualizar cómo se agrupan las categorías y si existe algún patrón que el modelo pueda aprender.
1# Separación de los datos en entrenamiento y prueba
2x_train, x_test, y_train, y_test = train_test_split(x_under, y_under, test_size=0.2, random_state=42, shuffle=True)
3
4# Escalado de variables
5scaler = StandardScaler()
6x_train = scaler.fit_transform(x_train)
7x_test = scaler.transform(x_test)
8
9# Definición del modelo de Regresión Logística
10def modelo(C, solver_, multiclass_):
11 logisticRegresionModel = LogisticRegression(random_state=42, solver=solver_, multi_class=multiclass_, n_jobs=-1, C=C)
12 return logisticRegresionModel
13
14# Asignamos y entrenamos el modelo
15modelo2 = modelo(1, 'saga', 'multinomial')
16modelo2.fit(x_train, y_train)
17
18# Predicciones sobre el conjunto de prueba
19prediction = modelo2.predict(x_test)
20
21# Matriz de confusión
22cm = confusion_matrix(y_test, prediction)
23print(cm)
24
25# Output:
26# [[119 0 5 0 1 0 3]
27# [ 0 98 0 0 0 0 0]
28# [ 5 0 97 0 0 0 1]
29# [ 0 0 0 90 0 5 10]
30# [ 0 0 4 1 91 0 0]
31# [ 3 0 0 0 0 84 4]
32# [ 0 0 1 6 6 0 97]]
1# Observamos el accuracy del modelo
2accuracy = accuracy_score(y_test, prediction)
3print(accuracy.round(3) * 100, '%')
4
5# Output:
6# 92.5 %
1# Iteramos por cada uno de los solvers y los métodos para ver cuál es el mejor
2multiclass = ['ovr','multinomial']
3solver_list = ['liblinear', 'newton-cg', 'lbfgs', 'sag', 'saga']
4scores = []
5params = []
6
7for i in multiclass:
8 for j in solver_list:
9 try:
10 model = modelo(1, j, i)
11 model.fit(x_train, y_train)
12 predictions = model.predict(x_test)
13 params.append(i + '-' + j)
14 accuraccy = accuracy_score(y_test, predictions)
15 scores.append(accuraccy)
16 except:
17 None
18
19# Visualización de los resultados
20fig = plt.figure(figsize=(10,10))
21sns.barplot(x=params, y=scores, hue=params).set_title('Beans Accuracy')
22plt.xticks(rotation=90)
23plt.show()
24
25# Output: Muestra un gráfico de barras comparando el accuracy de cada combinación solver/multiclass
1# Reasignamos parámetros
2# Asignamos el modelo
3modelo3 = modelo(1, 'newton-cg', 'multinomial')
4modelo3.fit(x_train, y_train)
5prediction4 = modelo3.predict(x_test)
6
7# Matriz de confusión
8print(confusion_matrix(y_test, prediction4))
9# Output:
10# [[119 0 5 0 1 0 3]
11# [ 0 98 0 0 0 0 0]
12# [ 5 0 97 0 0 0 1]
13# [ 0 0 0 90 0 5 10]
14# [ 0 0 4 1 91 0 0]
15# [ 3 0 0 0 0 84 4]
16# [ 0 0 1 6 6 0 97]]
17
18# Accuracy
19print('accuracy =>', accuracy_score(y_test, prediction4).round(3) * 100, '%')
20# Output:
21# accuracy => 92.5 %
Comentarios
Cargando comentarios...