ADVANCE Day26

@浙大疏锦行

📘 Day 26 实战作业:从"调包"到"造轮子" ------ 函数专题 (上)

1. 作业综述

核心目标

从今天开始,我们将不再满足于调用 print(), len()pandas.read_csv(),而是开始编写属于自己的自定义函数

这是构建大型项目(如我们之前的 ResNet 或 信贷预测 Pipeline)的基石。只有将复杂的逻辑封装成函数,代码才能具备复用性 (Reusability)可读性 (Readability)

涉及知识点

  • 函数定义 : def 关键字与文档字符串 (Docstring)。
  • 参数魔法: 位置参数、关键字参数、默认参数。
  • 无限接口 : *args (可变位置参数) 与 **kwargs (可变关键字参数) 的实战应用。

步骤 1:定义你的第一个工具

场景描述

在机器学习中,我们经常需要计算各种指标(如 Precision, Recall, F1)。

虽然 sklearn 有现成的,但为了理解原理,我们需要手写一个。

任务

  1. 编写一个函数 calculate_f1(precision, recall)
  2. 要求
    • 包含清晰的 文档字符串 (Docstring),说明参数和返回值。
    • 处理分母为 0 的情况(防止除零报错,返回 0)。
    • 返回计算好的 F1 分数。
python 复制代码
def calculate_f1(precision, recall):
    """
    计算 F1 Score 的自定义函数。
    
    参数:
    precision (float): 精确率
    recall (float): 召回率
    
    返回:
    float: F1 Score。如果分母为0,则返回 0.0。
    """
    # 1. 检查分母是否为 0
    if (precision + recall) == 0:
        return 0.0
    
    # 2. 计算公式: 2 * (P * R) / (P + R)
    f1 = 2 * (precision * recall) / (precision + recall)
    
    return f1

# --- 测试你的工具 ---
p = 0.85
r = 0.76

# 调用函数
score = calculate_f1(p, r)
print(f"Precision: {p}, Recall: {r}")
print(f"F1 Score: {score:.4f}")

# 测试极端情况
print(f"极端情况 F1: {calculate_f1(0, 0)}")
复制代码
Precision: 0.85, Recall: 0.76
F1 Score: 0.8025
极端情况 F1: 0.0

步骤 2:灵活的默认参数

场景描述

写代码时,有些参数 90% 的情况都是固定的,但我们希望保留修改它的权利。

比如数据加载函数,默认读取 .csv,但偶尔也需要读 .txt

任务

  1. 编写函数 mock_data_loader(file_path, mode='r', file_type='csv')
  2. 如果 file_type 是 'csv',打印 "正在解析表格...";如果是 'json',打印 "正在解析字典..."。
  3. 分别使用默认参数修改参数的方式调用它。
python 复制代码
def mock_data_loader(file_path, mode='r', file_type='csv'):
    """
    模拟数据加载器。
    
    参数:
    file_path (str): 文件路径
    mode (str): 打开模式,默认为 'r' (只读)
    file_type (str): 文件类型,默认为 'csv'
    """
    print(f"\n📂 正在打开文件: {file_path} (模式: {mode})")
    
    if file_type == 'csv':
        print("  > 正在解析 CSV 表格数据...")
    elif file_type == 'json':
        print("  > 正在解析 JSON 结构化数据...")
    else:
        print(f"  > ⚠️ 未知文件类型: {file_type}")
        
    print("  ✅ 加载完成!")

# --- 调用测试 ---
# 1. 最简单的调用 (使用全部默认值)
mock_data_loader("train_data.csv")

# 2. 修改部分默认值 (关键字传参)
mock_data_loader("config.json", file_type='json')

# 3. 全部自定义
mock_data_loader("log.txt", mode='w', file_type='text')
复制代码
📂 正在打开文件: train_data.csv (模式: r)
  > 正在解析 CSV 表格数据...
  ✅ 加载完成!

📂 正在打开文件: config.json (模式: r)
  > 正在解析 JSON 结构化数据...
  ✅ 加载完成!

📂 正在打开文件: log.txt (模式: w)
  > ⚠️ 未知文件类型: text
  ✅ 加载完成!

步骤 3:万能接口 *args**kwargs

