diciembre 21, 2025
16 min de lectura

Preguntas de Entrevista para Data Scientist Senior sobre ML, Producto y MLOps

interview
career-advice
job-search
Preguntas de Entrevista para Data Scientist Senior sobre ML, Producto y MLOps
Milad Bonakdar

Milad Bonakdar

Autor

Prepárate para entrevistas senior con preguntas prácticas sobre tradeoffs de ML, ingeniería de características, despliegue, monitoreo, pruebas A/B y decisiones de negocio.


Introducción

Para una entrevista de data scientist senior, prepárate para explicar no solo cómo funcionan los modelos, sino cómo los eliges, los llevas a producción, los monitoreas y los explicas. Las respuestas sólidas conectan tradeoffs estadísticos con métricas de producto, calidad de datos, restricciones de despliegue y decisiones de stakeholders.

Usa esta guía para practicar los temas que suelen separar a candidatos senior de perfiles intermedios: sesgo y varianza, diseño de features, datos desbalanceados, monitoreo de modelos, pruebas A/B, MLOps y fundamentos de deep learning. Al responder, añade un ejemplo breve de proyecto, el riesgo que controlaste y la métrica que seguirías después del lanzamiento.


Aprendizaje automático avanzado (6 preguntas)

1. Explique el equilibrio entre sesgo y varianza.

Respuesta: El equilibrio entre sesgo y varianza describe la relación entre la complejidad del modelo y el error de predicción.

  • Sesgo: Error derivado de simplificar en exceso las suposiciones (ajuste insuficiente)
  • Varianza: Error derivado de la sensibilidad a las fluctuaciones de los datos de entrenamiento (sobreajuste)
  • Equilibrio: Disminuir el sesgo aumenta la varianza y viceversa
  • Objetivo: Encontrar el equilibrio óptimo que minimice el error total
Loading diagram...
import numpy as np
from sklearn.model_selection import learning_curve
from sklearn.tree import DecisionTreeRegressor
import matplotlib.pyplot as plt

# Generar datos
X = np.random.rand(100, 1) * 10
y = 2 * X + 3 + np.random.randn(100, 1) * 2

# Modelo de alto sesgo (max_depth=1)
high_bias = DecisionTreeRegressor(max_depth=1)

# Modelo de alta varianza (max_depth=20)
high_variance = DecisionTreeRegressor(max_depth=20)

# Modelo óptimo (max_depth=3)
optimal = DecisionTreeRegressor(max_depth=3)

# Las curvas de aprendizaje muestran el equilibrio entre sesgo y varianza
train_sizes, train_scores, val_scores = learning_curve(
    optimal, X, y.ravel(), cv=5, train_sizes=np.linspace(0.1, 1.0, 10)
)

print(f"Puntuación de entrenamiento: {train_scores.mean():.2f}")
print(f"Puntuación de validación: {val_scores.mean():.2f}")

Rareza: Muy común Dificultad: Difícil


2. ¿Qué es la regularización y explique la regularización L1 frente a L2?

Respuesta: La regularización añade un término de penalización a la función de pérdida para evitar el sobreajuste.

  • L1 (Lazo):
    • Penalización: Suma de los valores absolutos de los coeficientes
    • Efecto: Modelos dispersos (algunos coeficientes se convierten exactamente en 0)
    • Uso: Selección de características
  • L2 (Ridge):
    • Penalización: Suma de los coeficientes al cuadrado
    • Efecto: Reduce los coeficientes hacia 0 (pero no exactamente 0)
    • Uso: Cuando todas las características son potencialmente relevantes
  • Elastic Net: Combina L1 y L2
from sklearn.linear_model import Lasso, Ridge, ElasticNet
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
import numpy as np

