DEV Community

Jesus Oviedo Riquelme
Jesus Oviedo Riquelme

Posted on

MLZC25-07. Reflexión sobre la Tarea de la Semana 1: Mi Primera Aventura en Machine Learning

🎯 El Momento de la Verdad: Aplicar Todo lo Aprendido

Después de una semana intensa explorando los fundamentos del Machine Learning, llegó el momento de la verdad: la tarea práctica. Es el momento donde la teoría se encuentra con la realidad, donde los conceptos abstractos se convierten en código ejecutable, y donde descubres si realmente entendiste lo que aprendiste.

📋 Sobre la Tarea de la Semana 1

La tarea oficial del Machine Learning Zoomcamp 2025 nos presenta un desafío práctico que cubre los fundamentos que exploramos durante la semana:

Dataset: Car Fuel Efficiency

  • 9,704 registros de automóviles con 11 características
  • Datos del mundo real con valores faltantes y inconsistencias
  • Variables: motor, cilindros, caballos de fuerza, peso, aceleración, año, origen, tipo de combustible, tracción, puertas, eficiencia de combustible

7 Preguntas Específicas:

  1. Versión de Pandas - Verificar herramientas
  2. Conteo de registros - Entender el tamaño del dataset
  3. Tipos de combustible únicos - Exploración de variables categóricas
  4. Valores faltantes - Análisis de calidad de datos
  5. Máxima eficiencia de combustible - Estadísticas descriptivas
  6. Mediana de caballos de fuerza - Manejo de valores faltantes
  7. Suma de pesos - Álgebra lineal básica

Lo que la Tarea Nos Enseña:

  • Pensamiento crítico: No hay respuestas únicas, hay decisiones que debes justificar
  • Iteración: Los primeros intentos raramente son perfectos
  • Documentación: Tu futuro yo te agradecerá las notas detalladas
  • Problema real: Los datos del mundo real nunca son perfectos

🚀 Mi Proceso de Resolución

Paso 1: El Primer Vistazo (y el Pánico Inicial)

# El momento de cargar los datos por primera vez
import pandas as pd
import numpy as np

# Descargar el dataset de automóviles
!wget https://raw.githubusercontent.com/alexeygrigorev/datasets/master/car_fuel_efficiency.csv

# Cargar los datos
df_car = pd.read_csv('car_fuel_efficiency.csv')
print(f"Forma del dataset: {df_car.shape}")
print(f"Columnas: {df_car.columns.tolist()}")
print(f"Tipos de datos:\n{df_car.dtypes}")

# Y la inevitable sensación de: "¿Y ahora qué hago?"
Enter fullscreen mode Exit fullscreen mode

Reflexión: Es normal sentir abrumación al ver datos por primera vez. La clave es no correr, sino explorar sistemáticamente. Con 9,704 registros y 11 columnas, el dataset de automóviles es perfecto para practicar.

Paso 2: Respondiendo las Preguntas Específicas

Aplicando lo aprendido en los posts anteriores, abordé cada pregunta sistemáticamente:

# Q1: Versión de Pandas
print(f"Versión de pandas: {pd.__version__}")

# Q2: Conteo de registros
print(f"Número de registros: {len(df_car)}")

# Q3: Tipos de combustible únicos
tipos_combustible = df_car['fuel_type'].unique()
print(f"Tipos de combustible únicos: {tipos_combustible}")
print(f"Número de tipos únicos: {len(tipos_combustible)}")

# Q4: Valores faltantes por columna
valores_faltantes = df_car.isnull().sum()
columnas_con_faltantes = valores_faltantes[valores_faltantes > 0]
print(f"Columnas con valores faltantes: {len(columnas_con_faltantes)}")

# Q5: Máxima eficiencia de combustible (vehículos asiáticos)
df_asia = df_car[df_car['origin'] == 'Asia']
max_eficiencia = df_asia['fuel_efficiency_mpg'].max()
print(f"Máxima eficiencia de combustible: {max_eficiencia:.3f}")

# Q6: Mediana de caballos de fuerza
mediana_hp = df_car['horsepower'].median()
print(f"Mediana de caballos de fuerza: {mediana_hp}")

