https://blog.youkuaiyun.com/weixin_45655710?type=blog
@浙大疏锦行
DAY 29 复习日:类的装饰器
知识点回顾
1.类的装饰器
2.装饰器思想的进一步理解:外部修改、动态
3.类方法的定义:内部定义和外部定义
作业:复习类和函数的知识点,写下自己过去29天的学习心得,如对函数和类的理解,对python这门工具的理解等,未来再过几个专题部分我们即将开启深度学习部分。
1. 知识脉络图谱
我们可以把这几天的学习内容看作构建一个智能工厂的过程:
- Day 28 面向对象 (OOP):这是工厂的蓝图。我们将数据和操作封装成“类”,比如“模型训练器”、“数据处理器”。
- Day 23 管道 (Pipeline):这是流水线。我们将数据预处理、特征工程、模型训练串联起来,一键运行,防止数据泄露。
- Day 26 函数参数 (*args, kwargs):这是灵活的控制台**。允许我们传入任意数量的配置和参数,增加工厂的通用性。
- Day 27 装饰器 (@decorator):这是监控探头。在不拆开机器(修改函数源码)的情况下,给流水线加上计时、日志记录功能。
- Day 25 异常处理 (try-except):这是安全气囊。防止某个零件出错(如除零、文件丢失)导致整个工厂爆炸(程序崩溃)。
- Day 24 元组 & OS 模块:这是档案室和文件柜。元组定义不可修改的配置(如输入形状),OS 模块管理文件的路径和存储。
2. 核心知识点速查表
| 模块 | 核心代码/概念 | 在 ML/DL 中的应用场景 |
|---|---|---|
| Pipeline | Pipeline(steps=[('scaler', scaler), ('clf', model)]) | 自动化数据清洗与训练,防止验证集数据泄露。 |
| OS 模块 | os.path.join(), os.walk(), os.makedirs() | 数据集管理:批量读取图片,自动创建模型保存目录。 |
| 异常处理 | try: ... except Error: ... finally: ... | 鲁棒性训练:遇到损坏图片跳过不报错;训练中断时保存进度。 |
| 函数参数 | def func(*args, **kwargs): | 超参数调优:接收不确定数量的模型配置参数(如 layer_num, dropout_rate)。 |
| 装饰器 | @timer, @logger | 实验监控:自动记录每个实验的训练耗时、显存占用。 |
| 面向对象 | class Model(object): def __init__(self): ... | 模型封装:PyTorch/Sklearn 中几乎所有模型都是类。 |
3. 综合实战作业:打造一个“智能模型训练器”
这个代码案例同时使用了:class (OOP), pipeline (管道), try-except (异常处理), os (路径管理), @decorator (装饰器), 和 **kwargs (参数)。
请仔细阅读代码和注释,这就是你这周学习成果的集大成者。
import os
import time
import functools
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer
# --- Day 27: 装饰器 (用于记录日志和时间) ---
def experiment_logger(func):
"""记录实验开始和结束时间,以及运行状态"""
@functools.wraps(func)
def wrapper(*args, **kwargs):
print(f"\n[LOG] >>> 开始执行: {func.__name__}")
start_time = time.time()
try:
result = func(*args, **kwargs) # 执行原函数
print(f"[LOG] <<< 执行成功,耗时: {time.time() - start_time:.2f}s")
return result
except Exception as e:
print(f"[LOG] !!! 执行出错: {e}")
raise # 继续抛出异常,让外部捕获
return wrapper
# --- Day 28: 面向对象 (封装整个训练流程) ---
class HousingModelTrainer:
# --- Day 26: 默认参数与初始化 ---
def __init__(self, data_path, save_dir="models"):
self.data_path = data_path
self.save_dir = save_dir
# --- Day 24: OS 模块 (创建目录) ---
if not os.path.exists(self.save_dir):
os.makedirs(self.save_dir)
print(f"已创建模型保存目录: {self.save_dir}")
# --- Day 25: 异常处理 (数据加载) ---
def load_data(self):
print("正在加载数据...")
try:
# 假设数据是 Day 23-24 用到的 housing.csv
if not os.path.exists(self.data_path):
raise FileNotFoundError(f"文件未找到: {self.data_path}")
df = pd.read_csv(self.data_path)
# 简单处理:仅选取部分数值列演示
X = df[['longitude', 'latitude', 'housing_median_age', 'total_rooms', 'median_income']]
y = df['median_house_value']
return train_test_split(X, y, test_size=0.2, random_state=42)
except FileNotFoundError as e:
print(f"严重错误: {e}")
return None, None, None, None
except Exception as e:
print(f"读取数据时发生未知错误: {e}")
return None, None, None, None
# --- Day 23: Pipeline (构建管道) ---
def _build_pipeline(self, n_estimators=100):
"""内部方法:构建预处理和模型管道"""
pipeline = Pipeline([
('imputer', SimpleImputer(strategy='median')), # 缺失值填充
('scaler', StandardScaler()), # 标准化
('regressor', RandomForestRegressor(n_estimators=n_estimators, random_state=42))
])
return pipeline
# --- Day 26 & 27: 装饰器应用 + **kwargs 动态参数 ---
@experiment_logger
def train(self, **kwargs):
"""
训练模型
**kwargs: 接收如 n_estimators 等模型超参数
"""
X_train, X_test, y_train, y_test = self.load_data()
if X_train is None:
print("数据加载失败,终止训练。")
return
# 获取参数,如果没传则使用默认值 100
n_est = kwargs.get('n_estimators', 100)
print(f"构建 Pipeline,参数 n_estimators={n_est}...")
self.pipeline = self._build_pipeline(n_estimators=n_est)
# Day 25: 异常处理 (训练过程)
try:
self.pipeline.fit(X_train, y_train)
score = self.pipeline.score(X_test, y_test)
print(f"模型训练完成!测试集 R2 分数: {score:.4f}")
# --- Day 24: OS 路径拼接 ---
model_save_path = os.path.join(self.save_dir, f"rf_model_{n_est}.pkl")
# 这里假装保存模型
with open(model_save_path, 'w') as f:
f.write("Simulated Model Binary")
print(f"模型已保存至: {model_save_path}")
except Exception as e:
print(f"训练过程中断: {e}")
finally:
print("训练流程结束 (清理临时资源...)")
# --- 主程序运行 ---
if __name__ == "__main__":
# 假设当前目录下有 housing.csv,如果没有,你可以换成自己的路径
# Day 24: 使用原始字符串处理路径
data_file = 'housing.csv'
# 1. 实例化对象
trainer = HousingModelTrainer(data_path=data_file)
# 2. 调用方法 (传入 **kwargs)
# 即使 housing.csv 不存在,程序也不会崩溃,而是会打印错误日志
trainer.train(n_estimators=50)
4. 复习总结语
这段代码展示了一个成熟的 Python 程序员是如何思考的:
- 不写死逻辑:用
class封装,用**kwargs传参。 - 不裸奔运行:用
pipeline保护数据流,用try-except保护程序流。 - 自动化管理:用
os处理路径,用decorator自动记录日志。
791

被折叠的 条评论
为什么被折叠?



