TechLead
Principiante
30 min
Guía completa

Fundamentos de Machine Learning

Aprende los fundamentos del aprendizaje automático, los tipos de aprendizaje y aplicaciones prácticas

¿Qué es el Machine Learning?

El Machine Learning (ML) es un subconjunto de la IA que permite a los computadores aprender y mejorar con la experiencia sin ser programados explícitamente. En lugar de escribir reglas específicas para cada tarea, proporcionamos datos y dejamos que el algoritmo descubra patrones y tome decisiones.

🎯 Concepto clave:

Los algoritmos de ML aprenden de datos, identifican patrones y hacen predicciones o decisiones con mínima intervención humana.

Tipos de Machine Learning

📚

Aprendizaje supervisado

Aprende a partir de datos etiquetados con resultados conocidos.

Ejemplos:

  • • Detección de spam en emails
  • • Predicción de precios de casas
  • • Clasificación de imágenes
  • • Diagnóstico médico
🔍

Aprendizaje no supervisado

Encuentra patrones en datos sin etiquetas.

Ejemplos:

  • • Segmentación de clientes
  • • Detección de anomalías
  • • Sistemas de recomendación
  • • Compresión de datos
🎮

Aprendizaje por refuerzo

Aprende por prueba y error con recompensas.

Ejemplos:

  • • Juegos (AlphaGo)
  • • Navegación de robots
  • • Autos autónomos
  • • Estrategias de trading

Flujo de trabajo en Machine Learning

1

Recolección de datos

Reúne datos relevantes de distintas fuentes

2

Preparación de datos

Limpia, normaliza y separa en sets de entrenamiento/prueba

3

Selección del modelo

Elige el algoritmo adecuado para tu problema

4

Entrenamiento

Alimenta el modelo con datos de entrenamiento para aprender patrones

5

Evaluación

Prueba el modelo con datos no vistos para medir precisión

6

Despliegue

Lleva el modelo a producción para uso real

Aprendizaje supervisado: regresión lineal

Implementemos un modelo de regresión lineal simple para predecir precios de casas según tamaño:

// Simple Linear Regression Implementation
class LinearRegression {
  constructor(learningRate = 0.01, iterations = 1000) {
    this.learningRate = learningRate;
    this.iterations = iterations;
    this.weight = 0;
    this.bias = 0;
    this.history = { loss: [], weight: [], bias: [] };
  }

  // Training the model using gradient descent
  fit(X, y) {
    const n = X.length;
    
    for (let i = 0; i < this.iterations; i++) {
      // Forward pass: make predictions
      const predictions = X.map(x => this.weight * x + this.bias);
      
      // Calculate loss (Mean Squared Error)
      const loss = predictions.reduce((sum, pred, idx) => {
        return sum + Math.pow(pred - y[idx], 2);
      }, 0) / n;
      
      // Calculate gradients
      let dWeight = 0;
      let dBias = 0;
      
      for (let j = 0; j < n; j++) {
        const error = predictions[j] - y[j];
        dWeight += (2 / n) * error * X[j];
        dBias += (2 / n) * error;
      }
      
      // Update parameters (gradient descent)
      this.weight -= this.learningRate * dWeight;
      this.bias -= this.learningRate * dBias;
      
      // Store history for visualization
      if (i % 100 === 0) {
        this.history.loss.push(loss);
        this.history.weight.push(this.weight);
        this.history.bias.push(this.bias);
        console.log(`Iteration ${i}: Loss = ${loss.toFixed(4)}`);
      }
    }
  }

  // Make predictions
  predict(X) {
    return Array.isArray(X) 
      ? X.map(x => this.weight * x + this.bias)
      : this.weight * X + this.bias;
  }
}

// Example: Predicting house prices
// X = house size in square feet
// y = price in thousands of dollars
const houseSizes = [1000, 1500, 2000, 2500, 3000, 3500, 4000];
const housePrices = [150, 200, 250, 300, 350, 400, 450];

console.log("Training Linear Regression Model...");
const model = new LinearRegression(0.0001, 1000);
model.fit(houseSizes, housePrices);

