当前位置: 首页 > news >正文

Python训练营打卡——DAY31(2025.5.20)

目录

一、机器学习项目的流程

二、文件的组织

1. 项目核心代码组织

2. 配置文件管理

3. 实验与探索代码

4. 项目产出物管理

三、注意事项

if name == "main"

编码格式

类型注解

四、通俗解释

1. 拆分文件和目录:整理房间一样管理代码​​

2. 导入模块:把其他房间的东西拿来用​​

3. 机器学习项目流程:像做菜的步骤​​

​​4. 项目目录结构:给代码盖一栋楼​​

​​5. 配置文件:菜谱参数集中管理​​

6. 编码格式:统一语言,避免鸡同鸭讲​​

​​7. 类型注解:给代码贴标签,防迷糊​​

​​8. if name == "main":区分“自用”和“被调用”​​

9. ​​总结:今天学了啥?​​

五、作业

​​1. 项目目录结构​​

​​2. 模块化代码示例​​

(1)src/data/load_data.py - 数据加载

(2)src/data/preprocess.py - 数据预处理

(3)src/models/train.py - 模型训练

(4)src/models/explain.py - 可解释性分析

3. ​​配置文件示例​​

config/config.yaml

4. ​​可复用代码的核心原则​​

5. ​​未来可复用的部分​​

6. ​​执行方式​​


昨天我们已经介绍了如何在不同的文件中,导入其他目录的文件,核心在于了解导入方式和python解释器检索目录的方式。

搞清楚了这些,那我们就可以来看看,如何把一个文件,拆分成多个具有着独立功能的文件,然后通过import的方式,来调用这些文件。这样具有几个好处:

  1. 可以让项目文件变得更加规范和清晰
  2. 可以让项目文件更加容易维护,修改某一个功能的时候,只需要修改一个文件,而不需要修改多个文件。
  3. 文件变得更容易复用,部分通用的文件可以单独拿出来,进行其他项目的复用。

一、机器学习项目的流程

一个典型的机器学习项目通常包含以下阶段:

  • 数据加载:从文件、数据库、API 等获取原始数据。
    • 命名参考:load_data.py 、data_loader.py
  • 数据探索与可视化:了解数据特性,初期可用 Jupyter Notebook,成熟后固化绘图函数。
    • 命名参考:eda.py 、visualization_utils.py
  • 数据预处理:处理缺失值、异常值,进行标准化、归一化、编码等操作。
    • 命名参考:preprocess.py 、data_cleaning.py 、data_transformation.py
  • 特征工程:创建新特征,选择、优化现有特征。
    • 命名参考:feature_engineering.py
  • 模型训练:构建模型架构,设置超参数并训练,保存模型。
    • 命名参考:model.py 、train.py
  • 模型评估:用合适指标评估模型在测试集上的性能,生成报告。
    • 命名参考:evaluate.py
  • 模型预测:用训练好的模型对新数据预测。
    • 命名参考:predict.py 、inference.py

二、文件的组织

1. 项目核心代码组织

  • src/(source的缩写):存放项目的核心源代码。按照机器学习项目阶段进一步细分:
    • src/data/:放置与数据相关的代码。
      • src/data/load_data.py:负责从各类数据源(如文件系统、数据库、API 等)读取原始数据。
      • src/data/preprocess.py:进行数据清洗(处理缺失值、异常值)、数据转换(标准化、归一化、编码等)操作。
      • src/data/feature_engineering.py:根据业务和数据特点,创建新特征或对现有特征进行选择、优化。
    • src/models/:关于模型的代码。
      • src/models/model.py:定义模型架构,比如神经网络结构、机器学习算法模型设定等。
      • src/models/train.py:设置模型超参数,并执行训练过程,保存训练好的模型。
      • src/models/evaluate.py:使用合适的评估指标(如准确率、召回率、均方误差等),在测试集上评估模型性能,生成评估报告。
      • src/models/predict.py 或 src/models/inference.py:利用训练好的模型对新数据进行预测。
    • src/utils/:存放通用辅助函数代码,可进一步细分:
      • src/utils/io_utils.py:包含文件读写相关帮助函数,比如读取特定格式文件、保存数据到文件等。
      • src/utils/logging_utils.py:实现日志记录功能,方便记录项目运行过程中的信息,便于调试和监控。
      • src/utils/math_utils.py:特定的数值计算函数,像自定义的矩阵运算、统计计算等。
      • src/utils/plotting_utils.py:绘图工具函数,用于生成数据可视化图表(如绘制损失函数变化曲线、特征分布直方图等 )。

