Scikit-learné unha biblioteca de Python utilizada principalmente para a aprendizaxe automática (machine learning). É unha ferramenta poderosa que permite construír modelos de clasificación, regresión, agrupamento (clustering), entre outras tarefas.
Ademais, proporciona ferramentas para preprocesar datos e avaliar os modelos, o que a converte nunha elección ideal para aprender algoritmos de IA de forma sinxela e eficiente.
Actividades de aprendizaxe
Actividade 1: Clasificación
◦ Obxectivo: Aprender como funciona un modelo de clasificación de Machine Learning. ◦ Instrución: Usar Scikit-learn para clasificar mazás e laranxas.
Paso 1: Imos crear un modelo básico de clasificación para entender o concepto.
Código Python: Clasifica según o peso mazá/laranxa
# Importar o clasificador de árbore de decisión de Scikit-learn
from sklearn.tree import DecisionTreeClassifier
# Datos de exemplo: pesos de froitas en gramos
pesos_froitas = [[150], [170], [140], [130]] # Valores de peso das froitas
etiquetas_froitas = [0, 0, 1, 1] # 0: mazá, 1: laranxa (etiquetas que representan a clasificación)
# Crear o modelo de clasificador de árbore de decisión
# O modelo aprenderá a distinguir entre mazás e laranxas baseándose nos seus pesos
modelo_clasificador = DecisionTreeClassifier()
# Adestrar o modelo cos datos de pesos e etiquetas
# Aquí indicamos ao modelo que relacione os pesos cos tipos de froita
modelo_clasificador.fit(pesos_froitas, etiquetas_froitas)
# Realizar unha predición cun peso de 160 gramos
# O modelo utilizará a aprendizaxe previa para decidir se é unha mazá (0) ou unha laranxa (1)
predición = modelo_clasificador.predict([[160]])
# Mostrar o resultado da predición
# Saída: "É unha mazá (0) ou unha laranxa (1)?"
print("É unha mazá (0) ou unha laranxa (1)?", predición)
Propóñoche:
Cambiar e aumentar os datos
Crear unha nova clase/categoría pera(2)
Que o programa che pida o peso a predecir
Explicación do programa:
Estamos a importar o modelo chamado DecisionTreeClassifier da biblioteca Scikit-learn. Este modelo é un algoritmo de árbore de decisión que nos axudará a clasificar datos baseándonos en exemplos previos.
Definimos os datos de adestramento:
pesos_froitas: Unha lista cos pesos (en gramos) dalgunhas froitas.
etiquetas_froitas: Unha lista que indica que froita é cada peso. Usamos 0 para representar mazás e 1 para laranxas. É dicir:
Peso de 150 g → Mazá (0)
Peso de 170 g → Mazá (0)
Peso de 140 g → Laranxa (1)
Peso de 130 g → Laranxa (1)
Estes son os datos que usaremos para que o modelo "aprenda" a clasificar froitas segundo o seu peso.
Adestramosfit o modelo utilizando os datos que definimos nos pasos anteriores. Os pesos son as características que o modelo analizará. As etiquetas son as categorías ou clases correspondentes. O modelo agora aprende os patróns entre os pesos e as froitas para poder realizar clasificacións no futuro.
Usamos o modelo adestrado para realizar unha predición predict. Neste caso, queremos saber se un obxecto que pesa 160 gramos é unha mazá ou unha laranxa.
modelo.predict([[160]]) devolve 0 (mazá) ou 1 (laranxa), segundo o que o modelo aprendeu.
Finalmente, mostramos o resultado na consola. O modelo devolve un valor (0 ou 1), e imprimímolo xunto a un texto para que quede claro cal é a predición.
Resultado:Basándose no aprendido, predí que é unha mazá.
Paso 2: Aprendendo con máis datos... e graficando!
Creación propia. Resultado da clasificación(CC BY-SA)
E se queremos millorar o programa anterior, de xeito que che pregunte se acertou , e incorpore o dato de peso e etiqueta, ós datos iniciais e volva entrenarse aprendendo cos novos datos?
Ten unha entrada dinámica : O programa solicitache un peso , clasifica o dato, e mostra o resultado na consola. Despós pregúntache se acertou ou non para gardar correctamente ese novo dato coa etiqueta correcta, se mazá ou se laranxa.
Actualización do gráfico: Cada vez que se introduce un peso, o gráfico actualízase cos datos actuais e o novo peso clasificado.
Adestramento adicional: O novo peso e a súa etiqueta engádense ao conxunto de datos de adestramento, e o modelo se reentrena para considerar os novos datos.Ao engadir novos pesos e etiquetas, o modelo reentrena para mellorar a súa precisión co tempo.
Propóñoche:
Cambiar e aumentar os datos
Crear unha nova clase/categoría pera(2)
REALIZA O RETO 8-Tarefa 1 e 2
Paso 3 : Agora con imaxes
Imos ir un paso máis aló: en lugar de clasificar datos numéricos, clasificaremos imaxes de laranxas e mazás. Precisamos unha carpeta comprimida con moitísimas imaxes (zip - 3133143 B) de laranxas e mazás e outras dúas carpetas con imaxes de laranxas (zip - 73369 B) e de mazás (zip - 63944 B) para probar o modelo.
Este programa carga un dataset de imaxes de mazás e laranxas organizado en carpetas, procesándoas para extraer características como un array plano de píxeles redimensionados a 64x64.
Divide as características extraídas en dous conxuntos: un para adestrar o modelo de clasificación e outro para avaliar a súa precisión, empregando un clasificador RandomForestClassifier.
O modelo é adestrado cos datos proporcionados e logo avaliado calculando a súa precisión en función da capacidade de clasificar correctamente as imaxes de probas.
Inclúe unha funcionalidade interactiva que permite subir imaxes desde o ordenador e, tras procesalas, o modelo predí se a imaxe corresponde a unha mazá ou unha laranxa.
O programa continúa clasificando novas imaxes que subas ata que decidas finalizar o proceso.
Próbao!!!
Propóñoche que investigues:
Como debe ser o dataset?
A mostrar a imaxe coa predición.
Usar técnicas de preprocesamento de imaxes, como conversión a escala de grises ou normalización.
Proba clasificadores adicionais, como SVC ou KNeighborsClassifier.
REALIZA O RETO 8-Tarefa 3
Explicación detallada do programa
Importar bibliotecas necesarias
Código:
import os
from PIL import Image
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from google.colab import files
Explicación: Estas bibliotecas permiten realizar tarefas fundamentais:
os: Navegar por carpetas e ficheiros no sistema operativo.
Pillow (PIL.Image): Manipular imaxes, como abrir e redimensionar.
numpy: Procesar datos numéricos (matrices e vectores).
RandomForestClassifier: Un clasificador que combina múltiples árbores de decisión.
train_test_split: Dividir os datos en adestramento e probas.
accuracy_score: Avaliar que tan preciso é o modelo.
files: Permitir subir ficheiros desde o ordenador en Google Colab.
Función para cargar imaxes e extraer características
Código:
def cargar_e_extraer_caracteristicas(ruta_dataset):
caracteristicas = []
etiquetas = []
for etiqueta, clase in enumerate(["apple", "orange"]): # 0=apple, 1=orange
ruta_clase = os.path.join(ruta_dataset, clase)
print(f"Procesando a carpeta: {ruta_clase}")
for nome_imaxe in os.listdir(ruta_clase):
ruta_imaxe = os.path.join(ruta_clase, nome_imaxe)
imaxe = Image.open(ruta_imaxe).resize((64, 64))
imaxe_array = np.array(imaxe).flatten()
caracteristicas.append(imaxe_array)
etiquetas.append(etiqueta)
return np.array(caracteristicas), np.array(etiquetas)
Explicación: Esta función procesa o dataset para extraer características:
Carga todas as imaxes das carpetas (apple e orange).
Convérteas en arrays numéricos redimensionados a 64x64 píxeles.
Engade as características das imaxes ao conxunto de datos (caracteristicas) e as etiquetas correspondentes ao conxunto (etiquetas).
Dividir datos para adestramento e probas
Código:
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
Explicación: Divide os datos en dúas partes:
Adestramento: Usados para que o modelo aprenda.
Probas: Usados para verificar que tan ben funciona o modelo con datos novos.
O 20% dos datos son reservados para probas (test_size=0.2).
Explicación: Crea un modelo de RandomForestClassifier e adéstrao cos datos de adestramento. O modelo aprende a identificar mazás e laranxas a partir dos píxeles das imaxes.
Explicación: O modelo realiza predicións para os datos de probas e calcula a súa precisión. O resultado mostra que tan ben predí o modelo.
Clasificación interactiva de novas imaxes
Código:
def clasificar_imaxes_interactivas():
while True:
print("Por favor, carga unha imaxe desde o teu ordenador para clasificar:")
arquivo_imaxe = files.upload()
for nome_imaxe in arquivo_imaxe.keys():
imaxe = Image.open(nome_imaxe).resize((64, 64))
imaxe_array = np.array(imaxe).flatten().reshape(1, -1)
resultado = modelo.predict(imaxe_array)
if resultado == 0:
print("A imaxe cargada clasifícase como: Mazá (Apple)")
else:
print("A imaxe cargada clasifícase como: Laranxa (Orange)")
continuar = input("¿Queres clasificar outra imaxe? (si/non): ").strip().lower()
if continuar != "si":
print("Programa finalizado. Ata logo!")
break
Explicación: Este bucle interactivo permite ao usuario:
Subir unha imaxe desde o ordenador.
Redimensionar a imaxe e convertela nun array numérico.
Predicir se a imaxe é unha mazá ou unha laranxa.
Continuar clasificando novas imaxes ata que o usuario decida rematar.
Unha instancia do modelo de árbore de decisión é simplemente un obxecto que creamos a partir da clase DecisionTreeClassifier en Scikit-learn.
É coma se tomásemos o "molde" que representa como funciona unha árbore de decisión (que está definido en Scikit-learn) e construísemos nosa propia versión personalizada para resolver o noso problema específico.
Estamos a crear unha copia da árbore de decisión que podemos adestrar, usar para predicións e adaptar aos nosos datos.
Esta copia ten todos os métodos e propiedades necesarios para levar a cabo tarefas como clasificación ou predición.
A instancia adéstrase con datos (como pesos de froitas) para aprender un patrón. Despois, usamos esa mesma instancia para facer predicións baseadas nos novos datos que lle deamos.
Código Python: Clasificando e incorporando datos
# Importar as bibliotecas necesarias
import os
from PIL import Image
import numpy as np
import zipfile
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from google.colab import files
# Subir o arquivo comprimido (zip)
print("Por favor, carga o arquivo ZIP coas imaxes:")
uploaded = files.upload() # Subir un arquivo ZIP
# Descomprimir o arquivo
for filename in uploaded.keys():
with zipfile.ZipFile(filename, 'r') as zip_ref:
zip_ref.extractall("dataset") # Extraer todo nunha carpeta chamada 'dataset'
print("Carpeta descomprimida. Os datos están listos para procesar.")
# Función para cargar imaxes e extraer características
def cargar_e_extraer_caracteristicas(ruta_dataset):
caracteristicas = []
etiquetas = []
for etiqueta, clase in enumerate(["apple", "orange"]): # 0=apple, 1=orange
ruta_clase = os.path.join(ruta_dataset, clase)
print(f"Procesando a carpeta: {ruta_clase}")
for nome_imaxe in os.listdir(ruta_clase):
ruta_imaxe = os.path.join(ruta_clase, nome_imaxe)
#print(f"Procesando a imaxe: {ruta_imaxe}")
# Abrir a imaxe e redimensionala a 64x64 píxeles
imaxe = Image.open(ruta_imaxe).resize((64, 64))
imaxe_array = np.array(imaxe).flatten() # Convertir a array plano (1D)
caracteristicas.append(imaxe_array)
etiquetas.append(etiqueta) # Engadir etiqueta (0 ou 1)
return np.array(caracteristicas), np.array(etiquetas)
# Ruta ao dataset descomprimido
ruta_dataset = "dataset/fruit-dataset"
# Cargar e procesar as imaxes
X, y = cargar_e_extraer_caracteristicas(ruta_dataset)
# Dividir os datos en conxuntos de adestramento e probas
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Crear e adestrar o modelo
modelo = RandomForestClassifier(random_state=42)
modelo.fit(X_train, y_train)
# Avaliar o modelo
predicións = modelo.predict(X_test)
precisión = accuracy_score(y_test, predicións)
print(f"Precisión do modelo: {precisión:.2f}")
# Bucle para subir e clasificar imaxes ata que o usuario decida rematar
def clasificar_imaxes_interactivas():
while True:
print("Por favor, carga unha imaxe desde o teu ordenador para clasificar:")
arquivo_imaxe = files.upload() # Subir imaxe
for nome_imaxe in arquivo_imaxe.keys():
imaxe = Image.open(nome_imaxe).resize((64, 64))
imaxe_array = np.array(imaxe).flatten().reshape(1, -1)
resultado = modelo.predict(imaxe_array)
if resultado == 0:
print("A imaxe cargada clasifícase como: Mazá (Apple)")
else:
print("A imaxe cargada clasifícase como: Laranxa (Orange)")
# Preguntar ao usuario se quere continuar
continuar = input("¿Queres clasificar outra imaxe? (si/non): ").strip().lower()
if continuar != "si":
print("Programa finalizado. Ata logo!")
break
# Iniciar o proceso de clasificación interactiva
clasificar_imaxes_interactivas()
Código Python: Clasificando imaxes de laranxas e mazás
# Importar as bibliotecas necesarias
import os
from PIL import Image
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from google.colab import files
# Función para cargar imaxes e extraer características
def cargar_e_extraer_caracteristicas(ruta_dataset):
caracteristicas = []
etiquetas = []
for etiqueta, clase in enumerate(["apple", "orange"]): # 0=apple, 1=orange
ruta_clase = os.path.join(ruta_dataset, clase)
print(f"Procesando a carpeta: {ruta_clase}")
for nome_imaxe in os.listdir(ruta_clase):
ruta_imaxe = os.path.join(ruta_clase, nome_imaxe)
#print(f"Procesando a imaxe: {ruta_imaxe}")
# Abrir a imaxe e redimensionala a 64x64 píxeles
imaxe = Image.open(ruta_imaxe).resize((64, 64))
imaxe_array = np.array(imaxe).flatten() # Convertir a array plano (1D)
caracteristicas.append(imaxe_array)
etiquetas.append(etiqueta) # Engadir etiqueta (0 ou 1)
return np.array(caracteristicas), np.array(etiquetas)
# Ruta ao dataset descomprimido
ruta_dataset = "dataset/fruit-dataset"
# Cargar e procesar as imaxes
X, y = cargar_e_extraer_caracteristicas(ruta_dataset)
# Dividir os datos en conxuntos de adestramento e probas
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Crear e adestrar o modelo
modelo = RandomForestClassifier(random_state=42)
modelo.fit(X_train, y_train)
# Avaliar o modelo
predicións = modelo.predict(X_test)
precisión = accuracy_score(y_test, predicións)
print(f"Precisión do modelo: {precisión:.2f}")
# Bucle para subir e clasificar imaxes ata que o usuario decida rematar
def clasificar_imaxes_interactivas():
while True:
print("Por favor, carga unha imaxe desde o teu ordenador para clasificar:")
arquivo_imaxe = files.upload() # Subir imaxe
for nome_imaxe in arquivo_imaxe.keys():
imaxe = Image.open(nome_imaxe).resize((64, 64))
imaxe_array = np.array(imaxe).flatten().reshape(1, -1)
resultado = modelo.predict(imaxe_array)
if resultado == 0:
print("A imaxe cargada clasifícase como: Mazá (Apple)")
else:
print("A imaxe cargada clasifícase como: Laranxa (Orange)")
# Preguntar ao usuario se quere continuar
continuar = input("¿Queres clasificar outra imaxe? (si/non): ").strip().lower()
if continuar != "si":
print("Programa finalizado. Ata logo!")
break
# Iniciar o proceso de clasificación interactiva
clasificar_imaxes_interactivas()
Actividade 2: Regresión
◦ Obxectivo: Entender como funciona a regresión lineal usando Scikit-learn. ◦ Instrución: Usar Scikit-learn para prever valores numéricos baseándose en datos de exemplo.
Paso 1: Entendendo o básico da regresión lineal
Imos crear un modelo básico de regresión lineal usando Scikit-learn. O exemplo tratará sobre a predición do prezo dunha casa en función do seu tamaño (en metros cadrados).
Código Python: Canto custa unha casa
A# Importar as librerías necesarias
from sklearn.linear_model import LinearRegression
# Datos de exemplo: tamaño das casas (m²) e os seus prezos (€)
tamano_casas = [[50], [80], [100], [150], [200]] # Área en m²
prezos_casas = [100000, 180000, 240000, 300000, 400000] # Prezo en euros
# Crear o modelo de regresión lineal
modelo_regresion = LinearRegression()
# Adestrar o modelo cos datos de entrada (tamaño das casas) e saída (prezos)
modelo_regresion.fit(tamano_casas, prezos_casas)
# Predicir o prezo dunha casa de 120 m²
tamano_prediccion = [[120]] # Tamaño para predicir
prezo_predito = modelo_regresion.predict(tamano_prediccion)
# Amosar o resultado da predición
print(f"O prezo dunha casa de 120 m² será: {prezo_predito[0]:.2f} €")
Explicación do código:
LinearRegression: O modelo usado para atopar a relación entre o tamaño da casa e o seu prezo.
fit: Adéstrase o modelo cos datos de tamaño e prezo para aprender os patróns.
predict: Usa o modelo adestrado para predicir o prezo dunha casa cun tamaño específico.
Proba este código en Colab e comproba o resultado. Funciona correctamente?
Paso 2: Ampliando datos e graficando a liña de regresión
Neste paso, incluiremos máis datos e crearemos unha gráfica para representar a liña de regresión, utilizando bibliotecas como Matplotlib.
Código Python: Custo gráfico dunha casa según tamaño
# Importar bibliotecas necesarias
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
# Datos de exemplo ampliados: tamaño das casas (m²) e prezos (€)
tamano_casas = np.array([[50], [80], [100], [150], [200], [250], [300]]) # Áreas ampliadas
prezos_casas = np.array([100000, 180000, 240000, 300000, 400000, 500000, 600000]) # Prezos ampliados
# Crear o modelo de regresión
modelo = LinearRegression()
# Adestrar o modelo cos datos ampliados
modelo.fit(tamano_casas, prezos_casas)
# Visualizar os datos e a liña de regresión
plt.scatter(tamano_casas, prezos_casas, color='blue', label='Datos reais')
plt.plot(tamano_casas, modelo.predict(tamano_casas), color='red', label='Liña de regresión')
plt.xlabel("Tamaño da casa (m²)")
plt.ylabel("Prezo da casa (€)")
plt.title("Liña de regresión: Prezo vs Tamaño")
plt.legend()
plt.grid(True)
plt.show()
# Predicir o prezo dunha casa de 180 m²
tamano_prediccion = np.array([[180]]) # Tamaño para predicir
prezo_predito = modelo.predict(tamano_prediccion)
print(f"O prezo dunha casa de 180 m² será: {prezo_predito[0]:.2f} €")
Explicación do programa:
Datos ampliados: Engadimos máis tamaños de casas e os seus prezos correspondentes para mellorar o modelo.
Matplotlib: Usamos esta biblioteca para visualizar os datos reais como puntos azuis e a liña de regresión como unha liña vermella.
Liña de regresión: Representa o patrón aprendido polo modelo entre tamaño e prezo.
Predición: Calculamos o prezo para unha casa específica (180 m²) usando o modelo adestrado.
Proba este código en Google Colab e verifica se a gráfica e a predición funcionan correctamente.
Paso 3: Regresión con múltiples variables
Neste paso, incorporaremos outra variable, como o número de habitacións, para mellorar as predicións. Esto permitirá comprender como funciona a regresión multivariable.
Creación propia. Regresión multivariable(CC BY-SA)
Código Python: Custo dunha casa según tamaño e habitacións
# Importar bibliotecas necesarias
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
# Datos de exemplo: tamaño (m²), número de habitacións e prezos (€)
datos_casas = np.array([[50, 2], [80, 3], [100, 3], [150, 4], [200, 4], [250, 5], [300, 6]])
prezos_casas = np.array([100000, 180000, 240000, 300000, 400000, 500000, 600000])
# Crear o modelo de regresión
modelo = LinearRegression()
# Adestrar o modelo cos datos de entrada e saída
modelo.fit(datos_casas, prezos_casas)
# Predicir o prezo dunha casa de 120 m² con 3 habitacións
datos_prediccion = np.array([[120, 3]]) # Tamaño e número de habitacións
prezo_predito = modelo.predict(datos_prediccion)
# Mostrar o resultado da predición
print(f"O prezo dunha casa de 120 m² e 3 habitacións será: {prezo_predito[0]:.2f} €")
# Crear un DataFrame para visualizar os datos
datos = pd.DataFrame({
'Tamaño (m²)': datos_casas[:, 0],
'Habitacións': datos_casas[:, 1],
'Prezo (€)': prezos_casas
})
# Personalizar o fondo amarelo suave
sns.set(style="whitegrid")
plt.figure(figsize=(10, 6), facecolor="#fffbe6") # Fondo amarelo suave
ax = sns.scatterplot(
x='Tamaño (m²)',
y='Prezo (€)',
size='Habitacións',
hue='Habitacións',
palette='viridis',
data=datos,
sizes=(50, 300),
legend='brief'
)
ax.set_facecolor("#fffbe6") # Configurar fondo interno da gráfica
plt.title('Relación entre tamaño, habitacións e prezo das casas', fontsize=14)
plt.xlabel('Tamaño da casa (m²)', fontsize=12)
plt.ylabel('Prezo da casa (€)', fontsize=12)
plt.legend(title="Habitacións", loc='upper left', bbox_to_anchor=(1, 1))
plt.show()
# Mostrar coeficientes do modelo
print("Coeficientes do modelo:", modelo.coef_)
print("Intersección (bias):", modelo.intercept_)
Datos multivariable: Usamos dous factores (tamaño e número de habitacións) para predicir os prezos.
LinearRegression: O modelo agora traballa con múltiples variables.
Coeficientes: Mostran como cada variable afecta o prezo da casa.
Intersección: O valor base cando todas as variables son 0 (tamén coñecido como bias).
Visualización con Seaborn:Usamos un gráfico de dispersión no que
O tamaño e a cor dos puntos representan o número de habitacións.
A relación entre o tamaño e o prezo se visualiza nunha dimensión clara.
Configuramos unha paleta de cores progresiva con viridis para facilitar a interpretación.
Uso de DataFrame con Pandas:Organizamos os datos en forma de DataFrame para facilitar o procesamento e as gráficas.
Gráfico mellorado:Engadimos un tamaño dinámico dos puntos para enfatizar o impacto do número de habitacións.
Proba este código no teu entorno de Colab e comproba os resultados. Observa como se comporta o modelo ao engadir máis datos.
Estes valores son os resultados do modelo de regresión lineal, e cada un representa aspectos clave da relación entre as variables (tamaño da casa e número de habitacións) e o prezo predito.
Coeficientes do modelo: [1719.04761905, 14190.47619048]
Estes coeficientes indican canto cambia o prezo da casa por cada unidade adicional de cada variable:
1719.04761905: Se o tamaño da casa aumenta en 1 m², o prezo da casa aumenta aproximadamente en 1719,05 €.
14190.47619048: Se o número de habitacións aumenta en 1, o prezo da casa aumenta aproximadamente en 14190,48 €.
Son valores que o modelo aprende a partir dos datos proporcionados para captar como cada factor inflúe no prezo.
Intersección (bias): -809.5238095236709
Este é o punto onde a liña de regresión "corta" o eixo vertical (prezos) cando todas as variables son igual a 0.
En termos simples: Se unha casa tivese tamaño igual a 0 m² e número de habitacións igual a 0 (un caso teórico), o modelo prediría un prezo inicial de -809,52 €.
Este valor é unha constante base que o modelo usa para axustar os cálculos e reflicte a súa calibración inicial.
Actividade 3: Segmentación e manexo de arquivos de datos
◦ Obxectivo: Comprender o concepto de clustering ou agrupamento co algoritmo Kmeans e aprender a usar dataset libres da web en proxectos. ◦ Instrución: Predicir os hábitos de compra a partir dun clustering de datos cun arquivo .csv. e aplicalos a unha ficticia multinacional de roupa e complementos.
Subiremos o arquivo (csv - 416614 B) desde o noso ordenador a Google Colab e cargaremos os datos no DataFrame para exploración inicial de que tipo de datos, columnas, cantidade etc, temos no arquivo con este programa.
Estos son os datos traducidos para que o comprendas mellor:
ID do Cliente
Idade
Xénero
Elemento Comprado
Categoría
Importe da Compra
Tamaño
Cor
Estación
Clasificación
Método de Pago
Frecuencia de Compras
1
55
Home
Blusa
Roupa
53
L
Gris
Inverno
3.1
Venmo
Quincenal
2
19
Home
Suéter
Roupa
64
L
Granate
Inverno
3.1
Efectivo
Quincenal
3
50
Home
Pantalóns
Roupa
73
S
Granate
Primavera
3.1
Tarxeta de crédito
Semanal
4
21
Home
Sandalias
Calzado
90
M
Granate
Primavera
3.5
PayPal
Semanal
5
45
Home
Blusa
Roupa
49
M
Turquesa
Primavera
2.7
PayPal
Anual
Paso 2:Preprocesamento de datos
Os datos deste arquivo teñen múltiples posibilidades para unha multinacional de roupa, como podes imaxinar.
Sen embargo, a maioría das veces os arquivos de BigData teñen erros, xa sexa por tipos de datos que non serven para o estudo que se quere facer, por datos baleiros ou con erros no formato, etc...
É moi importante "comprobar e limpar" os datos antes de utilizalos en intelixencia artificial (IA) para garantir que as análises, modelos ou aplicacións que construamos funcionen correctamente e produzan resultados fiables. Este proceso é coñecido como preprocesamento de datos e aplícase en calquera tipo de proxecto de IA que dependa de información (datos) como base.
Por suposto, existen técnicas moi depuradas para preparar os datos para IA, pero imos facelo "manualmente" para que comprendas os erros e problemas que pode ter un dataset.
Este programa limpa e prepara os datos para o clustering que nos interesa: convirte datos, xenera categorías, enche espazos baleiros, etc.
Ó final, xenera outro arquivo cos datos preparados para o clustering que che interese.
Os datos complexos, complican a visualización e comprensión dos datos, polo que xeneraremos só datos numéricos coas columnas Idade, Gasto e Talla, convertindo esta última a int con S=1, M=2,L=3 e XL=4 .
Anímote a que vexas ambos arquivos, entendas as diferencias e o que fixo o programa en cada caso.
Agora realizamos unha segmentación ou clustering, según a idade, o gasto medio e a talla, por exemplo, usando Kmeans para xenerar os clústeres.
Imos paso a paso para que comprendas ben o proceso:
Este primeiro programa, ensínache o que é un cluster e como se decide se un dato, agrúpase nun ou noutro clúster.
Recoméndoche executalo varias veces para afianzar a comprensión do concepto e usando primeiro 2 columnas(2D) e logo 3 columnas(3D).
Supoño que comprendes que os espazos de clústeres reais teñen moitísimas dimensións, e só unha máquina pode darlle sentido e "velo", pero o proceso é o mesmo que estamos intentando comprender en "visión humana" e "dimensións humana" de 2D e 3D.
A táboa seguinte preséntase para fins educativos. É un exemplo en 2D coas columnas Idade e Gasto con 4 clústeres. Cada vez que executes o programa, sairán 3 puntos aleatorios do dataset.
Na primeira columna están os datos do punto, incluíndo os valores escalados, na terceira columnas amósanse as distancias calculadas cara a cada centroide, e na cuarta tes un espazo reservado para a gráfica das distancias.
Datos do Punto
Distancias aos Centroides
Gráfica das Distancias
Análise do punto (índice 839) Valores escalados do punto: Idade: 0.258558 Gasto: -1.214590
Este segundo programa, ensínache o que é un clustering completo dun arquivo de datos. Como exemplo escollemos 3 clusters (existen algoritmos para decidir o mellor número de clusteres para os datos e os obxectivos concretos) e as tres columnas que xeneramos no preprocesamento de datos.
Creación propia. Clusterin/Segmentación/Agrupamento completo(CC BY-SA)
Identificación dos eixos e clusters: A gráfica é un scatter plot 3D nas súas tres dimensións: Idade (Eixe X), Gasto (Eixe Y) e Talla (Eixe Z). Vemos tres clusters claramente diferenciados, cada un representado nunha cor distinta: azul para o Cluster 0, laranxa para o Cluster 1 e verde para o Cluster 2.
Observación da dispersión : É posible constatar que os puntos dentro de cada cluster están relativamente próximos entre si, formando núcleos "similares ou unidos". Por exemplo, o Cluster 0 (en azul) agrupa os seus puntos arredor dun centro (representado por un "X") e o punto exemplar (indexado como 914) actúa como referencia concreta deste grupo. Este patrón de compactación e separación entre clusters indica que os datos posúen diferenzas significativas e que a máquina logra identificar unha estrutura real na información.(Que se ven bastante ben 3 capas de datos diferenciados)
Información útil para unha multinacional de roupa: Unha empresa con coñecemento dos hábitos de compra pode usar este tipo de análise para segmentar o mercado.
Por exemplo:
Se o Cluster 2 (en verde, exemplificado polos datos do índice 498 ) mostra clientes cun nivel de gasto elevado e unha faixa de idade contínua(todas as idades), pero tallas pequenas, a empresa podería dicir que ese segmento representa un mercado premium a quen ofrecer produtos exclusivos.
Se o Cluster 1 (en laranxa, exemplificado polo punto de índice 2328) acolle clientes cun gasto moderado ou baixo, a compañía podería crear promocións ou ofertas adaptadas a ese segmento.
De forma similar, o Cluster 0 (en azul) pode representar un grupo intermedio ou outro perfil coa característica sobresaínte de tallas grandes, permitindo personalizar o marketing e as campañas de fidelización.
Todo isto se confirma visualmente na gráfica, xa que as diferenzas de cor, a posición dos centroides e os exemplos concretos permiten detectar patróns reais que son verificables na segmentación dos datos.
Conclusión que debes comprender: A gráfica non só amosa de maneira clara a segregación dos datos en función de tres variables clave (Idade, Gasto e Talla), senón que tamén serve para ilustrar como unha máquina pode detectar relacións e agrupamentos que poden pasarnos desapercibidos.
Esta representación visual é unha ferramenta poderosa no ámbito do Big Data, xa que permite que, coa súa análise, se extraian decisións axeitadas para neste exemplo, a estratexia comercial dunha multinacional de roupa.
Que é un cluster?
Un cluster é un grupo de elementos semellantes que se agrupan xuntos segundo as súas características.
O algoritmo busca patróns nos datos para formar os grupos, sen necesidade de coñecer previamente que etiquetas teñen (aprendizaxe non supervisada).
O clustering é unha técnica que nos axuda a agrupar elementos semellantes sen coñecer previamente as etiquetas ou categorías.
Esta técnica de aprendizaxe non supervisada, significa que non lle dicimos ao ordenador que tipo de elemento está a ver( como fixemos cos laranxas/mazás ou can/gato), pero pedímoslle que os agrupe por características comúns.
Código Python: Subir o arquivo e visualizar os primeiros datos
# Importar as librerías
import pandas as pd
import matplotlib.pyplot as plt
from google.colab import files # Biblioteca para subir arquivos
# Subir o arquivo desde o ordenador
uploaded = files.upload()
# Cargar os datos do arquivo CSV (o nome do arquivo será a chave do dicionario 'uploaded')
datos = pd.read_csv(list(uploaded.keys())[0])
# Mostrar as primeiras filas para entender os datos
print(datos.head())
Código Python: Preprocesado de datos
# Importar librerías necesarias
import pandas as pd
# Función para analizar, limpar, preprocesar e modificar datos de forma educativa
def analizar_limpar_e_modificar_datos():
print("Benvido/a! Este programa axudarache a analizar, limpar e preparar os teus datos para proxectos de IA.")
print("Explicaremos cada paso para que comprendas por que é necesario realizar este proceso.")
# Paso 1: Subir o arquivo CSV
from google.colab import files
print("\nPor favor, sube o arquivo CSV cos datos que desexas analizar e limpar:")
uploaded = files.upload()
nome_arquivo = list(uploaded.keys())[0]
datos = pd.read_csv(nome_arquivo)
print(f"\nArquivo '{nome_arquivo}' cargado correctamente!")
print("\nVisualizando as primeiras filas dos datos:")
print(datos.head())
# Paso 2: Seleccionar columnas para analizar e limpar
print("\nColumnas dispoñibles no arquivo:")
print(list(datos.columns))
print("\nSelecciona as columnas que queres analizar e limpar. Introduce os nomes separados por comas.")
columnas_seleccionadas = input("Introduce os nomes das columnas (exemplo: 'Column1,Column2'): ").split(',')
# Limpar espazos ao redor dos nomes das columnas
columnas_seleccionadas = [col.strip() for col in columnas_seleccionadas]
print(f"\nSeleccionaches estas columnas: {columnas_seleccionadas}")
# Comprobar que as columnas existen
for columna in columnas_seleccionadas:
if columna not in datos.columns:
print(f"\nErro: A columna '{columna}' non existe no arquivo. Revise os nomes.")
return
# Paso 3: Cambiar nomes das columnas seleccionadas
print("\nQueres cambiar o nome dalgunha das columnas seleccionadas?")
print("1 - Si, quero cambiar os nomes.")
print("2 - Non, quero manter os nomes actuais.")
cambiar_nomes = input("Introduce o número correspondente á túa elección: ")
if cambiar_nomes == "1":
novos_nomes = {}
for columna in columnas_seleccionadas:
novo_nome = input(f"Introduce o novo nome para a columna '{columna}': ")
novos_nomes[columna] = novo_nome
datos.rename(columns=novos_nomes, inplace=True)
columnas_seleccionadas = [novos_nomes[col] for col in columnas_seleccionadas]
print(f"\nOs nomes das columnas foron actualizados: {novos_nomes}")
else:
print("\nManteranse os nomes orixinais das columnas seleccionadas.")
# Crear un DataFrame para traballar con só as columnas seleccionadas
datos_seleccionados = datos[columnas_seleccionadas].copy()
# Paso 4: Analizar e modificar valores en cada columna
print("\nAgora imos analizar os valores nas columnas seleccionadas.")
filas_a_eliminar = []
for columna in columnas_seleccionadas:
print(f"\nAnalizando a columna: '{columna}'")
tipos_detectados = datos_seleccionados[columna].apply(type).unique()
print(f"- Tipos de datos detectados: {[tipo.__name__ for tipo in tipos_detectados]}")
# Preguntar ao usuario que tipo de dato debería ter a columna
print("\nQue tipo de dato debería ter esta columna?")
print("1 - bool (True/False)")
print("2 - int (Números enteiros)")
print("3 - float (Números decimais)")
print("4 - str (Texto)")
tipo_dato_esperado = input("Introduce o número correspondente ao tipo de dato esperado: ")
tipo_actual = None
if pd.api.types.is_bool_dtype(datos_seleccionados[columna]):
tipo_actual = "1"
elif pd.api.types.is_integer_dtype(datos_seleccionados[columna]):
tipo_actual = "2"
elif pd.api.types.is_float_dtype(datos_seleccionados[columna]):
tipo_actual = "3"
elif pd.api.types.is_string_dtype(datos_seleccionados[columna]):
tipo_actual = "4"
if tipo_dato_esperado == tipo_actual:
print(f"- A columna '{columna}' xa está no formato esperado. Non require cambios.")
else:
# Convertir a columna ao tipo especificado
try:
if tipo_dato_esperado == "1":
datos_seleccionados[columna] = datos_seleccionados[columna].astype(bool)
elif tipo_dato_esperado == "2":
datos_seleccionados[columna] = datos_seleccionados[columna].astype(int)
elif tipo_dato_esperado == "3":
datos_seleccionados[columna] = datos_seleccionados[columna].astype(float)
elif tipo_dato_esperado == "4":
datos_seleccionados[columna] = datos_seleccionados[columna].astype(str)
print(f"- A columna '{columna}' foi convertida ao formato esperado.")
except ValueError as e:
print(f"\nErro ao converter os datos: {e}. Revisando os valores...")
# Preguntar ao usuario se quere cambiar os valores das categorías detectadas
categorias = datos_seleccionados[columna].unique()
print(f"- A columna '{columna}' ten {len(categorias)} categorías: {categorias}")
print("\nQueres cambiar os valores das categorías?")
print("1 - Si, quero cambiar os nomes/valores das categorías.")
print("2 - Non, quero manter os valores actuais.")
cambio_categoria = input("Introduce o número da túa elección: ")
if cambio_categoria == "1":
conversion = {}
for categoria in categorias:
print(f"Para a categoría '{categoria}', introduce o valor co que a queres substituír:")
novo_valor = input("Novo valor: ")
conversion[categoria] = novo_valor
print(f"Mapa de conversión para '{columna}': {conversion}")
datos_seleccionados[columna] = datos_seleccionados[columna].map(conversion)
# Validación de valores inexistentes ou problemáticos
print("- Comprobando valores inexistentes ou problemáticos na columna...")
for i, valor in enumerate(datos_seleccionados[columna]):
if pd.isnull(valor): # Valor inexistente ou NaN
print(f"Fila {i+1}: O valor está baleiro ou inexistente.")
decision = input("Queres eliminar esta fila? (Si/Non): ").strip().lower()
if decision == "si":
filas_a_eliminar.append(i)
# Eliminar filas erróneas segundo decisións do usuario
print("\nEliminando filas problemáticas segundo as túas decisións...")
datos_limpados = datos_seleccionados.drop(filas_a_eliminar, axis=0)
print(f"Filas eliminadas: {len(filas_a_eliminar)}")
# Paso 5: Gardar o arquivo limpo
print("\nGardando o arquivo limpo e completamente preprocesado...")
nome_saida = input("Introduce o nome do arquivo de saída (por exemplo, 'datos_limpados.csv'): ")
datos_limpados.to_csv(nome_saida, index=False)
print(f"\nArquivo limpo gardado como '{nome_saida}'. Contén os datos seleccionados e correctamente limpos.")
# Ofrecer ao usuario descargar o arquivo
print("\nDescargando o arquivo...")
files.download(nome_saida)
# Executar o programa educativo
analizar_limpar_e_modificar_datos()
Código Python: Creación de clústeres interactiva e con graficado de criterio de clasificación dun dato nun cluster
# Importar librerías necesarias
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
# Para a visualización 3D (se se seleccionan 3 columnas)
from mpl_toolkits.mplot3d import Axes3D
# Función interactiva para clustering con explicaciones detalladas
def clustering_interactivo():
print("Benvido/a ao programa interactivo de clustering con K-Means.")
print("Neste programa aprenderás paso a paso os conceptos de clustering, como a selección de columnas, escalado, elección do número de clusters,")
print("o cálculo dos centroides e a análise das distancias entre puntos e centroides.\n")
# Paso 1: Subida do arquivo CSV
print("[Paso 1] Por favor, sube o arquivo CSV cos datos que desexas usar.")
from google.colab import files
uploaded = files.upload()
nome_arquivo = list(uploaded.keys())[0]
datos = pd.read_csv(nome_arquivo)
print(f"\nO arquivo '{nome_arquivo}' foi cargado correctamente!")
print("Visualización das primeiras 5 filas para que veas os teus datos:")
print(datos.head())
# Paso 2: Mostrar columnas dispoñibles e os seus tipos
print("\n[Paso 2] Estas son as columnas dispoñibles no arquivo e os seus tipos de datos:")
print(datos.dtypes)
columnas_dispoñibles = list(datos.columns)
print("\nRecorda: Os métodos de clustering utilizan valores numéricos para representar as dimensións dos datos.")
input("\nPreme ENTER para continuar...")
# Paso 3: Selección interactiva de columnas (2 ou 3 columnas)
while True:
print("\n[Paso 3] Selecciona 2 ou 3 columnas numéricas para realizar o clustering.")
print("Por exemplo, se queres 2 columnas, escribe: col1, col2")
print("E se prefires 3 columnas, escribe: col1, col2, col3")
columnas_seleccionadas = input("Columnas seleccionadas: ").split(',')
columnas_seleccionadas = [col.strip() for col in columnas_seleccionadas]
# Verificar se as columnas existen
columnas_non_existentes = [col for col in columnas_seleccionadas if col not in columnas_dispoñibles]
if columnas_non_existentes:
print(f"\nErro: As seguintes columnas non existen: {columnas_non_existentes}. Revisa os nomes e tenta de novo.")
continue
# Comprobar que se elixin 2 ou 3 columnas
if len(columnas_seleccionadas) < 2 or len(columnas_seleccionadas) > 3:
print("\nErro: Debes seleccionar exactamente 2 ou 3 columnas para este programa educativo.")
continue
# Validar que as columnas sexan numéricas
columnas_non_numericas = [col for col in columnas_seleccionadas if not pd.api.types.is_numeric_dtype(datos[col])]
if columnas_non_numericas:
print(f"\nAs seguintes columnas non son numéricas: {columnas_non_numericas}.")
print("Opcions:")
print("1 - Escoller novas columnas numéricas.")
print("2 - Usar só as columnas numéricas dos que seleccionaches.")
eleccion = input("Que desexas facer? (1 ou 2): ").strip()
if eleccion == "1":
continue
elif eleccion == "2":
columnas_seleccionadas = [col for col in columnas_seleccionadas if col not in columnas_non_numericas]
if len(columnas_seleccionadas) < 2:
print("\nErro: Despois de filtrar, quedan menos de 2 columnas numéricas. Tenta de novo con outras columnas.")
continue
print(f"\nAs columnas seleccionadas modifícanse agora a: {columnas_seleccionadas}")
break
else:
print("\nOpción non válida. Inténtase de novo.")
else:
break
input("\nPreme ENTER para continuar á preparación dos datos...")
# Paso 4: Escalado dos datos
print("\n[Paso 4] Procesando e escalando os datos seleccionados...")
print("Explicación: As columnas poden ter escalas diferentes, polo que escalamos os datos para que cada dimensión teña a mesma influéncia no clustering.")
datos_num = datos[columnas_seleccionadas].copy()
scaler = StandardScaler()
datos_escalados = pd.DataFrame(scaler.fit_transform(datos_num), columns=columnas_seleccionadas)
print("\nOs datos seleccionados foron escalados correctamente.")
input("\nPreme ENTER para continuar á selección do número de clusters...")
# Paso 5: Selección do número de clusters
print("\n[Paso 5] Selección do número de clusters para o análisis.")
print("Explicación: O número de clusters determina como se agruparán os puntos.\n"
"- Un número baixo pode xerar grupos moi amplos,")
print(" mentres que un número elevado pode crear grupos moi pequenos e específicos.")
while True:
try:
num_clusters = int(input("Introduce o número de clusters (entre 2 e 10): ").strip())
if 2 <= num_clusters <= 10:
break
else:
print("Por favor, introduce un valor entre 2 e 10.")
except ValueError:
print("Erro: Debes introducir un número enteiro válido.")
input("\nPreme ENTER para aplicar o algoritmo K-Means...")
# Paso 6: Aplicación do algoritmo K-Means
print(f"\n[Paso 6] Aplicando K-Means con {num_clusters} clusters.")
print("Explicación: K-Means asigna cada punto a un cluster segundo a súa proximidade co centroide do grupo,")
print("que é a posición media dos puntos dentro do cluster.")
modelo = KMeans(n_clusters=num_clusters, random_state=42)
datos_escalados['Cluster'] = modelo.fit_predict(datos_escalados)
print("\nOs clusters foron asignados. Cada punto recibiu un identificador do cluster ao que pertence.")
input("\nPreme ENTER para continuar coa análise dos puntos e os centroides...")
# Paso 7: Selección e análise de 3 puntos aleatorios
print("\n[Paso 7] Selección e análise de 3 puntos aleatorios do conxunto de datos.")
print("Explicación: Este paso pretende que observes como se calculan as distancias dos puntos aos centroides de cada cluster.")
if len(datos_escalados) < 3:
print("Non hai suficientes datos para seleccionar 3 puntos. Usaremos todos os puntos dispoñibles.")
puntos_analise = datos_escalados.copy()
puntos_analise_originais = datos.copy()
else:
puntos_analise = datos_escalados.sample(n=3, random_state=42)
puntos_analise_originais = datos.loc[puntos_analise.index]
centroides = pd.DataFrame(modelo.cluster_centers_, columns=columnas_seleccionadas)
print("\nCentroides obtidos polo algoritmo (valores escalados):")
print(centroides)
print("\nA continuación, analízase cada un dos puntos seleccionados separadamente.")
for i, fila in puntos_analise.iterrows():
print(f"\n--- Análise do punto (índice {i}) ---")
print("Valores escalados do punto:")
print(fila[columnas_seleccionadas])
# Calcular distancias do punto a cada centroide
distancias = np.linalg.norm(centroides - fila[columnas_seleccionadas], axis=1)
for idx, distancia in enumerate(distancias):
print(f"Distancia ao centroide do Cluster {idx}: {distancia:.2f}")
cluster_asignado = np.argmin(distancias)
print(f"Conclusión: Este punto pertence ao Cluster {cluster_asignado}, xa que presenta a menor distancia ({distancias[cluster_asignado]:.2f}).")
# Xeración dunha gráfica individual para o punto analizado
if len(columnas_seleccionadas) == 2:
print("\nVisualización 2D para o punto analizado:")
fig, ax = plt.subplots(figsize=(8,6))
# Plot dos centroides
for idx, centroide in centroides.iterrows():
ax.scatter(centroide[columnas_seleccionadas[0]], centroide[columnas_seleccionadas[1]],
s=200, label=f"Centroide {idx}", alpha=0.8, marker='X')
# Plot do punto seleccionado
ax.scatter(fila[columnas_seleccionadas[0]], fila[columnas_seleccionadas[1]],
color='red', s=100, label=f"Punto índice {i}", marker='o')
# Trazo de liñas entre o punto e cada centroide
for idx, centroide in centroides.iterrows():
ax.plot([fila[columnas_seleccionadas[0]], centroide[columnas_seleccionadas[0]]],
[fila[columnas_seleccionadas[1]], centroide[columnas_seleccionadas[1]]],
linestyle='--', color='gray')
# Calcula o punto medio para mostrar a distancia
mid_x = (fila[columnas_seleccionadas[0]] + centroide[columnas_seleccionadas[0]]) / 2
mid_y = (fila[columnas_seleccionadas[1]] + centroide[columnas_seleccionadas[1]]) / 2
ax.text(mid_x, mid_y, f"{distancias[idx]:.2f}", fontsize=9, color="blue")
ax.set_xlabel(columnas_seleccionadas[0])
ax.set_ylabel(columnas_seleccionadas[1])
ax.set_title(f"Análise do Punto índice {i} (2D)")
ax.legend()
plt.show()
elif len(columnas_seleccionadas) == 3:
print("\nVisualización 3D para o punto analizado:")
fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(111, projection='3d')
# Plot dos centroides
for idx, centroide in centroides.iterrows():
ax.scatter(centroide[columnas_seleccionadas[0]], centroide[columnas_seleccionadas[1]],
centroide[columnas_seleccionadas[2]], s=200, label=f"Centroide {idx}", alpha=0.8, marker='X')
# Plot do punto seleccionado
ax.scatter(fila[columnas_seleccionadas[0]], fila[columnas_seleccionadas[1]], fila[columnas_seleccionadas[2]],
color='red', s=100, label=f"Punto índice {i}", marker='o')
# Trazo de liñas entre o punto e cada centroide
for idx, centroide in centroides.iterrows():
xs = [fila[columnas_seleccionadas[0]], centroide[columnas_seleccionadas[0]]]
ys = [fila[columnas_seleccionadas[1]], centroide[columnas_seleccionadas[1]]]
zs = [fila[columnas_seleccionadas[2]], centroide[columnas_seleccionadas[2]]]
ax.plot(xs, ys, zs, linestyle='--', color='gray')
mid_x = (fila[columnas_seleccionadas[0]] + centroide[columnas_seleccionadas[0]]) / 2
mid_y = (fila[columnas_seleccionadas[1]] + centroide[columnas_seleccionadas[1]]) / 2
mid_z = (fila[columnas_seleccionadas[2]] + centroide[columnas_seleccionadas[2]]) / 2
ax.text(mid_x, mid_y, mid_z, f"{distancias[idx]:.2f}", fontsize=9, color="blue")
ax.set_xlabel(columnas_seleccionadas[0])
ax.set_ylabel(columnas_seleccionadas[1])
ax.set_zlabel(columnas_seleccionadas[2])
ax.set_title(f"Análise do Punto índice {i} (3D)")
ax.legend()
plt.show()
else:
print("Visualización non soportada para o número de columnas seleccionadas.")
input("\nPreme ENTER para continuar co seguinte punto (se hai máis)...")
print("\nAnálise completada. Agrazadecemos a túa participación e esperamos que este proceso te axude a comprender mellor os conceptos de clustering.")
# Execución do programa
clustering_interactivo()
Os centroides en K-Means calcúlanse e actualízanse a medida que o algoritmo iterativamente refina os clusters.
Inicialización : O primeiro centroide seleccionase aleatoriamente a partir dos datos.Para os centroides seguintes, utilizase o algoritmo k-means , que escolle cada novo centroide a base da distancia dos puntos aos centroides xa seleccionados.Con este método, cada punto ten unha probabilidade de ser escollido proporcional ao cadrado da súa distancia mínima a calquera centroide xa definido, o que garante unha boa dispersión inicial dos centroides.
Asignación dos puntos: Unha vez establecidos os centroides iniciais, cada punto do dataset é asignado ao centroide máis próximo (medindo a distancia Euclídea, por exemplo).
Recalcular os centroides: Despois de asignar os puntos, cada centroide récalcúlase como a media aritmética de todos os puntos que lle foron asignados. Este novo cálculo reflicte a posición central do cluster formado polos puntos que se achegaron máis a ese centroide.
Iteración ata a converxencia: O proceso de asignación de puntos e recálculo de centroides repítese reiteradamente. O algoritmo detén as iteracións cando os centroides se estabilizan (ou sexa, cando os cambios de posición son prácticamente insignificantes) ou se alcanza un número máximo de iteracións.
Este proceso garante que, a medida que o algoritmo avanza, os clusters se definen de xeito que os puntos dentro de cada grupo son os máis similares posibles, segundo a medida de distancia utilizada. Esta metodoloxía enfróntase sempre a algún punto de aleatoriedade (especialmente na elección inicial dos centroides), polo que, en diferentes execucións, os clusters poderían variar lixeiramente se non se establece unha semilla fixa para a aleatoriedade (por exemplo, random_state=42 no noso código).
Código Python: Clustering completo dun arquivo de datos
# Importar librerías necesarias
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
# Para a visualización 3D (se se seleccionan 3 columnas)
from mpl_toolkits.mplot3d import Axes3D
def clustering_interactivo():
print("-----------------------------------------------------")
print("Benvido/a ao programa interactivo de clustering con K-Means.")
print("Neste proxecto veremos como unha máquina pode descubrir relacións entre datos\n"
"que os humanos, a man ou a simple análise visual, podemos non detectar. Isto representa\n"
"unha ferramenta moi poderosa en Big Data, abrindo un universo de posibilidades.")
print("-----------------------------------------------------\n")
# Paso 1: Subida do arquivo CSV
print("[Paso 1] Subida do arquivo CSV:")
print("Por favor, sube o arquivo CSV cos datos que desexas usar.")
from google.colab import files
uploaded = files.upload()
nome_arquivo = list(uploaded.keys())[0]
datos = pd.read_csv(nome_arquivo)
print(f"\nO arquivo '{nome_arquivo}' foi cargado correctamente!")
print("Visualización das primeiras 5 filas para que comprobes os teus datos:")
print(datos.head())
# Paso 2: Mostrar columnas dispoñibles e os seus tipos
print("\n[Paso 2] Visualización das columnas dispoñibles e os seus tipos:")
print(datos.dtypes)
columnas_dispoñibles = list(datos.columns)
print("\nRecorda: Para realizar clustering necesitamos valores numéricos para definir as dimensións.")
input("\nPreme ENTER para continuar...")
# Paso 3: Selección interactiva de columnas (2 ou 3 columnas)
while True:
print("\n[Paso 3] Selecciona 2 ou 3 columnas numéricas para o clustering.")
print("Exemplo: para 2 columnas, escribe: col1, col2")
print(" para 3 columnas, escribe: col1, col2, col3")
columnas_seleccionadas = input("Columnas seleccionadas: ").split(',')
columnas_seleccionadas = [col.strip() for col in columnas_seleccionadas]
# Verificar se as columnas existen
columnas_non_existentes = [col for col in columnas_seleccionadas if col not in columnas_dispoñibles]
if columnas_non_existentes:
print(f"\nErro: As seguintes columnas non existen: {columnas_non_existentes}. Revisa os nomes e tenta de novo.")
continue
# Comprobar que se seleccionen 2 ou 3 columnas
if len(columnas_seleccionadas) < 2 or len(columnas_seleccionadas) > 3:
print("\nErro: Debes seleccionar exactamente 2 ou 3 columnas para este programa educativo.")
continue
# Validar que as columnas sexan numéricas
columnas_non_numericas = [col for col in columnas_seleccionadas if not pd.api.types.is_numeric_dtype(datos[col])]
if columnas_non_numericas:
print(f"\nAs seguintes columnas non son numéricas: {columnas_non_numericas}.")
print("Opcións:")
print("1 - Escoller novas columnas numéricas.")
print("2 - Usar só as columnas numéricas dentre das que escolliche.")
eleccion = input("Que desexas facer? (1 ou 2): ").strip()
if eleccion == "1":
continue
elif eleccion == "2":
columnas_seleccionadas = [col for col in columnas_seleccionadas if col not in columnas_non_numericas]
if len(columnas_seleccionadas) < 2:
print("\nErro: Despois de filtrar, quedan menos de 2 columnas numéricas. Tenta de novo con outras columnas.")
continue
print(f"\nAs columnas seleccionadas modifícanse a: {columnas_seleccionadas}")
break
else:
print("\nOpción non válida. Inténtase de novo.")
else:
break
input("\nPreme ENTER para continuar á preparación dos datos...")
# Paso 4: Escalado dos datos
print("\n[Paso 4] Escalado dos datos:")
print("Explicación: As columnas poden ter escalas diferentes. Escalamos os datos para que cada dimensión teña o mesmo peso\n"
"no proceso de clustering, evitando que unha variable domine a análise.")
datos_num = datos[columnas_seleccionadas].copy()
scaler = StandardScaler()
datos_escalados = pd.DataFrame(scaler.fit_transform(datos_num), columns=columnas_seleccionadas)
print("\nOs datos foron escalados correctamente.")
input("\nPreme ENTER para continuar á selección do número de clusters...")
# Paso 5: Selección do número de clusters
print("\n[Paso 5] Selección do número de clusters:")
print("Explicación: O número de clusters determina como se agruparán os puntos.\n"
"Un número baixo pode xerar grupos moi amplos e un número elevado pode crear grupos máis pequenos.\n"
"Elixe un número entre 2 e 10.")
while True:
try:
num_clusters = int(input("Introduce o número de clusters (entre 2 e 10): ").strip())
if 2 <= num_clusters <= 10:
break
else:
print("Por favor, introduce un valor entre 2 e 10.")
except ValueError:
print("Erro: Debes introducir un número enteiro válido.")
input("\nPreme ENTER para aplicar o algoritmo K-Means...")
# Paso 6: Aplicación do algoritmo K-Means
print(f"\n[Paso 6] Aplicando K-Means con {num_clusters} clusters.")
print("Explicación: O algoritmo K-Means asigna cada punto ó cluster cuxo centroide (a media dos puntos) se achega máis a el.\n"
"Este proceso repítese iterativamente ata que os clusters se estabilizan.")
modelo = KMeans(n_clusters=num_clusters, random_state=42)
datos_escalados['Cluster'] = modelo.fit_predict(datos_escalados)
print("\nOs clusters foron asignados a cada punto.")
input("\nPreme ENTER para ver a visualización global dos clusters...")
# Novo Paso 7: Visualización global dos clusters
print("\n-----------------------------------------------------")
print("[Paso 7] Visualización global dos clusters:")
print("Explicación: A máquina detectou relacións entre os datos e agrupounos en clusters.\n"
"Na gráfica que verás a continuación, cada cor representa un cluster. Ademais,\n"
"para cada cluster, mostramos un exemplo representativo (o punto máis próximo ó centroide).\n"
"Isto ilustra como se poden detectar patróns nun universo de datos que un ser humano podería non notar.")
print("-----------------------------------------------------\n")
# Definir unha lista de cores para os clusters (ata 10 clusters)
cores = ['blue', 'orange', 'green', 'red', 'purple', 'brown', 'pink', 'gray', 'olive', 'cyan']
# Calcular os centroides en formato DataFrame con nomes das columnas
centroides = pd.DataFrame(modelo.cluster_centers_, columns=columnas_seleccionadas)
# Para cada cluster, atopar o punto máis achegado ó seu centroide para usalo como exemplo representativo
exemplo_por_cluster = {}
for i in range(num_clusters):
# Selecciona os puntos pertencentes ó cluster i
mask = datos_escalados['Cluster'] == i
puntos_cluster = datos_escalados.loc[mask, columnas_seleccionadas]
# Se existen puntos (por precaución)
if len(puntos_cluster) > 0:
# Calcula as distancias euclidianas ó centroide
dists = np.linalg.norm(puntos_cluster.values - centroides.iloc[i].values, axis=1)
indice_min = dists.argmin()
# Obtén o índice real do punto no DataFrame (mantén o índice orixinal)
exemplo_idx = puntos_cluster.index[indice_min]
exemplo_por_cluster[i] = exemplo_idx
else:
exemplo_por_cluster[i] = None
# Visualización: Se se seleccionan 2 columnas (2D) ou 3 columnas (3D)
if len(columnas_seleccionadas) == 2:
fig, ax = plt.subplots(figsize=(10,8))
# Plot para cada cluster
for i in range(num_clusters):
mask = datos_escalados['Cluster'] == i
pontos = datos_escalados.loc[mask, columnas_seleccionadas]
cor = cores[i % len(cores)]
ax.scatter(pontos[columnas_seleccionadas[0]], pontos[columnas_seleccionadas[1]],
c=cor, label=f"Cluster {i} (cor: {cor}, ex: idx {exemplo_por_cluster[i]})", alpha=0.6)
# Ponto do centroide
ax.scatter(centroides.iloc[i, 0], centroides.iloc[i, 1],
marker='X', s=200, c=cor, edgecolor='black')
ax.set_xlabel(columnas_seleccionadas[0])
ax.set_ylabel(columnas_seleccionadas[1])
ax.set_title("Visualización Global dos Clusters (2D)")
ax.legend(loc="best", fontsize=9)
plt.grid(True)
plt.show()
elif len(columnas_seleccionadas) == 3:
fig = plt.figure(figsize=(12,10))
ax = fig.add_subplot(111, projection='3d')
for i in range(num_clusters):
mask = datos_escalados['Cluster'] == i
pontos = datos_escalados.loc[mask, columnas_seleccionadas]
cor = cores[i % len(cores)]
ax.scatter(pontos[columnas_seleccionadas[0]], pontos[columnas_seleccionadas[1]], pontos[columnas_seleccionadas[2]],
c=cor, label=f"Cluster {i} (cor: {cor}, ex: idx {exemplo_por_cluster[i]})", alpha=0.6)
# Ponto do centroide
ax.scatter(centroides.iloc[i, 0], centroides.iloc[i, 1], centroides.iloc[i, 2],
marker='X', s=200, c=cor, edgecolor='black')
ax.set_xlabel(columnas_seleccionadas[0])
ax.set_ylabel(columnas_seleccionadas[1])
ax.set_zlabel(columnas_seleccionadas[2])
ax.set_title("Visualización Global dos Clusters (3D)")
ax.legend(loc="best", fontsize=9)
plt.show()
else:
print("Visualización non soportada para este número de columnas.")
print("\n-----------------------------------------------------")
print("FIN DO PROGRAMA")
print("Observa como a máquina, empregando estatísticas e máis, pode detectar patróns e relacións entre datos\n"
"que a simple vista non se verían. Este é o poder do Big Data: abrir unha porta a novas posibilidades de\n"
"descubrimento e innovación. Grazas por participar!")
print("-----------------------------------------------------")
# Execución do programa
clustering_interactivo()