# Q7: Suma de pesos (álgebra lineal)
# Seleccionar 7 filas de vehículos asiáticos
X = df_asia[['vehicle_weight', 'model_year']].head(7).to_numpy()
y = np.array([1100, 1300, 800, 900, 1000, 1100, 1200])
w = np.linalg.inv(X.T @ X) @ X.T @ y
suma_pesos = np.sum(w)
print(f"Suma de pesos: {suma_pesos:.6f}")
Enter fullscreen mode Exit fullscreen mode

Lecciones aprendidas:

  • Cada pregunta tiene un propósito: Desde verificar herramientas hasta álgebra lineal
  • Los datos reales son imperfectos: 2,622 valores faltantes en total
  • La práctica hace la diferencia: De teoría a código ejecutable

Paso 3: Desafíos Específicos de la Tarea

La tarea presentó desafíos específicos que me forzaron a pensar críticamente:

# Desafío 1: Manejo de valores faltantes en horsepower
print("=== DESAFÍO: VALORES FALTANTES ===")
print(f"Valores faltantes en horsepower: {df_car['horsepower'].isnull().sum()}")

# Decisión: Usar la moda (152) para imputar
moda_hp = df_car['horsepower'].mode()[0]
df_car_fillna = df_car.fillna({'horsepower': moda_hp})

# Verificar el cambio en la mediana
mediana_antes = df_car['horsepower'].median()
mediana_despues = df_car_fillna['horsepower'].median()
print(f"Mediana antes: {mediana_antes}")
print(f"Mediana después: {mediana_despues}")
print(f"¿Cambió? {mediana_antes != mediana_despues}")

# Desafío 2: Álgebra lineal para la suma de pesos
print("\n=== DESAFÍO: ÁLGEBRA LINEAL ===")
# Seleccionar 7 vehículos asiáticos
df_asia = df_car[df_car['origin'] == 'Asia']
X = df_asia[['vehicle_weight', 'model_year']].head(7).to_numpy()
y = np.array([1100, 1300, 800, 900, 1000, 1100, 1200])

# Calcular pesos usando la fórmula normal
w = np.linalg.inv(X.T @ X) @ X.T @ y
suma_pesos = np.sum(w)
print(f"Suma de pesos: {suma_pesos:.6f}")

# Desafío 3: Filtrado por origen
print("\n=== DESAFÍO: FILTRADO ESPECÍFICO ===")
df_asia = df_car[df_car['origin'] == 'Asia']
max_eficiencia_asia = df_asia['fuel_efficiency_mpg'].max()
print(f"Máxima eficiencia en vehículos asiáticos: {max_eficiencia_asia:.3f}")
Enter fullscreen mode Exit fullscreen mode

Decisiones importantes que tuve que tomar:

  • Imputación de horsepower: Usar moda (152) vs mediana (149)
  • Filtrado por origen: ¿Por qué solo vehículos asiáticos?
  • Álgebra lineal: Entender la fórmula normal vs implementación manual

Paso 4: La Matemática Detrás de las Respuestas

Aunque la tarea no incluye modelado tradicional, sí incluye conceptos matemáticos fundamentales:

# Análisis de las respuestas obtenidas
print("=== ANÁLISIS DE RESULTADOS ===")

# Q1: Herramientas
print(f"Pandas version: {pd.__version__}")

# Q2: Tamaño del dataset
print(f"Total de registros: {len(df_car)}")

# Q3: Variables categóricas
tipos_combustible = df_car['fuel_type'].unique()
print(f"Tipos de combustible: {tipos_combustible}")
print(f"Distribución: {df_car['fuel_type'].value_counts().to_dict()}")

# Q4: Calidad de datos
valores_faltantes = df_car.isnull().sum()
columnas_problematicas = valores_faltantes[valores_faltantes > 0]
print(f"Columnas con valores faltantes: {len(columnas_problematicas)}")
print(f"Total de valores faltantes: {valores_faltantes.sum()}")

# Q5: Estadísticas por región
df_asia = df_car[df_car['origin'] == 'Asia']
print(f"Vehículos asiáticos: {len(df_asia)}")
print(f"Máxima eficiencia asiática: {df_asia['fuel_efficiency_mpg'].max():.3f}")

# Q6: Impacto de la imputación
mediana_original = df_car['horsepower'].median()
print(f"Mediana original: {mediana_original}")
print(f"Moda de horsepower: {df_car['horsepower'].mode()[0]}")