2. 配置文件管理

  • config/ 目录:集中存放项目的配置文件,方便管理和切换不同环境(开发、测试、生产)的配置。
    • config/config.py 或 config/settings.py:以 Python 代码形式定义配置参数。
    • config/config.yaml 或 config/config.json:采用 YAML 或 JSON 格式,清晰列出文件路径、模型超参数、随机种子、API 密钥等可配置参数。
    • .env 文件:通常放在项目根目录,用于存储敏感信息(如数据库密码、API 密钥等),在代码中通过环境变量的方式读取,一般会被 .gitignore 忽略,防止敏感信息泄露。

3. 实验与探索代码

  • notebooks/ 或 experiments/ 目录:用于初期的数据探索、快速实验、模型原型验证。

    • notebooks/initial_eda.ipynb:在项目初期,使用 Jupyter Notebook 进行数据探索与可视化,了解数据特性,分析数据分布、相关性等。
    • experiments/model_experimentation.py:编写脚本对不同模型架构、超参数组合进行快速实验,对比实验结果,寻找最优模型设置。

    这部分往往是最开始的探索阶段,后面跑通了后拆分成了完整的项目,留作纪念用。

4. 项目产出物管理

  • data/ 目录:存放项目相关数据。
    • data/raw/:放置从外部获取的未经处理的原始数据,保持数据原始状态。
    • data/processed/:存放经过预处理(清洗、转换、特征工程等操作)后的数据,供模型训练和评估使用。
    • data/interim/:(可选)保存中间处理结果,比如数据清洗过程中生成的临时文件、特征工程中间步骤产生的数据等。
  • models/ 目录:专门存放训练好的模型文件,根据模型保存格式不同,可能是 .pkl(Python pickle 格式,常用于保存 sklearn 模型 )、.h5(常用于保存 Keras 模型 )、.joblib 等。
  • reports/ 或 output/ 目录:存储项目运行产生的各类报告和输出文件。
    • reports/evaluation_report.txt:记录模型评估的详细结果,包括各项评估指标数值、模型性能分析等。
    • reports/visualizations/:存放数据可视化图片,如损失函数收敛图、预测结果对比图等。
    • output/logs/:保存项目运行日志文件,记录项目从开始到结束过程中的关键信息,如训练开始时间、训练过程中的损失值变化、预测时间等。

总结一下通用的拆分起步思路:

  1. 首先,按照机器学习的主要工作流程(数据处理、训练、评估等)将代码分离到不同的 .py 文件中。 这是最基本也是最有价值的一步。
  2. 然后,创建一个 utils.py 来存放通用的辅助函数。
  3. 考虑将所有配置参数集中到一个 config.py 文件中。
  4. 为你的数据和模型产出物创建专门的顶层目录,如 data/ 和 models/,将它们与你的源代码(通常放在 src/ 目录)分开。

当遵循这些通用的拆分思路和原则时,项目结构自然会变得清晰。


三、注意事项

if name == "main"

常常会看到if name == "main"这个写法,实际上,每个文件都是一个对象,对象就会有属性和方法。

如果直接运行这个文件,则__name__等于__main__,若这个文件被其他模块导入,则__name__不等于__main__。