# Generar datos con muchas características
X, y = make_regression(n_samples=100, n_features=20, n_informative=10, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

# Regularización L1 (Lazo)
lasso = Lasso(alpha=1.0)
lasso.fit(X_train, y_train)
print(f"Coeficientes de Lazo: {np.sum(lasso.coef_ != 0)} no cero de {len(lasso.coef_)}")

# Regularización L2 (Ridge)
ridge = Ridge(alpha=1.0)
ridge.fit(X_train, y_train)
print(f"Coeficientes de Ridge: {np.sum(ridge.coef_ != 0)} no cero de {len(ridge.coef_)}")

# Elastic Net (L1 + L2)
elastic = ElasticNet(alpha=1.0, l1_ratio=0.5)
elastic.fit(X_train, y_train)

print(f"\nPuntuación de Lazo: {lasso.score(X_test, y_test):.3f}")
print(f"Puntuación de Ridge: {ridge.score(X_test, y_test):.3f}")
print(f"Puntuación de Elastic Net: {elastic.score(X_test, y_test):.3f}")

Rareza: Muy común Dificultad: Media


3. Explique los métodos de conjunto: Bagging vs Boosting.

Respuesta: Los métodos de conjunto combinan múltiples modelos para mejorar el rendimiento.

  • Bagging (Bootstrap Aggregating):
    • Entrenar modelos en paralelo en subconjuntos aleatorios
    • Reduce la varianza
    • Ejemplo: Bosque aleatorio
  • Boosting:
    • Entrenar modelos secuencialmente, cada uno corrigiendo errores anteriores
    • Reduce el sesgo
    • Ejemplos: AdaBoost, Gradient Boosting, XGBoost
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split, cross_val_score

# Cargar datos
data = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(
    data.data, data.target, test_size=0.3, random_state=42
)

# Bagging - Bosque aleatorio
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X_train, y_train)
rf_score = rf.score(X_test, y_test)

# Boosting - Gradient Boosting
gb = GradientBoostingClassifier(n_estimators=100, random_state=42)
gb.fit(X_train, y_train)
gb_score = gb.score(X_test, y_test)

print(f"Precisión de Bosque Aleatorio (Bagging): {rf_score:.3f}")
print(f"Precisión de Gradient Boosting: {gb_score:.3f}")

# Validación cruzada
rf_cv = cross_val_score(rf, data.data, data.target, cv=5)
gb_cv = cross_val_score(gb, data.data, data.target, cv=5)

print(f"\nPuntuaciones de CV de RF: {rf_cv.mean():.3f} (+/- {rf_cv.std():.3f})")
print(f"Puntuaciones de CV de GB: {gb_cv.mean():.3f} (+/- {gb_cv.std():.3f})")

Rareza: Muy común Dificultad: Difícil


4. ¿Qué es la validación cruzada y por qué k-fold es mejor que la división de entrenamiento-prueba?

Respuesta: La validación cruzada evalúa el rendimiento del modelo de forma más robusta que una única división de entrenamiento-prueba.

  • K-Fold CV:
    • Divide los datos en k pliegues
    • Entrena k veces, cada vez utilizando un pliegue diferente como validación
    • Promedia los resultados
  • Beneficios:
    • Estimación del rendimiento más fiable
    • Utiliza todos los datos tanto para el entrenamiento como para la validación
    • Reduce la varianza en la estimación del rendimiento
  • Variaciones: K-Fold estratificado, Leave-One-Out, División de series temporales
from sklearn.model_selection import cross_val_score, KFold, StratifiedKFold
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris

data = load_iris()
X, y = data.data, data.target

model = LogisticRegression(max_iter=200)

# K-Fold estándar
kfold = KFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, X, y, cv=kfold)
print(f"Puntuaciones de CV de K-Fold: {scores}")
print(f"Media: {scores.mean():.3f} (+/- {scores.std():.3f})")

# K-Fold estratificado (conserva la distribución de clases)
stratified_kfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
stratified_scores = cross_val_score(model, X, y, cv=stratified_kfold)
print(f"\nPuntuaciones de K-Fold estratificado: {stratified_scores}")
print(f"Media: {stratified_scores.mean():.3f} (+/- {stratified_scores.std():.3f})")

# Validación cruzada personalizada
from sklearn.model_selection import cross_validate

