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

相关推荐
Kurbaneli2 小时前
Python的起源与发展
python
过河卒_zh15667662 小时前
网信发布2025年“人工智能+政务”规范应用案例拟入选名单公示
人工智能·大模型·aigc·政务·算法备案
dazzle2 小时前
Python高级技巧:装饰器全面指南,从基础到高级应用
python
南_山无梅落2 小时前
11.Python 常用数据类型「增删改查」操作总结表格
python
IT_陈寒2 小时前
Redis 性能优化实战:5个被低估的配置项让我节省了40%内存成本
前端·人工智能·后端
乾元2 小时前
用 AI 做联动:当应用层出现问题,网络如何被“自动拉入决策回路”
运维·开发语言·网络·人工智能·ci/cd·自动化
qq_12498707532 小时前
基于springboot的智能医院挂号系统(源码+论文+部署+安装)
java·人工智能·spring boot·后端·毕业设计
光羽隹衡2 小时前
机器学习——决策树之回归树
决策树·机器学习·回归
wenxiaohai1232 小时前
在anaconda中安装cuda-pytorch
人工智能·pytorch·python·anaconda