这个写法有如下好处:

  1. 明确程序起点:一个 Python 项目往往由多个模块组成。if name == "main" 可清晰界定程序执行的起始位置。比如一个包含数据处理模块 data_processing.py、模型训练模块 model_training.py 的机器学习项目,在 model_training.py 中用 if name == "main" 包裹训练相关的主逻辑代码,运行该文件时就知道需要从这里开始执行(其他文件都是附属文件),让项目结构和执行流程更清晰。(大多时候如此)

  2. 避免执行:python遵从模块导入即执行机制,当你使用 import xxx 导入一个模块时,Python 会执行该模块中的所有顶层代码(即不在任何函数或类内部的代码)。如果顶层代码中定义了全局变量或执行了某些操作(如读取文件、初始化数据库连接),这些操作会在导入时立即生效,并可能影响整个程序的状态。为了避免执行不必要的代码,我们可以使用 if name == "main" 来避免在导入时执行不必要的代码。这样,只有当模块被直接运行时(即被执行 python xxx.py),才会执行顶层代码,而导入时则不会执行。这样,我们就可以确保在导入模块时,不会执行不必要的代码,从而提高程序的性能和可维护性。

  3. 合理的资源管理:if name == "main" 与定义 main 函数结合使用,函数内变量在函数执行完这些变量被释放,能及时回收内存资源,避免内存泄漏,保证程序高效运行。

编码格式

规范的py文件,首行会有:# -- coding: utf-8 --

主要目的是 显式声明文件的编码格式,确保 Python 解释器能正确读取和解析文件中的非 ASCII 字符(如中文、日文、特殊符号等)。也就是说这个是写给解释器看的。

因为,在 Python 2.x 时代,默认编码是 ASCII,不支持直接在代码中写入非 ASCII 字符(如中文注释、字符串中的中文),否则会报错(SyntaxError: Non-UTF-8 code starting with...)。但是Python 3.x 默认为 UTF-8 编码,理论上可以省略编码声明。但实际开发中,为了兼容旧代码、明确文件编码规则,或在团队协作中避免因编辑器 / 环境配置不同导致的乱码问题,许多开发者仍会保留这一行声明。

ps:

  1. 编码声明必须出现在文件的前两行(通常是首行),否则会被忽略。
  2. 如果编码格式没问题,可能是vscode的编码格式不是utf-8,可以尝试修改编码格式。
  3. 常见的编码报错是因为字符串编码问题,可以尝试显式转化,即读取的时候转化为utf-8编码。

非 ASCII 字符的代码如下所示:

# -*- coding: utf-8 -*-
msg = "你好,世界!"  # 中文字符串
print(msg)
你好,世界!

很多时候,项目中会包含gitattribute文件,来确保在不同操作系统和编辑器中,文件的编码格式一致。这里我们后面说到git工具再介绍

类型注解

Python 的类型注解是在 Python 3.5+ 引入的特性,用于为变量、函数参数、返回值和类属性等添加类型信息。虽然 Python 仍是动态类型语言,但类型注解可以提高代码可读性、可维护性,并支持静态类型检查工具(如 mypy)。

其次你在安装python插件的时候,附带安装了2个插件

  1. 一个是python debugger用于断点调试,我们已经介绍了
  2. 另一个是pylance,用于代码提示和类型检查,这个插件会根据你的代码中的类型注解,给出相应的提示和检查,比如你定义了一个函数,参数类型是int,那么当你传入一个字符串时,它会提示你传入的参数类型不正确。

变量类型注解语法为 变量名: 类型

# 变量的类型注解
name: str = "Alice"
age: int = 30
height: float = 1.75
is_student: bool = False

函数类型注解为函数参数和返回值指定类型,语法为 def 函数名(参数: 类型) -> 返回类型。

def add(a: int, b: int) -> int:return a + bdef greet(name: str) -> None:print(f"Hello, {name}")

类属性与方法的类型注解:为类的属性和方法添加类型信息。