cv_results = cross_validate(
    model, X, y, cv=5,
    scoring=['accuracy', 'precision_macro', 'recall_macro'],
    return_train_score=True
)

print(f"\nPrecisión de la prueba: {cv_results['test_accuracy'].mean():.3f}")
print(f"Precisión de la prueba: {cv_results['test_precision_macro'].mean():.3f}")
print(f"Recuperación de la prueba: {cv_results['test_recall_macro'].mean():.3f}")

Rareza: Muy común Dificultad: Media


5. Explique las técnicas de reducción de la dimensionalidad (PCA, t-SNE).

Respuesta: La reducción de la dimensionalidad reduce el número de características preservando la información.

  • PCA (Análisis de componentes principales):
    • Transformación lineal
    • Encuentra direcciones de máxima varianza
    • Preserva la estructura global
    • Rápido, interpretable
  • t-SNE (t-Distributed Stochastic Neighbor Embedding):
    • Transformación no lineal
    • Preserva la estructura local
    • Bueno para la visualización
    • Más lento, no para la extracción de características
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
from sklearn.datasets import load_digits
import matplotlib.pyplot as plt

# Cargar datos de alta dimensión
digits = load_digits()
X, y = digits.data, digits.target

print(f"Forma original: {X.shape}")

# PCA - reducir a 2 dimensiones
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
print(f"Forma de PCA: {X_pca.shape}")
print(f"Relación de varianza explicada: {pca.explained_variance_ratio_}")
print(f"Varianza total explicada: {pca.explained_variance_ratio_.sum():.3f}")

# t-SNE - reducir a 2 dimensiones
tsne = TSNE(n_components=2, random_state=42)
X_tsne = tsne.fit_transform(X)
print(f"Forma de t-SNE: {X_tsne.shape}")

# PCA para la extracción de características (mantener el 95% de la varianza)
pca_95 = PCA(n_components=0.95)
X_reduced = pca_95.fit_transform(X)
print(f"\nComponentes para el 95% de la varianza: {pca_95.n_components_}")
print(f"Forma reducida: {X_reduced.shape}")

Rareza: Común Dificultad: Difícil


6. ¿Qué es la curva ROC y el AUC? ¿Cuándo la usaría?

Respuesta: La curva ROC (Receiver Operating Characteristic) representa la tasa de verdaderos positivos frente a la tasa de falsos positivos en varios umbrales.

  • AUC (Área bajo la curva): Métrica única que resume la ROC
    • AUC = 1.0: Clasificador perfecto
    • AUC = 0.5: Clasificador aleatorio
    • AUC < 0.5: Peor que aleatorio
  • Casos de uso:
    • Comparación de modelos
    • Conjuntos de datos desequilibrados
    • Cuando necesita elegir el umbral
from sklearn.metrics import roc_curve, roc_auc_score, auc
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer
import matplotlib.pyplot as plt

# Cargar datos
data = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(
    data.data, data.target, test_size=0.3, random_state=42
)

# Entrenar modelo
model = LogisticRegression(max_iter=10000)
model.fit(X_train, y_train)

# Obtener predicciones de probabilidad
y_pred_proba = model.predict_proba(X_test)[:, 1]

# Calcular la curva ROC
fpr, tpr, thresholds = roc_curve(y_test, y_pred_proba)
roc_auc = auc(fpr, tpr)

print(f"AUC: {roc_auc:.3f}")

# Alternativa: cálculo directo del AUC
auc_score = roc_auc_score(y_test, y_pred_proba)
print(f"AUC (directo): {auc_score:.3f}")

# Encontrar el umbral óptimo (estadístico J de Youden)
optimal_idx = np.argmax(tpr - fpr)
optimal_threshold = thresholds[optimal_idx]
print(f"Umbral óptimo: {optimal_threshold:.3f}")

Rareza: Muy común Dificultad: Media


Ingeniería de características (4 preguntas)

7. ¿Qué técnicas utiliza para la ingeniería de características?