# Q7: Álgebra lineal aplicada
X = df_asia[['vehicle_weight', 'model_year']].head(7).to_numpy()
y = np.array([1100, 1300, 800, 900, 1000, 1100, 1200])
w = np.linalg.inv(X.T @ X) @ X.T @ y
print(f"Pesos calculados: {w}")
print(f"Suma de pesos: {np.sum(w):.6f}")
Enter fullscreen mode Exit fullscreen mode

Paso 5: La Interpretación de los Resultados

Cada respuesta de la tarea me enseñó algo específico sobre el dataset y las técnicas:

def interpretar_resultados_tarea():
    """Interpretación específica de los resultados de la tarea"""

    print("=== INTERPRETACIÓN DE RESULTADOS DE LA TAREA ===")

    # 1. Análisis del dataset
    print("📊 ANÁLISIS DEL DATASET:")
    print(f"- Tamaño: {len(df_car)} registros, {len(df_car.columns)} columnas")
    print(f"- Período: {df_car['model_year'].min()}-{df_car['model_year'].max()}")
    print(f"- Orígenes: {df_car['origin'].value_counts().to_dict()}")
    print(f"- Combustibles: {df_car['fuel_type'].value_counts().to_dict()}")

    # 2. Calidad de datos
    print("\n🔍 CALIDAD DE DATOS:")
    valores_faltantes = df_car.isnull().sum()
    print(f"- Columnas con faltantes: {len(valores_faltantes[valores_faltantes > 0])}")
    print(f"- Total de faltantes: {valores_faltantes.sum()}")
    print(f"- Porcentaje de faltantes: {(valores_faltantes.sum() / (len(df_car) * len(df_car.columns)) * 100):.2f}%")

    # 3. Insights específicos
    print("\n💡 INSIGHTS ESPECÍFICOS:")

    # Eficiencia por origen
    eficiencia_por_origen = df_car.groupby('origin')['fuel_efficiency_mpg'].agg(['mean', 'max'])
    print("Eficiencia por origen:")
    for origen in eficiencia_por_origen.index:
        print(f"  {origen}: Media={eficiencia_por_origen.loc[origen, 'mean']:.2f}, Max={eficiencia_por_origen.loc[origen, 'max']:.2f}")

    # Impacto de la imputación
    print(f"\nImputación de horsepower:")
    print(f"  Mediana original: {df_car['horsepower'].median()}")
    print(f"  Moda: {df_car['horsepower'].mode()[0]}")
    print(f"  ¿Cambió la mediana? {df_car['horsepower'].median() != 152}")

    # 4. Lecciones aprendidas
    print("\n🎓 LECCIONES APRENDIDAS:")
    print("- Los datos reales siempre tienen imperfecciones")
    print("- La imputación puede cambiar las estadísticas")
    print("- El filtrado por subgrupos revela patrones interesantes")
    print("- La álgebra lineal es fundamental para ML")

interpretar_resultados_tarea()
Enter fullscreen mode Exit fullscreen mode

💡 Lecciones Aprendidas

1. La Teoría vs. La Práctica

Lo que pensé que pasaría:

  • Cargar datos → Responder preguntas → ¡Listo!

Lo que realmente pasó:

  • Cargar datos → Explorar → Encontrar valores faltantes → Decidir cómo imputar → Verificar impacto → Filtrar por subgrupos → Aplicar álgebra lineal → Interpretar resultados → ¡Listo!

Lección: Cada pregunta simple esconde decisiones complejas que requieren pensamiento crítico.

2. Las Decisiones Importan

Cada pregunta de la tarea requirió decisiones justificadas:

  • Q6: ¿Usar moda (152) o mediana (149) para imputar horsepower?
  • Q5: ¿Por qué filtrar solo vehículos asiáticos?
  • Q7: ¿Entender la fórmula normal o implementar manualmente?
  • Q4: ¿Cómo contar columnas con valores faltantes?

Lección: Cada decisión tiene consecuencias que afectan los resultados finales.

3. La Documentación es Crucial

# ❌ Código sin documentación
df_car['horsepower'].fillna(152)

# ✅ Código documentado
# Q6: Decisión de usar moda (152) en lugar de mediana (149) para imputar horsepower
# porque la moda es más representativa de la distribución de datos
moda_hp = df_car['horsepower'].mode()[0]  # 152
df_car_fillna = df_car.fillna({'horsepower': moda_hp})