# 定义一个矩形类
class Rectangle:width: float      # 矩形宽度(浮点数),类属性的类型注解(不初始化值)height: float     # 矩形高度(浮点数)def __init__(self, width: float, height: float):self.width = widthself.height = heightdef area(self) -> float:# 计算面积(宽度 × 高度)return self.width * self.height

上述的width: float # 矩形宽度(浮点数)这个写法由于没有对变量赋值,所以是一种类型注解写法


四、通俗解释

好的!我用最直白的大白话,结合生活场景,帮你理解今天的内容:


1. 拆分文件和目录:整理房间一样管理代码​

​核心思想​​:
把一个大项目拆成多个小文件,就像整理房间时把衣服放衣柜、书放书架、工具放工具箱。

  • ​好处​​:找东西方便、改bug不用到处翻、代码可以重复使用。
  • ​举个栗子​​:
    • data_loader.py → 专门负责从Excel/数据库里“搬数据”。
    • model.py → 专门定义机器学习模型的“长相”(比如神经网络有几层)。
    • utils.py → 存放万能小工具,比如计算平均数、画图函数。

2. 导入模块:把其他房间的东西拿来用​

​核心思想​​:
如果一个文件A想用另一个文件B的函数,就像从隔壁房间借杯子喝水,需要“打招呼”(导入)。

  • ​关键点​​:
    • 文件要放在正确的位置(比如都放在同一个大文件夹里)。
    • 导入语句要写对路径,比如 from data.data_loader import load_data

3. 机器学习项目流程:像做菜的步骤​

  1. ​买菜(数据加载)​​:从超市(文件)买来原始食材(数据)。
  2. ​洗菜切菜(预处理)​​:去掉烂叶子(处理缺失值),切块(标准化)。
  3. ​炒菜(训练模型)​​:按照菜谱(超参数)翻炒(训练)。
  4. ​尝味道(评估)​​:让朋友试吃,打分(准确率、损失值)。
  5. ​上菜(预测)​​:用这个菜谱给新客人做饭(新数据预测)。

​4. 项目目录结构:给代码盖一栋楼​

  • ​一楼(src)​​:放核心代码,按功能分房间:
    • data/ → 数据处理相关文件(加载、清洗)。
    • models/ → 模型定义、训练、评估。
    • utils/ → 工具函数(比如画图、读文件)。
  • ​二楼(data)​​:放食材(数据),分生菜(原始数据)和熟菜(处理后的数据)。
  • ​三楼(notebooks)​​:像草稿纸,用Jupyter快速试菜(实验)。
  • ​四楼(reports)​​:放成品(模型文件)、菜谱说明书(评估报告)。

​5. 配置文件:菜谱参数集中管理​

  • ​为什么需要​​:比如“盐放多少克”写在菜谱里,不用每次炒菜都问别人。
  • ​举个栗子​​:
    • config.yaml → 存参数(学习率=0.01,训练轮数=100)。
    • .env → 存密码(数据库密码、API密钥),像保险箱,代码里通过环境变量读取。

6. 编码格式:统一语言,避免鸡同鸭讲​

  • ​核心​​:在Python文件开头写 # -*- coding: utf-8 -*-,告诉电脑:“这个文件里可能有中文,请用UTF-8编码读我!”
  • ​常见问题​​:如果出现乱码,检查文件是否保存为UTF-8格式(VSCode右下角可改)。

​7. 类型注解:给代码贴标签,防迷糊​

  • ​举个栗子​​:
    def add(a: int, b: int) -> int:return a + b
    • 这表示:ab必须是整数,返回值也是整数。
    • ​好处​​:写代码时像做选择题,错误选项会被工具(如PyCharm)标红提醒。

​8. if name == "main":区分“自用”和“被调用”​

  • ​核心​​:
    • 如果直接运行这个文件(比如 python my_script.py),下面的代码会执行。
    • 如果这个文件被其他文件导入(比如 import my_script),下面的代码不会执行。
  • ​举个栗子​​:
    # my_script.py
    def main():print("Hello!")if __name__ == "__main__":main()  # 只有直接运行这个文件时才会打印Hello!

