🔬 MLOps实战训练营

学习进度

阶段 4: 模型对比实验(MLflow进阶)

目标: 从50%到70%信心值 🎯

📅 第4阶段:模型对比实验(MLflow进阶)

🚀 系统性模型对比 = 从"能跑模型"到"工程师"的关键跃升!

🎯 为什么要做模型对比?

在实际项目中,你永远不知道哪个算法最适合你的数据。系统性的模型对比能让你向客户证明:"我们测试了6种算法,随机森林在你的数据上效果最好,准确率提升了15%"


职场意义:系统性对比是高级工程师的标志性技能

🏆 6大算法擂台赛

📈 Linear Regression
🔗 Ridge Regression
🎯 Lasso Regression
⚖️ ElasticNet
🌳 Random Forest
🚀 Gradient Boosting

模型训练常见陷阱与解决方案

❌ 问题1: 不同模型结果无法对比

正确做法

统一的训练框架,确保数据处理一致

职场意义:系统性对比是高级工程师的标志

错误做法

每次手动调整代码训练不同模型

❌ 问题2: 超参数调优混乱

解决方案

使用MLflow记录每次实验的参数和结果

进阶技巧:用Optuna等工具做自动超参数优化

常见错误

随意调参,没有记录调参过程

❌ 问题3: 模型过拟合没发现

解决方法

始终关注验证集表现,设置早停机制

实战经验:过拟合是新手最容易犯的错误,但也最好解决

危险信号

训练集准确率95%,验证集准确率60%

❌ 问题4: 内存不足训练中断

应急方案

减小batch_size,使用数据采样

根本解决:监控内存使用,优化数据加载

举一反三:资源限制在生产环境中很常见,要学会优化

上午:多模型训练脚本

💡 所有代码块默认收起,点击标题栏可展开查看完整代码,支持一键复制
🐍 src/day3_model_comparison.py
"""
Day 3: 模型对比实验
目标:训练多个模型并在MLflow中对比效果
"""

import mlflow
import mlflow.sklearn
import pandas as pd
import numpy as np
import joblib
import click
from sklearn.linear_model import LinearRegression, Ridge, Lasso, ElasticNet
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.svm import SVR
from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error
from datetime import datetime
import yaml
import warnings
warnings.filterwarnings('ignore')

def load_processed_data():
    """加载处理后的数据"""
    print("📊 加载处理后的数据...")
    
    X_train = pd.read_csv('data/processed/X_train.csv')
    X_val = pd.read_csv('data/processed/X_val.csv')
    X_test = pd.read_csv('data/processed/X_test.csv')
    
    y_train = pd.read_csv('data/processed/y_train.csv').values.ravel()
    y_val = pd.read_csv('data/processed/y_val.csv').values.ravel()
    y_test = pd.read_csv('data/processed/y_test.csv').values.ravel()
    
    print(f"训练集: {X_train.shape}")
    print(f"验证集: {X_val.shape}")
    print(f"测试集: {X_test.shape}")
    
    return X_train, X_val, X_test, y_train, y_val, y_test

def get_model_configs():
    """获取所有模型配置"""
    return {
        'linear': {
            'model': LinearRegression(),
            'params': {}
        },
        'ridge': {
            'model': Ridge(alpha=1.0, random_state=42),
            'params': {'alpha': 1.0}
        },
        'lasso': {
            'model': Lasso(alpha=1.0, random_state=42),
            'params': {'alpha': 1.0}
        },
        'elastic_net': {
            'model': ElasticNet(alpha=1.0, l1_ratio=0.5, random_state=42),
            'params': {'alpha': 1.0, 'l1_ratio': 0.5}
        },
        'random_forest': {
            'model': RandomForestRegressor(
                n_estimators=100, 
                max_depth=10, 
                random_state=42,
                n_jobs=-1
            ),
            'params': {
                'n_estimators': 100,
                'max_depth': 10,
                'random_state': 42
            }
        },
        'gradient_boosting': {
            'model': GradientBoostingRegressor(
                n_estimators=100,
                learning_rate=0.1,
                max_depth=3,
                random_state=42
            ),
            'params': {
                'n_estimators': 100,
                'learning_rate': 0.1,
                'max_depth': 3,
                'random_state': 42
            }
        }
    }