# Verificar el impacto de la imputación
mediana_antes = df_car['horsepower'].median()  # 149.0
mediana_despues = df_car_fillna['horsepower'].median()  # 152.0
print(f"Mediana cambió: {mediana_antes != mediana_despues}")

# Q7: Implementación de la fórmula normal para regresión lineal
# w = (X^T X)^(-1) X^T y
X = df_asia[['vehicle_weight', 'model_year']].head(7).to_numpy()
y = np.array([1100, 1300, 800, 900, 1000, 1100, 1200])
w = np.linalg.inv(X.T @ X) @ X.T @ y
Enter fullscreen mode Exit fullscreen mode

Lección: Documentar decisiones técnicas ayuda a entender el razonamiento posterior.

4. La Iteración es Normal

Mi primera respuesta a Q6 fue incorrecta. ¡Usé la mediana en lugar de la moda! Pero eso está bien porque:

  • Me ayudó a entender la diferencia entre mediana y moda
  • Me forzó a verificar el impacto de la imputación
  • Me enseñó a ser más cuidadoso con las instrucciones

Lección: Los errores son oportunidades de aprendizaje. Iterar es parte del proceso.

5. El Contexto Importa

Las decisiones de la tarea dependían del contexto específico:

  • Q5: Filtrar por origen asiático porque la pregunta lo especificaba
  • Q6: Usar moda para imputar porque era el valor más frecuente
  • Q7: Aplicar álgebra lineal porque era parte del aprendizaje fundamental

Lección: Cada pregunta tiene un contexto específico que guía la respuesta correcta.

🎯 Reflexiones Profundas

¿Qué me sorprendió más?

La complejidad detrás de preguntas aparentemente simples. "¿Cuál es la mediana de horsepower?" parece directo, pero requiere decidir cómo manejar los valores faltantes primero.

¿Qué me frustró más?

La pregunta Q7 sobre álgebra lineal. No entendía por qué necesitaba calcular la suma de pesos, pero después de implementarlo, comprendí la importancia de la matemática fundamental.

¿Qué me emocionó más?

Ver cómo cada pregunta conectaba con conceptos de los posts anteriores. La tarea realmente aplicaba todo lo que habíamos aprendido sobre EDA, preprocesamiento y análisis de datos.

¿Qué cambiaría si pudiera empezar de nuevo?

  1. Leer cada pregunta más cuidadosamente
  2. Verificar mis respuestas antes de continuar
  3. Documentar mi razonamiento para cada decisión
  4. Entender mejor la fórmula normal antes de implementarla

🔍 Análisis de Mis Errores

Error 1: No leer cuidadosamente las instrucciones

# ❌ Lo que hice mal (Q6)
mediana_hp = df_car['horsepower'].median()  # 149.0
print(f"Mediana: {mediana_hp}")

# ✅ Lo que debería haber hecho
# La pregunta pedía la mediana DESPUÉS de imputar con la moda
moda_hp = df_car['horsepower'].mode()[0]  # 152
df_car_fillna = df_car.fillna({'horsepower': moda_hp})
mediana_despues = df_car_fillna['horsepower'].median()  # 152.0
print(f"Mediana después de imputar: {mediana_despues}")
Enter fullscreen mode Exit fullscreen mode

Error 2: No verificar el impacto de la imputación

# ❌ Lo que hice mal
df_car['horsepower'].fillna(152, inplace=True)
# No verifiqué si esto cambió la mediana

# ✅ Lo que debería haber hecho
mediana_antes = df_car['horsepower'].median()
df_car['horsepower'].fillna(152, inplace=True)
mediana_despues = df_car['horsepower'].median()
print(f"¿Cambió la mediana? {mediana_antes != mediana_despues}")
Enter fullscreen mode Exit fullscreen mode

Error 3: No entender la fórmula normal

# ❌ Lo que hice mal (Q7)
# Intenté implementar la fórmula sin entenderla

# ✅ Lo que debería haber hecho
# Entender que w = (X^T X)^(-1) X^T y es la fórmula normal
# para regresión lineal por mínimos cuadrados
X = df_asia[['vehicle_weight', 'model_year']].head(7).to_numpy()
y = np.array([1100, 1300, 800, 900, 1000, 1100, 1200])
w = np.linalg.inv(X.T @ X) @ X.T @ y
print(f"Pesos calculados: {w}")
Enter fullscreen mode Exit fullscreen mode