9. ​​总结:今天学了啥?​

  1. ​整理代码​​:像收拾房间一样分门别类。
  2. ​导入模块​​:从别的文件“借东西”要用正确姿势。
  3. ​项目流程​​:做机器学习像炒菜,步骤不能乱。
  4. ​配置文件​​:参数集中管理,改起来方便。
  5. ​类型注解​​:给代码贴标签,减少低级错误。
  6. ​编码格式​​:统一语言,避免乱码“鸡同鸭讲”。

​一句话​​:今天学的都是如何让代码更整洁、更易维护、更容易和别人合作!就像学做饭要先学会整理厨房~ 


五、作业

将心脏病项目整理为规范结构:尝试针对之前心脏病项目ipynb,将它按照今天的示例项目整理成规范的形式,思考下哪些部分可以未来复用

以下是按照机器学习项目标准流程拆分的代码结构,分为可复用模块和项目主流程:

​1. 项目目录结构​

heart_disease_project/
├── config/
│ ├── config.yaml # 配置文件(数据路径、模型参数)
│ └── .env # 敏感信息(数据库密码等)
├── data/
│ ├── raw/ # 原始数据(heart.csv)
│ ├── processed/ # 处理后的数据(heart_processed.csv)
├── src/
│ ├── data/
│ │ ├── load_data.py # 数据加载
│ │ ├── preprocess.py # 数据预处理(清洗、编码)
│ │ └── explore.py # 数据探索(可视化、统计)
│ ├── models/
│ │ ├── train.py # 模型训练(随机森林)
│ │ ├── evaluate.py # 模型评估(混淆矩阵、ROC)
│ │ └── explain.py # 可解释性分析(SHAP、PDP)
│ └── utils/
│ ├── io_utils.py # 文件读写工具
│ └── plot_utils.py # 通用绘图函数
├── notebooks/ # Jupyter Notebook(实验草稿)
├── reports/
│ ├── figures/ # 可视化图片
│ └── evaluation_report.md
├── main.py # 项目入口脚本
└── requirements.txt # 依赖包列表


​2. 模块化代码示例​

(1)src/data/load_data.py - 数据加载
import pandas as pd
from config.settings import DATA_PATHdef load_raw_data() -> pd.DataFrame:"""加载原始数据"""df = pd.read_csv(DATA_PATH["raw"])return dfdef load_processed_data() -> pd.DataFrame:"""加载预处理后的数据"""df = pd.read_csv(DATA_PATH["processed"])return df
(2)src/data/preprocess.py - 数据预处理
import pandas as pd
from config.settings import CATEGORICAL_COLS, DROP_FIRSTdef rename_columns(df: pd.DataFrame) -> pd.DataFrame:"""重命名列名(增强可读性)"""rename_map = {"age": "age","sex": "sex","cp": "chest_pain_type",# ... 其他列名映射}return df.rename(columns=rename_map)def encode_categorical(df: pd.DataFrame) -> pd.DataFrame:"""对分类变量进行编码"""df = df.astype({col: "category" for col in CATEGORICAL_COLS})df = pd.get_dummies(df, columns=CATEGORICAL_COLS, drop_first=DROP_FIRST)return df
(3)src/models/train.py - 模型训练
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from src.data.load_data import load_processed_datadef train_model(test_size: float = 0.2) -> RandomForestClassifier:"""训练随机森林模型"""X, y = load_processed_data().drop("target"), load_processed_data()["target"]X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_size)model = RandomForestClassifier(max_depth=5, n_estimators=10)model.fit(X_train, y_train)return model
(4)src/models/explain.py - 可解释性分析
import shap
from src.models.train import train_modeldef analyze_shap_values() -> None:"""使用SHAP分析特征重要性"""model = train_model()explainer = shap.TreeExplainer(model)shap_values = explainer.shap_values(X_test)shap.summary_plot(shap_values, X_test)