Respuesta: La ingeniería de características crea nuevas características a partir de los datos existentes para mejorar el rendimiento del modelo.

  • Técnicas:
    • Codificación: Codificación one-hot, de etiqueta, de destino
    • Escalado: StandardScaler, MinMaxScaler
    • Agrupación: Discretizar variables continuas
    • Características polinómicas: Términos de interacción
    • Específico del dominio: Características de fecha, características de texto
    • Agregaciones: Estadísticas de grupo
from sklearn.preprocessing import StandardScaler, OneHotEncoder, PolynomialFeatures
import pandas as pd
import numpy as np

# Datos de muestra
df = pd.DataFrame({
    'age': [25, 30, 35, 40, 45],
    'salary': [50000, 60000, 75000, 80000, 90000],
    'department': ['IT', 'HR', 'IT', 'Finance', 'HR'],
    'date': pd.date_range('2023-01-01', periods=5)
})

# Codificación one-hot
df_encoded = pd.get_dummies(df, columns=['department'], prefix='dept')

# Escalado
scaler = StandardScaler()
df_encoded[['age_scaled', 'salary_scaled']] = scaler.fit_transform(
    df_encoded[['age', 'salary']]
)

# Agrupación
df_encoded['age_group'] = pd.cut(df['age'], bins=[0, 30, 40, 100], labels=['young', 'mid', 'senior'])

# Características de fecha
df_encoded['year'] = df['date'].dt.year
df_encoded['month'] = df['date'].dt.month
df_encoded['day_of_week'] = df['date'].dt.dayofweek

# Características polinómicas
poly = PolynomialFeatures(degree=2, include_bias=False)
poly_features = poly.fit_transform(df[['age', 'salary']])

# Características de interacción
df_encoded['age_salary_interaction'] = df['age'] * df['salary']

print(df_encoded.head())

Rareza: Muy común Dificultad: Media


8. ¿Cómo maneja los conjuntos de datos desequilibrados?

Respuesta: Los conjuntos de datos desequilibrados tienen distribuciones de clase desiguales, lo que puede sesgar los modelos.

  • Técnicas:
    • Remuestreo:
      • Sobre muestreo de la clase minoritaria (SMOTE)
      • Submuestreo de la clase mayoritaria
    • Ponderaciones de clase: Penalizar la clasificación errónea de la clase minoritaria
    • Métodos de conjunto: Bosque aleatorio equilibrado
    • Evaluación: Utilice precisión, recuperación, F1, no solo precisión
    • Detección de anomalías: Tratar la minoría como una anomalía
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, confusion_matrix
from imblearn.over_sampling import SMOTE
from imblearn.under_sampling import RandomUnderSampler

# Crear un conjunto de datos desequilibrado
X, y = make_classification(
    n_samples=1000, n_features=20, n_informative=15,
    n_classes=2, weights=[0.9, 0.1], random_state=42
)

print(f"Distribución de clases: {np.bincount(y)}")

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 1. Sin manejar el desequilibrio
model_baseline = LogisticRegression()
model_baseline.fit(X_train, y_train)
y_pred_baseline = model_baseline.predict(X_test)
print("\nLínea de base (sin manejo):")
print(classification_report(y_test, y_pred_baseline))

# 2. SMOTE (sobremuestreo sintético de minorías)
smote = SMOTE(random_state=42)
X_train_smote, y_train_smote = smote.fit_resample(X_train, y_train)
print(f"\nDespués de SMOTE: {np.bincount(y_train_smote)}")

model_smote = LogisticRegression()
model_smote.fit(X_train_smote, y_train_smote)
y_pred_smote = model_smote.predict(X_test)
print("\nCon SMOTE:")
print(classification_report(y_test, y_pred_smote))

# 3. Ponderaciones de clase
model_weighted = LogisticRegression(class_weight='balanced')
model_weighted.fit(X_train, y_train)
y_pred_weighted = model_weighted.predict(X_test)
print("\nCon ponderaciones de clase:")
print(classification_report(y_test, y_pred_weighted))

Rareza: Muy común Dificultad: Media


