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),让数据处理效率翻倍!

相关推荐
我材不敲代码3 小时前
Python实现打包贪吃蛇游戏
开发语言·python·游戏
0思必得05 小时前
[Web自动化] Selenium处理动态网页
前端·爬虫·python·selenium·自动化
水如烟5 小时前
孤能子视角:“组织行为学–组织文化“
人工智能
韩立学长5 小时前
【开题答辩实录分享】以《基于Python的大学超市仓储信息管理系统的设计与实现》为例进行选题答辩实录分享
开发语言·python
大山同学5 小时前
图片补全-Context Encoder
人工智能·机器学习·计算机视觉
qq_192779875 小时前
高级爬虫技巧:处理JavaScript渲染(Selenium)
jvm·数据库·python
薛定谔的猫19826 小时前
十七、用 GPT2 中文对联模型实现经典上联自动对下联:
人工智能·深度学习·gpt2·大模型 训练 调优
u0109272716 小时前
使用Plotly创建交互式图表
jvm·数据库·python
爱学习的阿磊6 小时前
Python GUI开发:Tkinter入门教程
jvm·数据库·python
壮Sir不壮6 小时前
2026年奇点:Clawdbot引爆个人AI代理
人工智能·ai·大模型·claude·clawdbot·moltbot·openclaw