3. ​​配置文件示例​

config/config.yaml
data:raw: "./data/raw/heart.csv"processed: "./data/processed/heart_processed.csv"model:type: "random_forest"params:max_depth: 5n_estimators: 10

4. ​​可复用代码的核心原则​

  1. ​模块化设计​

    • 数据加载、预处理、模型训练等步骤封装成独立函数/类。
    • 示例:preprocess.py 中的 encode_categorical 可被其他项目复用。
  2. ​配置与代码分离​

    • 数据路径、模型参数通过 config.yaml 管理,无需硬编码。
    • 修改参数时只需调整配置文件,无需改动代码。
  3. ​工具函数封装​

    • 通用功能(如文件读写、绘图)放在 utils/ 目录。
    • 示例:plot_utils.py 可包含 plot_roc_curve 等通用绘图函数。
  4. ​入口脚本统一调用​

    • main.py 调用各模块完成完整流程:
      from src.data.load_data import load_raw_data
      from src.models.train import train_model
      from src.models.explain import analyze_shap_valuesif __name__ == "__main__":df = load_raw_data()df = preprocess_data(df)model = train_model(df)evaluate_model(model, df)analyze_shap_values(model)

5. ​​未来可复用的部分​

模块/函数复用场景复用方法
load_data.py其他数据科学项目直接调用 load_raw_data()
preprocess.py数据清洗、特征工程调整 CATEGORICAL_COLS 后复用
train.py训练不同模型(如XGBoost)修改模型类即可
shap_analysis.py任何模型的可解释性分析替换 explainer 类型

6. ​​执行方式​

  1. ​开发模式​​:在 Jupyter Notebook 中逐步调试(notebooks/)。
  2. ​生产模式​​:运行 main.py 一键完成全流程。
  3. ​复用代码​​:复制 src/ 目录到新项目,调整配置文件即可。

通过这种结构化设计,代码的维护成本降低,团队协作效率显著提升。


@浙大疏锦行

相关文章:

  • Modbus通信协议详解
  • 基于FFT变换的雷达信号检测和参数估计matlab性能仿真
  • 【SPIN】PROMELA远程引用与控制流验证(SPIN学习系列--5)
  • AI练习:毛发旋转效果
  • SPATA2·在空转中推断组织学相关基因表达梯度
  • (T_T),不小心删掉RabbitMQ配置文件数据库及如何恢复
  • BI行业分析思维框架 - 环保行业分析(一)
  • Metal入门,使用Metal绘制3D图形
  • Java泛型 的详细知识总结
  • 【C# 自动化测试】Selenium显式等待机制详解
  • 考研系列-408真题计算机组成原理篇(2020-2023)
  • 如何利用 Java 爬虫根据 ID 获取某手商品详情:实战指南
  • Docker-Harbor 私有镜像仓库使用指南
  • 小白编程学习之巧解「消失的数字」
  • 2025年JIII SCI1区TOP,多策略霜冰优化算法IRIME+无人机路径规划,深度解析+性能实测
  • (2)JVM 内存模型更新与 G1 垃圾收集器优化
  • 电子科技大学软件工程实践期末
  • USB转TTL
  • 智能笔记助手-NotepadAI使用指南
  • 多线程(六)
  • 重庆黔江一足疗养生馆负责人涉嫌违法犯罪被移送检察机关
  • 焦点访谈丨售假手段又翻新,警惕化肥“忽悠团”的坑农套路
  • 来论|以法治之力激发民营经济新动能
  • 鸿蒙电脑正式发布,余承东:国产软件起步晚,基础弱,探索面向未来的电脑体验
  • 减负举措如何助力基层干部轻装上阵?记者一线调查
  • 倒计时1天:走进“中国荔乡”茂名,探寻农交文旅商融合发展新模式