def evaluate_model(model, X_train, X_val, X_test, y_train, y_val, y_test):
    """评估模型性能"""
    # 预测
    train_pred = model.predict(X_train)
    val_pred = model.predict(X_val)
    test_pred = model.predict(X_test)
    
    # 计算指标
    metrics = {
        'train_mse': mean_squared_error(y_train, train_pred),
        'train_rmse': np.sqrt(mean_squared_error(y_train, train_pred)),
        'train_mae': mean_absolute_error(y_train, train_pred),
        'train_r2': r2_score(y_train, train_pred),
        
        'val_mse': mean_squared_error(y_val, val_pred),
        'val_rmse': np.sqrt(mean_squared_error(y_val, val_pred)),
        'val_mae': mean_absolute_error(y_val, val_pred),
        'val_r2': r2_score(y_val, val_pred),
        
        'test_mse': mean_squared_error(y_test, test_pred),
        'test_rmse': np.sqrt(mean_squared_error(y_test, test_pred)),
        'test_mae': mean_absolute_error(y_test, test_pred),
        'test_r2': r2_score(y_test, test_pred)
    }
    
    return metrics

@click.command
@click.option('--model-type', default='all', help='模型类型: linear/ridge/lasso/elastic_net/random_forest/gradient_boosting/all')
@click.option('--experiment-name', default='day3-model-comparison', help='MLflow实验名称')
def train_models(model_type, experiment_name):
    """训练和对比模型"""
    
    # 加载数据
    X_train, X_val, X_test, y_train, y_val, y_test = load_processed_data()
    
    # 设置MLflow实验
    mlflow.set_experiment(experiment_name)
    
    # 获取模型配置
    model_configs = get_model_configs()
    
    # 确定要训练的模型
    if model_type == 'all':
        models_to_train = model_configs.keys()
    else:
        models_to_train = [model_type] if model_type in model_configs else []
    
    results = []
    
    for name in models_to_train:
        print(f"\n🚀 训练 {name} 模型...")
        
        config = model_configs[name]
        model = config['model']
        params = config['params']
        
        with mlflow.start_run(run_name=f"{name}-{datetime.now().strftime('%H%M%S')}"):
            # 训练模型
            model.fit(X_train, y_train)
            
            # 评估模型
            metrics = evaluate_model(model, X_train, X_val, X_test, y_train, y_val, y_test)
            
            # 记录参数
            mlflow.log_param("model_type", name)
            for param_name, param_value in params.items():
                mlflow.log_param(param_name, param_value)
            
            # 记录指标
            for metric_name, metric_value in metrics.items():
                mlflow.log_metric(metric_name, metric_value)
            
            # 保存模型
            mlflow.sklearn.log_model(
                model, 
                "model",
                registered_model_name=f"{name}_house_price_model"
            )
            
            # 保存模型到本地
            model_dir = f'models/{name}'
            os.makedirs(model_dir, exist_ok=True)
            joblib.dump(model, f'{model_dir}/model.pkl')
            
            # 记录结果
            result = {
                'model_name': name,
                'val_r2': metrics['val_r2'],
                'test_r2': metrics['test_r2'],
                'val_rmse': metrics['val_rmse'],
                'test_rmse': metrics['test_rmse']
            }
            results.append(result)
            
            print(f"✅ {name} 完成 - 验证R²: {metrics['val_r2']:.4f}, 测试R²: {metrics['test_r2']:.4f}")
    
    # 打印对比结果
    print("\n📊 模型对比结果:")
    print("=" * 80)
    results_df = pd.DataFrame(results)
    results_df = results_df.sort_values('val_r2', ascending=False)
    print(results_df.to_string(index=False))
    
    # 保存对比结果
    results_df.to_csv('models/comparison_results.csv', index=False)
    
    # 找出最佳模型
    best_model = results_df.iloc[0]
    print(f"\n🏆 最佳模型: {best_model['model_name']}")
    print(f"验证R²: {best_model['val_r2']:.4f}")
    print(f"测试R²: {best_model['test_r2']:.4f}")
    
    return results_df