console.log(`\nModel trained!`);
console.log(`Weight (slope): ${model.weight.toFixed(4)}`);
console.log(`Bias (intercept): ${model.bias.toFixed(4)}`);

// Make predictions
console.log("\nPredictions:");
const testSizes = [1200, 2800, 3800];
const predictions = model.predict(testSizes);
testSizes.forEach((size, i) => {
  console.log(`House ${size} sqft → $${predictions[i].toFixed(2)}k`);
});

// Output:
// House 1200 sqft → $170.00k
// House 2800 sqft → $320.00k
// House 3800 sqft → $420.00k

🔍 Cómo funciona:

  • Paso hacia adelante: Calcula predicciones usando peso y sesgo actuales
  • Cálculo de pérdida: Mide qué tan equivocadas son las predicciones (MSE)
  • Descenso de gradiente: Ajusta peso y sesgo para reducir la pérdida
  • Iteración: Repite hasta que el modelo converge

Aprendizaje no supervisado: clustering K-Means

Implementemos K-Means para agrupar puntos de datos similares:

// K-Means Clustering Implementation
class KMeans {
  constructor(k = 3, maxIterations = 100) {
    this.k = k;
    this.maxIterations = maxIterations;
    this.centroids = [];
    this.labels = [];
  }

  // Calculate Euclidean distance
  distance(point1, point2) {
    return Math.sqrt(
      point1.reduce((sum, val, i) => 
        sum + Math.pow(val - point2[i], 2), 0
      )
    );
  }

  // Initialize centroids randomly
  initializeCentroids(data) {
    const indices = new Set();
    while (indices.size < this.k) {
      indices.add(Math.floor(Math.random() * data.length));
    }
    this.centroids = Array.from(indices).map(i => [...data[i]]);
  }

  // Assign each point to nearest centroid
  assignClusters(data) {
    this.labels = data.map(point => {
      const distances = this.centroids.map(centroid => 
        this.distance(point, centroid)
      );
      return distances.indexOf(Math.min(...distances));
    });
  }

  // Update centroids based on cluster means
  updateCentroids(data) {
    const newCentroids = Array(this.k).fill(null).map(() => []);
    
    // Sum all points in each cluster
    data.forEach((point, i) => {
      const cluster = this.labels[i];
      if (!newCentroids[cluster].length) {
        newCentroids[cluster] = [...point];
      } else {
        point.forEach((val, j) => {
          newCentroids[cluster][j] += val;
        });
      }
    });
    
    // Calculate means
    const counts = Array(this.k).fill(0);
    this.labels.forEach(label => counts[label]++);
    
    this.centroids = newCentroids.map((centroid, i) => 
      centroid.map(val => val / counts[i])
    );
  }

  // Train the model
  fit(data) {
    this.initializeCentroids(data);
    
    for (let i = 0; i < this.maxIterations; i++) {
      const oldLabels = [...this.labels];
      
      this.assignClusters(data);
      this.updateCentroids(data);
      
      // Check for convergence
      if (JSON.stringify(oldLabels) === JSON.stringify(this.labels)) {
        console.log(`Converged at iteration ${i}`);
        break;
      }
    }
  }

  // Predict cluster for new data
  predict(point) {
    const distances = this.centroids.map(centroid => 
      this.distance(point, centroid)
    );
    return distances.indexOf(Math.min(...distances));
  }
}

// Example: Customer segmentation
const customers = [
  [25, 50000],  // [age, income]
  [30, 60000],
  [35, 70000],
  [45, 90000],
  [50, 100000],
  [22, 40000],
  [28, 55000],
  [55, 120000],
  [60, 150000],
  [40, 80000]
];

console.log("Clustering customers into 3 segments...");
const kmeans = new KMeans(3);
kmeans.fit(customers);

console.log("\nCustomer Segments:");
customers.forEach((customer, i) => {
  const segment = kmeans.labels[i];
  console.log(`Customer ${i + 1} [Age: ${customer[0]}, Income: $${customer[1]}] → Segment ${segment}`);
});