9. Explique las técnicas de selección de características.

Respuesta: La selección de características identifica las características más relevantes para el modelado.

  • Métodos:
    • Métodos de filtro: Pruebas estadísticas (correlación, chi-cuadrado)
    • Métodos de envoltura: Eliminación recursiva de características (RFE)
    • Métodos integrados: Lazo, importancia de características basada en árboles
    • Reducción de la dimensionalidad: PCA (diferente de la selección)
from sklearn.feature_selection import SelectKBest, chi2, RFE, SelectFromModel
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.preprocessing import MinMaxScaler

# Cargar datos
data = load_breast_cancer()
X, y = data.data, data.target

# 1. Método de filtro - SelectKBest con chi-cuadrado
X_scaled = MinMaxScaler().fit_transform(X)
selector_chi2 = SelectKBest(chi2, k=10)
X_chi2 = selector_chi2.fit_transform(X_scaled, y)
print(f"Características originales: {X.shape[1]}")
print(f"Características seleccionadas (chi2): {X_chi2.shape[1]}")

# 2. Método de envoltura - Eliminación recursiva de características
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rfe = RFE(estimator=rf, n_features_to_select=10)
X_rfe = rfe.fit_transform(X, y)
print(f"Características seleccionadas (RFE): {X_rfe.shape[1]}")
print(f"Clasificación de características: {rfe.ranking_}")

# 3. Método integrado - Importancia de características basada en árboles
rf.fit(X, y)
importances = rf.feature_importances_
indices = np.argsort(importances)[::-1]

print("\nLas 10 características principales por importancia:")
for i in range(10):
    print(f"{i+1}. {data.feature_names[indices[i]]}: {importances[indices[i]]:.4f}")

# SelectFromModel
selector_model = SelectFromModel(rf, threshold='median', prefit=True)
X_selected = selector_model.transform(X)
print(f"\nCaracterísticas seleccionadas (importancia): {X_selected.shape[1]}")

Rareza: Común Dificultad: Media


10. ¿Cómo maneja las variables categóricas con alta cardinalidad?

Respuesta: Las variables categóricas de alta cardinalidad tienen muchos valores únicos.

  • Técnicas:
    • Codificación de destino: Reemplazar con la media de destino
    • Codificación de frecuencia: Reemplazar con la frecuencia
    • Incrustación: Aprender representaciones densas (redes neuronales)
    • Agrupación: Combinar categorías raras en "Otro"
    • Hashing: Hash a un número fijo de depósitos
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split

# Datos de muestra con alta cardinalidad
df = pd.DataFrame({
    'city': np.random.choice([f'City_{i}' for i in range(100)], 1000),
    'target': np.random.randint(0, 2, 1000)
})

print(f"Ciudades únicas: {df['city'].nunique()}")

# 1. Codificación de destino
target_means = df.groupby('city')['target'].mean()
df['city_target_encoded'] = df['city'].map(target_means)

# 2. Codificación de frecuencia
freq = df['city'].value_counts()
df['city_frequency'] = df['city'].map(freq)

# 3. Agrupar categorías raras
freq_threshold = 10
rare_cities = freq[freq < freq_threshold].index
df['city_grouped'] = df['city'].apply(lambda x: 'Other' if x in rare_cities else x)

print(f"\nDespués de la agrupación: {df['city_grouped'].nunique()} valores únicos")

# 4. Codificación hash (usando la librería category_encoders)
# from category_encoders import HashingEncoder
# encoder = HashingEncoder(cols=['city'], n_components=10)
# df_hashed = encoder.fit_transform(df)

print(df[['city', 'city_target_encoded', 'city_frequency', 'city_grouped']].head())

Rareza: Común Dificultad: Difícil


Implementación y producción de modelos (4 preguntas)

11. ¿Cómo implementa un modelo de aprendizaje automático en producción?