if __name__ == "__main__":
    import os
    train_models()

晚上:运行对比并分析

🔧 模型训练和结果分析
# 训练所有模型
python src/day3_model_comparison.py --model-type all

# 查看结果
cat models/comparison_results.csv

# 启动MLflow UI查看对比
nohup mlflow ui --host 0.0.0.0 --port 5000 >> mlflow-ui.log 2>&1 &
🐍 src/day3_analysis.py - 模型性能分析
"""
模型性能分析和可视化
"""

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import mlflow
import numpy as np

def analyze_model_performance():
    """分析模型性能"""
    # 读取对比结果
    results = pd.read_csv('models/comparison_results.csv')
    
    # 创建可视化
    fig, axes = plt.subplots(2, 2, figsize=(15, 10))
    
    # R² 对比
    sns.barplot(data=results, x='val_r2', y='model_name', ax=axes[0,0], palette='viridis')
    axes[0,0].set_title('验证集 R² 对比')
    axes[0,0].set_xlabel('R² Score')
    
    # RMSE 对比
    sns.barplot(data=results, x='val_rmse', y='model_name', ax=axes[0,1], palette='plasma')
    axes[0,1].set_title('验证集 RMSE 对比')
    axes[0,1].set_xlabel('RMSE')
    
    # 验证vs测试R²
    sns.scatterplot(data=results, x='val_r2', y='test_r2', s=100, ax=axes[1,0])
    axes[1,0].plot([0, 1], [0, 1], 'r--', alpha=0.5)
    axes[1,0].set_title('验证集 vs 测试集 R²')
    axes[1,0].set_xlabel('验证集 R²')
    axes[1,0].set_ylabel('测试集 R²')
    
    # 模型复杂度vs性能
    complexity = {'linear': 1, 'ridge': 2, 'lasso': 2, 'elastic_net': 3, 
                 'random_forest': 4, 'gradient_boosting': 5}
    results['complexity'] = results['model_name'].map(complexity)
    sns.scatterplot(data=results, x='complexity', y='val_r2', s=100, ax=axes[1,1])
    axes[1,1].set_title('模型复杂度 vs 性能')
    axes[1,1].set_xlabel('复杂度')
    axes[1,1].set_ylabel('验证集 R²')
    
    plt.tight_layout()
    plt.savefig('models/model_comparison.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    print("📊 分析图表已保存到 models/model_comparison.png")

if __name__ == "__main__":
    analyze_model_performance()
🔧 运行分析并提交成果
# 运行分析
python src/day3_analysis.py

# 提交Day 3成果
git add .
git commit -m "Day 3: Multi-model comparison with MLflow

- Trained 6 different models (Linear, Ridge, Lasso, ElasticNet, RF, GBM)
- Comprehensive evaluation with train/val/test metrics
- Model comparison visualization
- Best model: [根据实际结果填写]
- All experiments tracked in MLflow"
📈 模型算法掌握

6种经典回归算法的原理和应用场景

🔬 实验管理

使用MLflow系统性追踪和对比模型

📊 性能评估

多维度指标评估和可视化分析

⚡ 调试优化

识别和解决常见训练问题

🏆 阶段 4 成就解锁

  • 6个模型训练完成并对比
  • MLflow实验管理熟练运用
  • 最佳模型已确定
  • 信心值:50% → 70%

🚀 下一步预告

阶段 5: 将使用Prefect构建自动化训练流水线,让整个过程一键执行!

你将从手动执行ML流程进化到工程师级别的自动化系统,这是从"能跑模型"到"工程师"的关键跃升。