console.log("\nCentroid positions:");
kmeans.centroids.forEach((centroid, i) => {
  console.log(`Segment ${i}: Age ${centroid[0].toFixed(1)}, Income $${centroid[1].toFixed(0)}`);
});

🎯 Conceptos clave:

  • Centroides: Puntos centrales de cada cluster
  • Asignación: Cada punto pertenece al centroide más cercano
  • Actualización: Mueve los centroides a la media de los puntos asignados
  • Convergencia: Detiene cuando los clusters ya no cambian

Métricas de evaluación del modelo

Métricas de clasificación

// Confusion Matrix & Metrics
function evaluateClassifier(yTrue, yPred) {
  let tp = 0, fp = 0, tn = 0, fn = 0;
  
  for (let i = 0; i < yTrue.length; i++) {
    if (yTrue[i] === 1 && yPred[i] === 1) tp++;
    else if (yTrue[i] === 0 && yPred[i] === 1) fp++;
    else if (yTrue[i] === 0 && yPred[i] === 0) tn++;
    else fn++;
  }
  
  const accuracy = (tp + tn) / (tp + tn + fp + fn);
  const precision = tp / (tp + fp);
  const recall = tp / (tp + fn);
  const f1Score = 2 * (precision * recall) / (precision + recall);
  
  return { accuracy, precision, recall, f1Score };
}

// Example
const actual = [1, 0, 1, 1, 0, 1, 0, 0];
const predicted = [1, 0, 1, 0, 0, 1, 1, 0];
const metrics = evaluateClassifier(actual, predicted);

console.log("Accuracy:", metrics.accuracy.toFixed(3));
console.log("Precision:", metrics.precision.toFixed(3));
console.log("Recall:", metrics.recall.toFixed(3));
console.log("F1 Score:", metrics.f1Score.toFixed(3));

Métricas de regresión

// Regression Evaluation
function evaluateRegression(yTrue, yPred) {
  const n = yTrue.length;
  
  // Mean Squared Error
  const mse = yTrue.reduce((sum, val, i) => 
    sum + Math.pow(val - yPred[i], 2), 0) / n;
  
  // Root Mean Squared Error
  const rmse = Math.sqrt(mse);
  
  // Mean Absolute Error
  const mae = yTrue.reduce((sum, val, i) => 
    sum + Math.abs(val - yPred[i]), 0) / n;
  
  // R² Score
  const yMean = yTrue.reduce((a, b) => a + b) / n;
  const ssTot = yTrue.reduce((sum, val) => 
    sum + Math.pow(val - yMean, 2), 0);
  const ssRes = yTrue.reduce((sum, val, i) => 
    sum + Math.pow(val - yPred[i], 2), 0);
  const r2 = 1 - (ssRes / ssTot);
  
  return { mse, rmse, mae, r2 };
}

// Example
const actualPrices = [100, 200, 300, 400];
const predictedPrices = [110, 190, 310, 390];
const metrics = evaluateRegression(actualPrices, predictedPrices);

console.log("MSE:", metrics.mse.toFixed(2));
console.log("RMSE:", metrics.rmse.toFixed(2));
console.log("MAE:", metrics.mae.toFixed(2));
console.log("R²:", metrics.r2.toFixed(3));

⚠️ Errores comunes en ML

  • Overfitting: El modelo aprende demasiado bien el entrenamiento y falla en datos nuevos
  • Underfitting: El modelo es demasiado simple para capturar patrones
  • Data leakage: El entrenamiento incluye accidentalmente información del set de prueba
  • Sesgo en los datos: Los datos no representan la distribución real
  • Selección de features: Usar variables irrelevantes o omitir importantes

📚 Conclusiones clave

  • El Machine Learning aprende de datos sin programación explícita
  • Tres tipos principales: Supervisado, no supervisado y por refuerzo
  • La regresión lineal es un algoritmo supervisado fundamental
  • K-Means es un algoritmo de clustering no supervisado popular
  • Evaluar el modelo es crucial para medir rendimiento
  • Evita el overfitting con divisiones train/test y validación