场景描述

这是 Python 高级编程中最帅气的特性,在 PyTorch 和 Transformers 源码中随处可见。

  • *args: 用于接收任意数量的无名参数(打包成元组)。
  • **kwargs: 用于接收任意数量的键值对参数(打包成字典)。

任务

编写一个"超级模型训练器" train_model(model_name, *metrics, **config)

  1. model_name: 必填参数。
  2. *metrics: 接收任意数量的评估指标(如 "Accuracy", "F1", "AUC")。
  3. **config: 接收任意数量的超参数(如 lr=0.01, batch_size=32)。
python 复制代码
def train_model(model_name, *metrics, **config):
    print(f"\n🚀 开始训练模型: 【{model_name}】")
    
    # 1. 处理 *args (metrics)
    if metrics:
        print("📊 需要计算的指标:")
        for m in metrics:
            print(f"  - {m}")
    else:
        print("⚠️ 未指定评估指标!")
        
    # 2. 处理 **kwargs (config)
    print("⚙️ 训练配置 (Hyperparameters):")
    for key, value in config.items():
        print(f"  {key}: {value}")
        
    print("... 模型训练中 ...")
    print("✅ 训练结束!")

# --- 实战调用 ---

# 场景 A: 简单训练
train_model("LogisticRegression", "Accuracy", lr=0.1)

# 场景 B: 复杂深度学习训练
# 注意看:我可以传 2 个指标,也可以传 10 个配置,函数都能接得住!
train_model(
    "ResNet50", 
    "Accuracy", "Precision", "Recall", "F1_Score",  # *metrics
    batch_size=64,                                  # **config
    learning_rate=0.001,
    optimizer="Adam",
    device="cuda:0"
)
复制代码
🚀 开始训练模型: 【LogisticRegression】
📊 需要计算的指标:
  - Accuracy
⚙️ 训练配置 (Hyperparameters):
  lr: 0.1
... 模型训练中 ...
✅ 训练结束!

🚀 开始训练模型: 【ResNet50】
📊 需要计算的指标:
  - Accuracy
  - Precision
  - Recall
  - F1_Score
⚙️ 训练配置 (Hyperparameters):
  batch_size: 64
  learning_rate: 0.001
  optimizer: Adam
  device: cuda:0
... 模型训练中 ...
✅ 训练结束!

🎓 Day 26 总结:掌控代码的控制权

今天我们完成了一次身份的转变:

  1. 封装思维 :通过 def,我们将一堆代码打包成了一个 function。以后遇到计算 F1 Score,直接调用即可,这就是 DRY 原则 (Don't Repeat Yourself)
  2. 接口设计
    • 默认参数 让函数好用(大部分时候不用传参)。
    • *args / **kwargs 让函数强大(想传多少传多少)。

深度学习伏笔

你今天写的 train_model(name, *args, **kwargs) 其实就是 PyTorch 中模型定义和训练循环的雏形。在后续的大型项目中,这种写法能让你的代码极具扩展性。

Next Level : 下一次,我们将探索函数的高阶玩法(Lambda, Map, Filter),让数据处理效率翻倍!

相关推荐
风象南1 天前
Claude Code这个隐藏技能,让我告别PPT焦虑
人工智能·后端
曲幽1 天前
FastAPI压力测试实战:Locust模拟真实用户并发及优化建议
python·fastapi·web·locust·asyncio·test·uvicorn·workers
Mintopia1 天前
OpenClaw 对软件行业产生的影响
人工智能
陈广亮1 天前
构建具有长期记忆的 AI Agent:从设计模式到生产实践
人工智能
会写代码的柯基犬1 天前
DeepSeek vs Kimi vs Qwen —— AI 生成俄罗斯方块代码效果横评
人工智能·llm
Mintopia1 天前
OpenClaw 是什么?为什么节后热度如此之高?
人工智能
爱可生开源社区1 天前
DBA 的未来?八位行业先锋的年度圆桌讨论
人工智能·dba
叁两1 天前
用opencode打造全自动公众号写作流水线,AI 代笔太香了!
前端·人工智能·agent
敏编程1 天前
一天一个Python库:jsonschema - JSON 数据验证利器
python