Respuesta: La implementación de modelos hace que los modelos estén disponibles para su uso en el mundo real.

  • Pasos:
    1. Serialización del modelo: Guardar el modelo (pickle, joblib, ONNX)
    2. Desarrollo de API: Crear API REST (Flask, FastAPI)
    3. Contenedorización: Docker para la consistencia
    4. Implementación: Plataformas en la nube (AWS, GCP, Azure)
    5. Monitoreo: Seguimiento del rendimiento, deriva
    6. CI/CD: Pruebas e implementación automatizadas
# 1. Entrenar y guardar el modelo
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
import joblib

# Entrenar modelo
data = load_iris()
model = RandomForestClassifier()
model.fit(data.data, data.target)

# Guardar modelo
joblib.dump(model, 'model.joblib')

# 2. Crear API con FastAPI
from fastapi import FastAPI
import numpy as np

app = FastAPI()

# Cargar modelo
model = joblib.load('model.joblib')

@app.post("/predict")
def predict(features: list):
    # Convertir a matriz numpy
    X = np.array(features).reshape(1, -1)
    prediction = model.predict(X)
    probability = model.predict_proba(X)
    
    return {
        "prediction": int(prediction[0]),
        "probability": probability[0].tolist()
    }

# 3. Dockerfile
"""
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
"""

# 4. Uso
# curl -X POST "http://localhost:8000/predict" \
#      -H "Content-Type: application/json" \
#      -d '{"features": [5.1, 3.5, 1.4, 0.2]}'

Rareza: Muy común Dificultad: Difícil


12. ¿Qué es el monitoreo de modelos y por qué es importante?

Respuesta: El monitoreo de modelos rastrea el rendimiento del modelo en producción.

  • Qué monitorear:
    • Métricas de rendimiento: Precisión, precisión, recuperación
    • Deriva de datos: Cambios en la distribución de entrada
    • Deriva de conceptos: Cambios en la relación de destino
    • Métricas del sistema: Latencia, rendimiento, errores
  • Acciones:
    • Alertas cuando el rendimiento se degrada
    • Volver a entrenar con nuevos datos
    • Pruebas A/B de nuevos modelos
import numpy as np
from scipy import stats

# Simular datos de producción
training_data = np.random.normal(0, 1, 1000)
production_data = np.random.normal(0.5, 1.2, 1000)  # Derivado

# Detectar la deriva de datos utilizando la prueba de Kolmogorov-Smirnov
statistic, p_value = stats.ks_2samp(training_data, production_data)

print(f"Estadístico KS: {statistic:.4f}")
print(f"Valor P: {p_value:.4f}")

if p_value < 0.05:
    print("¡Deriva de datos detectada! Considere volver a entrenar el modelo.")
else:
    print("No se detectó ninguna deriva significativa.")

# Monitorear el rendimiento del modelo
class ModelMonitor:
    def __init__(self, model):
        self.model = model
        self.predictions = []
        self.actuals = []
        
    def log_prediction(self, X, y_pred, y_true=None):
        self.predictions.append(y_pred)
        if y_true is not None:
            self.actuals.append(y_true)
    
    def get_accuracy(self):
        if len(self.actuals) == 0:
            return None
        return np.mean(np.array(self.predictions) == np.array(self.actuals))
    
    def check_drift(self, new_data, reference_data):
        statistic, p_value = stats.ks_2samp(new_data, reference_data)
        return p_value < 0.05

# Uso
monitor = ModelMonitor(model)
# monitor.log_prediction(X, y_pred, y_true)
# accuracy = monitor.get_accuracy()

Rareza: Común Dificultad: Media


13. Explique las pruebas A/B en el contexto del aprendizaje automático.

Respuesta: Las pruebas A/B comparan dos versiones (control vs tratamiento) para determinar cuál funciona mejor.

  • Proceso:
    1. Dividir el tráfico aleatoriamente
    2. Servir diferentes modelos a cada grupo
    3. Recopilar métricas
    4. Prueba estadística para determinar el ganador
  • Métricas: Tasa de conversión, ingresos, participación
  • Pruebas estadísticas: Prueba t, chi-cuadrado, métodos bayesianos