🚀 Lo que Aprendí sobre Machine Learning

1. Los fundamentos importan

Antes de algoritmos complejos, necesitas entender estadísticas básicas, álgebra lineal y manipulación de datos.

2. Los datos reales son imperfectos

9,704 registros con 2,622 valores faltantes me enseñaron que la limpieza de datos es crucial.

3. Cada decisión tiene consecuencias

Usar moda vs mediana para imputar cambió completamente la respuesta. Las decisiones importan.

4. La matemática es fundamental

La fórmula normal w = (X^T X)^(-1) X^T y no es solo teoría, es la base de la regresión lineal.

5. El contexto guía las decisiones

Cada pregunta tenía un contexto específico que determinaba la respuesta correcta.

🎯 Mi Plan para las Próximas Semanas

Semana 2: Regresión

  • Aplicar la fórmula normal que aprendí en Q7
  • Explorar diferentes algoritmos de regresión
  • Mejorar mi proceso de validación de datos

Semana 3: Clasificación

  • Adaptar las técnicas de EDA para problemas de clasificación
  • Explorar métricas específicas de clasificación
  • Entender el trade-off entre precisión y recall

Semana 4: Árboles y Ensemble

  • Comparar con la regresión lineal que implementé
  • Entender cuándo usar cada algoritmo
  • Explorar técnicas de ensemble

💭 Preguntas que me quedan

  1. ¿Por qué la fórmula normal es tan importante en ML?
  2. ¿Qué otras técnicas de imputación debería conocer?
  3. ¿Cómo puedo mejorar mi proceso de EDA?
  4. ¿Qué métricas adicionales debería considerar para datos reales?
  5. ¿Cómo puedo hacer mi código más reproducible y documentado?

🔗 Conclusión

La tarea de la Semana 1 fue mucho más que responder 7 preguntas. Fue mi primera experiencia real con los fundamentos de Machine Learning:

  • Q1-Q2 → Verificar herramientas y entender el dataset
  • Q3-Q4 → Explorar variables categóricas y calidad de datos
  • Q5-Q6 → Aplicar estadísticas descriptivas y manejo de valores faltantes
  • Q7 → Implementar álgebra lineal fundamental

Cada pregunta me enseñó algo nuevo, cada error me hizo más sabio, y cada respuesta me acercó más a entender lo que realmente significa hacer Machine Learning.

🎯 Reflexión Final

¿Qué significa para mí haber completado esta tarea?

Significa que ya no soy solo un espectador del Machine Learning. Soy un participante activo. Puedo cargar datos, explorarlos, manejar valores faltantes, aplicar estadísticas, y implementar álgebra lineal.

Pero más importante, significa que entiendo que el Machine Learning no es solo código y algoritmos. Es pensamiento crítico, toma de decisiones, iteración, y aprendizaje constante. Cada pregunta simple esconde complejidad que requiere comprensión profunda.

💡 Para los que Vienen Después

Si estás a punto de empezar tu primera tarea de Machine Learning:

  1. Lee cada pregunta cuidadosamente - Los detalles importan
  2. Documenta tu razonamiento - Explica por qué tomas cada decisión
  3. Verifica tus respuestas - No asumas que la primera respuesta es correcta
  4. Pregúntate por qué - Cada decisión debe estar justificada
  5. No tengas miedo de fallar - Los errores son oportunidades de aprendizaje

🤝 Última Reflexión

¿Estoy listo para la Semana 2?

Sí, pero con humildad. Sé que tengo mucho que aprender, pero también sé que tengo las bases para seguir aprendiendo. La Semana 1 me dio los fundamentos, la Semana 2 me dará la oportunidad de aplicar la fórmula normal que aprendí en Q7 a problemas de regresión más complejos.

El viaje apenas comienza, y estoy emocionado por lo que viene.


"El Machine Learning no es solo sobre algoritmos, es sobre resolver problemas reales con datos reales. Y eso es exactamente lo que hicimos esta semana con 7 preguntas aparentemente simples que me enseñaron lecciones profundas."

¿Qué tal tu experiencia con la tarea? ¿Qué lecciones aprendiste? ¿Qué te frustró más y qué te emocionó más?

Top comments (0)