import numpy as np
from scipy import stats

# Simular los resultados de las pruebas A/B
# Grupo de control (Modelo A)
control_conversions = 520
control_visitors = 10000

# Grupo de tratamiento (Modelo B)
treatment_conversions = 580
treatment_visitors = 10000

# Calcular las tasas de conversión
control_rate = control_conversions / control_visitors
treatment_rate = treatment_conversions / treatment_visitors

print(f"Tasa de conversión de control: {control_rate:.4f}")
print(f"Tasa de conversión de tratamiento: {treatment_rate:.4f}")
print(f"Elevación: {((treatment_rate - control_rate) / control_rate * 100):.2f}%")

# Prueba de significación estadística (prueba z de dos proporciones)
pooled_rate = (control_conversions + treatment_conversions) / (control_visitors + treatment_visitors)
se = np.sqrt(pooled_rate * (1 - pooled_rate) * (1/control_visitors + 1/treatment_visitors))
z_score = (treatment_rate - control_rate) / se
p_value = 2 * (1 - stats.norm.cdf(abs(z_score)))

print(f"\nPuntuación Z: {z_score:.4f}")
print(f"Valor P: {p_value:.4f}")

if p_value < 0.05:
    print("¡El resultado es estadísticamente significativo!")
    if treatment_rate > control_rate:
        print("El tratamiento (Modelo B) es mejor.")
    else:
        print("El control (Modelo A) es mejor.")
else:
    print("No hay diferencia estadísticamente significativa.")

# Cálculo del tamaño de la muestra
from statsmodels.stats.power import zt_ind_solve_power

required_sample = zt_ind_solve_power(
    effect_size=0.02,  # Efecto mínimo detectable
    alpha=0.05,
    power=0.8,
    alternative='two-sided'
)
print(f"\nTamaño de muestra requerido por grupo: {int(required_sample)}")

Rareza: Común Dificultad: Difícil


14. ¿Qué es MLOps y por qué es importante?

Respuesta: MLOps (Machine Learning Operations) aplica los principios de DevOps a los sistemas de ML.

  • Componentes:
    • Control de versiones: Código, datos, modelos
    • Pruebas automatizadas: Pruebas unitarias, de integración, de modelos
    • Canalizaciones de CI/CD: Implementación automatizada
    • Monitoreo: Rendimiento, detección de deriva
    • Reproducibilidad: Seguimiento de experimentos
  • Herramientas: MLflow, Kubeflow, DVC, Weights & Biases
# Ejemplo: MLflow para el seguimiento de experimentos
import mlflow
import mlflow.sklearn
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# Cargar datos
data = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
    data.data, data.target, test_size=0.3, random_state=42
)

# Iniciar la ejecución de MLflow
with mlflow.start_run():
    # Registrar parámetros
    n_estimators = 100
    max_depth = 5
    mlflow.log_param("n_estimators", n_estimators)
    mlflow.log_param("max_depth", max_depth)
    
    # Entrenar modelo
    model = RandomForestClassifier(
        n_estimators=n_estimators,
        max_depth=max_depth,
        random_state=42
    )
    model.fit(X_train, y_train)
    
    # Evaluar
    y_pred = model.predict(X_test)
    accuracy = accuracy_score(y_test, y_pred)
    
    # Registrar métricas
    mlflow.log_metric("accuracy", accuracy)
    
    # Registrar modelo
    mlflow.sklearn.log_model(model,
Newsletter subscription

Consejos de carrera semanales que realmente funcionan

Recibe las últimas ideas directamente en tu bandeja de entrada

Tu Próxima Entrevista Está a Solo un Currículum de Distancia

Crea un currículum profesional y optimizado en minutos. No se necesitan habilidades de diseño, solo resultados comprobados.

Crea mi currículum

Compartir esta publicación

Haz que tus 6 Segundos Cuenten

Los reclutadores escanean currículums durante un promedio de solo 6 a 7 segundos. Nuestras plantillas probadas están diseñadas para captar la atención al instante y mantenerlos leyendo.