Week 07:统计机器学习项目启动、数据卡与 Baseline

发布于 2026-07-26 07:00 5145 字 26 min read

Week 07:统计机器学习项目启动、数据卡与 Baseline。fish-first 终端教学,面向 CachyOS、VS Code、uv 和 Python 学习路线。
Oh My Pi / weekly tutorial / week07-stat-ml-project-start
miku@cachyos:~/Code/python-learning$ omp teach week07-stat-ml-project-start --fish-first --step-by-step
source710 行教学文档
weekWeek 07
shellfish-first 命令版
backlink20 周计划

Week 07:统计机器学习项目启动、数据卡与 Baseline

返回主线计划:USTC 统计学:AI / 量化金融 20 周终端式成长计划

Week 05-06 你已经能训练 sklearn baseline、做交叉验证和模型选择。Week 07 开始把这些能力组织成一个可以展示的统计机器学习项目。目标不是“写很多模型”,而是让一个陌生人打开你的仓库后能看懂:问题是什么、数据从哪里来、如何运行、baseline 是什么、目前错误在哪里。

本文默认 CachyOS + fish shell + VS Code + uv + Python + Git。命令按 fish 写。

0. 本周详细教学:语法、规范、验收

本节不是追加在尾部的复习,而是本周正文的入口。先读这里,再做后面的命令和项目。

0.1 本周真正要学会什么

维度要求
知识点问题定义、数据卡、baseline、特征工程计划
代码语法能从空文件写出本周核心脚本,而不是只复制运行
程序规范函数拆分、路径清楚、输入输出明确、错误能解释
交付物projects/stat-ml-baseline/README.md
验收方式从 fish 终端运行命令,得到可复查的文件或指标

0.2 代码语法精讲

下面的代码不是最终答案,而是本周必须理解的最小骨架:

omppython
problem = {
    "target": "predict whether sample is positive",
    "unit": "one row is one observation",
    "baseline": "DummyClassifier + LogisticRegression",
    "risk": "target leakage from future columns",
}
for k, v in problem.items():
    print(f"{k}: {v}")

读代码时按四步检查:输入从哪里来;中间变量的类型和 shape 是什么;函数或脚本输出什么;哪些错误应该显式报出来。

0.3 本周程序规范

  • 所有路径用相对路径或 `pathlib.Path`,不要写死 `/home/miku/...`。
  • 核心逻辑进 `src/`,notebook 只做探索和解释。
  • 每个脚本能从 fish 终端运行,并在 README 写出命令。
  • 输出必须落盘到 `reports/`、`figures/` 或 `outputs/`,不能只在屏幕上看。

0.4 本周练习分层

层级任务不合格表现合格验收
最小练习手写上面的最小骨架只在 notebook 里运行终端运行成功
标准练习把逻辑拆成函数/模块一个大脚本从头写到尾至少 2 个函数,职责清楚
项目练习生成本周交付物 projects/stat-ml-baseline/README.md只有屏幕输出文件落盘,可复查
复盘练习写 3 个错误和修复只写“已解决”写清报错、原因、修复、预防

0.5 本周和主线的连接

1. 本周目标

创建一个完整项目骨架:

ompprompt
projects/stat-ml-baseline/
├── README.md
├── data/
├── docs/
├── notebooks/
├── reports/
└── src/

并完成四个核心产物:

  • docs/data_card.md:说明数据来源、字段、目标变量、限制。
  • src/train_baseline.py:能训练并输出 baseline 结果。
  • reports/baseline_results.md:记录模型、指标、划分方式、初步结论。
  • reports/error_analysis.md:分析错误样本与下一步改进。

本周你要从“脚本能跑”升级为“项目能被别人理解”。

2. 前置条件

你应该已经完成:

  • Week 05:train / validation / test、多个 baseline、分类或回归指标。
  • Week 06:KFold / StratifiedKFold、Pipeline、GridSearchCV、防泄漏。
  • Week 03-04:pandas 清洗、EDA 图表、报告写作。
  • Git 基础:git statusgit addgit commit

检查工具:

ompfish
python --version
uv --version
git --version
code --version

如果你刚打开新终端,后面每次运行项目前都先激活:

ompfish
source .venv/bin/activate.fish

3. 选题原则

推荐题目:

ompprompt
基于统计学习的表格数据预测与误差分析

你可以选择:

  • Kaggle 入门数据:Titanic、House Prices、Spaceship Titanic。
  • UCI 数据集:Adult Income、Wine Quality、Bank Marketing。
  • 金融或经济公开数据:指数收益、宏观指标、公司财务指标。
  • 校内课程数据:只要不涉及隐私或不可公开数据。

选择标准:

标准 建议
数据规模 初学项目优先 500 到 100000 行,不要一开始选超大数据
数据类型 表格数据优先,特征包括数值和类别都可以
目标变量 明确:分类或回归,不要模糊
可解释性 能讲清楚每个字段大概含义
合法性 数据来源可引用,不含隐私或违反平台条款

如果不知道选什么,建议用 UCI Wine Quality 或 Kaggle Titanic。它们简单、可解释、适合展示完整流程。

4. 建立项目目录

在学习总目录下创建项目:

ompfish
cd ~/Code/python-learning
mkdir -p projects
cd projects
mkdir -p stat-ml-baseline
cd stat-ml-baseline
pwd

初始化 Python 项目:

ompfish
uv init
uv venv
source .venv/bin/activate.fish
uv add pandas numpy scikit-learn matplotlib seaborn tabulate

创建目录:

ompfish
mkdir -p data/raw data/interim data/processed docs notebooks reports src

用 VS Code 打开:

ompfish
code .

5. 文件布局

建议结构:

ompprompt
stat-ml-baseline/
├── .venv/                       # 本地虚拟环境,不提交
├── data/
│   ├── raw/                     # 原始数据,只读
│   ├── interim/                 # 中间处理结果
│   └── processed/               # 建模用数据
├── docs/
│   └── data_card.md             # 数据卡
├── notebooks/
│   └── 01_eda.ipynb             # 可选:探索分析
├── reports/
│   ├── baseline_results.md      # baseline 结果
│   └── error_analysis.md        # 错误分析
├── src/
│   ├── train_baseline.py        # 训练入口
│   └── make_dataset.py          # 可选:数据清洗入口
├── pyproject.toml
├── uv.lock
└── README.md

目录职责要清楚:

目录 职责
data/raw/ 放原始数据,不在里面手工改值
data/interim/ 放临时清洗结果,可删除重建
data/processed/ 放最终建模输入
docs/ 放数据说明、设计说明
notebooks/ 放探索性分析,不做最终训练入口
reports/ 放实验结果和错误分析
src/ 放可重复运行的 Python 脚本

6. 创建 README 初稿

打开 README.md,先写一个能说明项目方向的初稿。不要等项目结束才写 README,否则你会忘记很多设计选择。

建议结构:

ompmarkdown
# Statistical Machine Learning Baseline

Problem

This project predicts … using tabular data. The task is classification / regression.

Data

  • Source:
  • Rows:
  • Columns:
  • Target:
  • Unit of observation:

Method

  • Baseline models:
  • Validation strategy:
  • Main metric:

Current Status

Week 07 project start. Baseline and error analysis are in progress.

How to Run

  1. Create and activate a uv virtual environment.
  2. Install dependencies.
  3. Run the baseline script.

这不是最终版。Week 08 会继续打磨 README。本周的 README 只要能帮助你保持项目方向即可。

7. 创建数据卡

创建文件:

ompprompt
docs/data_card.md

建议内容:

ompmarkdown
# Data Card

Dataset Name

Write the dataset name here.

Source

  • URL:
  • License or access condition:
  • Download date:

Prediction Target

  • Target column:
  • Task type: classification / regression
  • Positive class definition if classification:

Unit of Observation

One row represents …

Columns

ColumnTypeMeaningNotes
example_columnnumeric

Missing Values

Describe missing columns and possible reasons.

Known Limitations

  • Sampling bias:
  • Time period limitation:
  • Measurement errors:
  • Possible leakage columns:

Ethical or Privacy Notes

State whether the dataset contains personal, financial, medical, or sensitive information.

数据卡不是形式主义。它能防止你在 Week 08 写报告时讲不清数据来源。

8. 下载或放入数据

如果数据已经手动下载,把 CSV 放到:

ompprompt
data/raw/dataset.csv

用 fish 检查文件:

ompfish
ls data/raw

如果你用 Kaggle,不建议本教程里展开认证流程。初学阶段可以手动从网页下载 zip,再解压到 data/raw/。如果使用 UCI 的公开 CSV,可以用浏览器下载,或者用 Python 下载。

重要原则:

ompprompt
原始数据进 data/raw/
脚本生成的数据进 data/processed/
不要在 Excel 里手改原始数据后覆盖 raw 文件

9. 如果暂时没有数据:使用 sklearn 数据集占位

为了先搭项目骨架,可以用 sklearn 自带数据集跑通流程。等你选定真实数据后再替换 load_data()

本教程下面使用 breast cancer dataset 做可运行示例。它不是你的最终项目题目也没关系;Week 07 重点是项目结构。

10. 编写 baseline 训练脚本

创建文件:

ompprompt
src/train_baseline.py

粘贴下面代码:

omppython
from pathlib import Path

import pandas as pd from sklearn.datasets import load_breast_cancer from sklearn.ensemble import RandomForestClassifier from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score, confusion_matrix, f1_score, precision_score, recall_score, roc_auc_score from sklearn.model_selection import StratifiedKFold, cross_validate, train_test_split from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler

RANDOM_STATE = 42 RESULT_PATH = Path(“reports/baseline_results.md”) ERROR_PATH = Path(“reports/error_analysis.md”)

def load_project_data(): dataset = load_breast_cancer(as_frame=True) X = dataset.data y = dataset.target return X, y, list(dataset.target_names)

def build_models(): return { “logistic_regression”: Pipeline( steps=[ (“scaler”, StandardScaler()), (“model”, LogisticRegression(max_iter=3000, random_state=RANDOM_STATE)), ] ), “random_forest”: RandomForestClassifier( n_estimators=200, max_depth=None, min_samples_leaf=1, random_state=RANDOM_STATE, ), }

def score_models(models, X_train, y_train): cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=RANDOM_STATE) scoring = { “accuracy”: “accuracy”, “precision”: “precision”, “recall”: “recall”, “f1”: “f1”, “roc_auc”: “roc_auc”, } rows = [] for name, model in models.items(): scores = cross_validate(model, X_train, y_train, cv=cv, scoring=scoring, n_jobs=-1) row = {“model”: name} for metric in scoring: values = scores[f”test_{metric}”] row[f”{metric}_mean”] = values.mean() row[f”{metric}_std”] = values.std() rows.append(row) return sorted(rows, key=lambda item: item[“f1_mean”], reverse=True)

def evaluate_final_model(model, X_train, X_test, y_train, y_test): model.fit(X_train, y_train) predictions = model.predict(X_test) probabilities = model.predict_proba(X_test)[:, 1] metrics = { “accuracy”: accuracy_score(y_test, predictions), “precision”: precision_score(y_test, predictions), “recall”: recall_score(y_test, predictions), “f1”: f1_score(y_test, predictions), “roc_auc”: roc_auc_score(y_test, probabilities), } matrix = confusion_matrix(y_test, predictions) errors = X_test.assign(actual=y_test.to_numpy(), predicted=predictions, probability=probabilities) errors = errors[errors[“actual”] != errors[“predicted”]] return metrics, matrix, errors

def write_baseline_report(rows, test_metrics, target_names): table_rows = [] for row in rows: table_rows.append( ”| {model} | {f1_mean:.4f} | {f1_std:.4f} | {roc_auc_mean:.4f} | {recall_mean:.4f} |“.format( **row ) )

plain report = f"""# Baseline Results

Dataset

  • Dataset: sklearn breast cancer dataset or project replacement dataset
  • Target names:
  • Task: binary classification

Validation Design

  • Holdout test size: 20%
  • Cross validation: StratifiedKFold with 5 folds on the training portion
  • Selection metric: mean CV F1
  • Random state:

Cross-Validation Results

ModelMean F1Std F1Mean ROC AUCMean Recall
{chr(10).join(table_rows)}

Final Test Metrics

MetricValue
Accuracy{test_metrics[‘accuracy’]:.4f}
Precision{test_metrics[‘precision’]:.4f}
Recall{test_metrics[‘recall’]:.4f}
F1{test_metrics[‘f1’]:.4f}
ROC AUC{test_metrics[‘roc_auc’]:.4f}

Notes

  • Replace this section with your interpretation.
  • Explain why the chosen metric matches the project goal.
  • Compare the model against a naive baseline if possible. """ RESULT_PATH.parent.mkdir(parents=True, exist_ok=True) RESULT_PATH.write_text(report, encoding=“utf-8”)

def write_error_analysis(matrix, errors): preview = errors.head(10).round(4).to_markdown(index=False) report = f"""# Error Analysis

Confusion Matrix

Rows are actual labels, columns are predicted labels.

{matrix}
</code></pre></div>
<h2>Wrong Prediction Preview</h2>
<p>{preview}</p>
<h2>Observations To Fill In</h2>
<ul>
<li>What type of mistake appears most often?</li>
<li>Are false positives or false negatives more costly?</li>
<li>Do wrong predictions have low confidence or high confidence?</li>
<li>Which features look unusual among wrong predictions?</li>
<li>What data cleaning or feature engineering should be tried next?
&quot;&quot;&quot;
  ERROR_PATH.parent.mkdir(parents=True, exist_ok=True)
  ERROR_PATH.write_text(report, encoding=&quot;utf-8&quot;)</li>
</ul>
<p>def main():
    X, y, target_names = load_project_data()
    X_train, X_test, y_train, y_test = train_test_split(
        X,
        y,
        test_size=0.2,
        random_state=RANDOM_STATE,
        stratify=y,
    )
    models = build_models()
    rows = score_models(models, X_train, y_train)
    best_name = rows[0][&quot;model&quot;]
    test_metrics, matrix, errors = evaluate_final_model(models[best_name], X_train, X_test, y_train, y_test)</p>
<div class="omp-code-frame" data-lang="prompt"><div class="omp-code-bar"><span>omp</span><span>prompt</span></div><pre><code>write_baseline_report(rows, test_metrics, target_names)
write_error_analysis(matrix, errors)

print(pd.DataFrame(rows).round(4).to_string(index=False))
print()
print(&quot;Selected model:&quot;, best_name)
print(&quot;Reports written:&quot;, RESULT_PATH, ERROR_PATH)
</code></pre></div>
<p>if <strong>name</strong> == &quot;<strong>main</strong>&quot;:
    main()</p>
<div class="omp-code-frame" data-lang="prompt"><div class="omp-code-bar"><span>omp</span><span>prompt</span></div><pre><code>
## 11. 运行 baseline

```fish
source .venv/bin/activate.fish
python src/train_baseline.py
</code></pre></div>
<p>应该生成:</p>
<div class="omp-code-frame" data-lang="prompt"><div class="omp-code-bar"><span>omp</span><span>prompt</span></div><pre><code class="language-text">reports/baseline_results.md
reports/error_analysis.md
</code></pre></div>
<p>检查:</p>
<div class="omp-code-frame" data-lang="fish"><div class="omp-code-bar"><span>omp</span><span>fish</span></div><pre><code class="language-fish">test -f reports/baseline_results.md; and echo &quot;baseline report exists&quot;
test -f reports/error_analysis.md; and echo &quot;error analysis exists&quot;
</code></pre></div>
<p>打开报告:</p>
<div class="omp-code-frame" data-lang="fish"><div class="omp-code-bar"><span>omp</span><span>fish</span></div><pre><code class="language-fish">code reports/baseline_results.md reports/error_analysis.md
</code></pre></div>
<h2>12. 把示例数据替换成真实项目数据</h2>
<p>假设真实 CSV 是:</p>
<div class="omp-code-frame" data-lang="prompt"><div class="omp-code-bar"><span>omp</span><span>prompt</span></div><pre><code class="language-text">data/raw/train.csv
</code></pre></div>
<p>目标列叫:</p>
<div class="omp-code-frame" data-lang="prompt"><div class="omp-code-bar"><span>omp</span><span>prompt</span></div><pre><code class="language-text">target
</code></pre></div>
<p>可以把 <code>load_project_data()</code> 改成:</p>
<div class="omp-code-frame" data-lang="python"><div class="omp-code-bar"><span>omp</span><span>python</span></div><pre><code class="language-python">def load_project_data():
    data = pd.read_csv(&quot;data/raw/train.csv&quot;)
    X = data.drop(columns=[&quot;target&quot;])
    y = data[&quot;target&quot;]
    target_names = sorted(y.astype(str).unique().tolist())
    return X, y, target_names
</code></pre></div>
<p>如果有类别变量,你需要在 Week 06 学过的 <code>ColumnTransformer</code> 中处理。不要用“随便把字符串替换成 0、1、2”的方式编码城市、行业、学校等无序类别。</p>
<h2>13. 明确问题定义</h2>
<p>在 README 的 <code>Problem</code> 部分回答:</p>
<div class="omp-code-frame" data-lang="prompt"><div class="omp-code-bar"><span>omp</span><span>prompt</span></div><pre><code class="language-text">我要预测什么?
为什么这个预测有意义?
每一行数据代表什么?
目标变量是如何定义的?
预测提前量是多少?
这个项目是分类还是回归?
</code></pre></div>
<p>示例:</p>
<div class="omp-code-frame" data-lang="prompt"><div class="omp-code-bar"><span>omp</span><span>prompt</span></div><pre><code class="language-text">This project predicts whether a passenger survived on the Titanic using passenger-level tabular features. Each row is one passenger. The target is Survived, where 1 means survived and 0 means not survived. This is a binary classification task.
</code></pre></div>
<p>统计学学生尤其要注意“单位”。一行是一个人、一家公司、一天、一笔交易,分析意义完全不同。</p>
<h2>14. 建立 naive baseline</h2>
<p>除了 sklearn 模型,还应该有 naive baseline。</p>
<p>分类任务:</p>
<div class="omp-code-frame" data-lang="prompt"><div class="omp-code-bar"><span>omp</span><span>prompt</span></div><pre><code class="language-text">永远预测训练集中最多的类别
</code></pre></div>
<p>回归任务:</p>
<div class="omp-code-frame" data-lang="prompt"><div class="omp-code-bar"><span>omp</span><span>prompt</span></div><pre><code class="language-text">永远预测训练集目标变量均值或中位数
</code></pre></div>
<p>你可以在报告中写:</p>
<div class="omp-code-frame" data-lang="prompt"><div class="omp-code-bar"><span>omp</span><span>prompt</span></div><pre><code class="language-text">Naive baseline: always predict the majority class.
F1 is low because the model never identifies minority-class cases.
</code></pre></div>
<p>这样可以证明 sklearn 模型不仅比随机好,也比最简单策略好。</p>
<h2>15. 初步错误分析怎么做</h2>
<p>不要只看总分。打开 <code>reports/error_analysis.md</code>,观察错误样本:</p>
<div class="omp-code-frame" data-lang="fish"><div class="omp-code-bar"><span>omp</span><span>fish</span></div><pre><code class="language-fish">code reports/error_analysis.md
</code></pre></div>
<p>写下:</p>
<table>
<thead>
<tr>
<th>问题</th>
<th>例子</th>
</tr>
</thead>
<tbody><tr>
<td>哪类错误更多</td>
<td>false positives 多,还是 false negatives 多</td>
</tr>
<tr>
<td>错误样本有什么共同点</td>
<td>某些特征极端、缺失多、靠近决策边界</td>
</tr>
<tr>
<td>指标是否符合目标</td>
<td>如果漏判代价高,recall 是否足够</td>
</tr>
<tr>
<td>是否需要新特征</td>
<td>比如比例、分组统计、时间窗口</td>
</tr>
<tr>
<td>是否可能有数据问题</td>
<td>标签噪声、重复样本、泄漏列</td>
</tr>
</tbody></table>
<p>错误分析的价值在于指导 Week 08 的改进,不是为了装饰报告。</p>
<h2>16. README 本周至少要写到什么程度</h2>
<p>Week 07 的 README 不要求完美,但至少包含:</p>
<div class="omp-code-frame" data-lang="prompt"><div class="omp-code-bar"><span>omp</span><span>prompt</span></div><pre><code class="language-text">项目标题
问题定义
数据来源
目标变量
运行命令
当前 baseline 结果链接
下一步计划
</code></pre></div>
<p>运行命令可以写成:</p>
<div class="omp-code-frame" data-lang="fish"><div class="omp-code-bar"><span>omp</span><span>fish</span></div><pre><code class="language-fish">uv venv
source .venv/bin/activate.fish
uv sync
python src/train_baseline.py
</code></pre></div>
<p>如果你用了手动下载数据,README 必须说明数据应该放在哪里:</p>
<div class="omp-code-frame" data-lang="prompt"><div class="omp-code-bar"><span>omp</span><span>prompt</span></div><pre><code class="language-text">Download the dataset and place the CSV at data/raw/train.csv.
</code></pre></div>
<p>不要让读者猜文件名。</p>
<h2>17. Git 提交</h2>
<p>先创建 <code>.gitignore</code>,内容至少包括:</p>
<div class="omp-code-frame" data-lang="prompt"><div class="omp-code-bar"><span>omp</span><span>prompt</span></div><pre><code class="language-text">.venv/
__pycache__/
.ipynb_checkpoints/
.DS_Store
data/raw/*.zip
</code></pre></div>
<p>如果原始 CSV 很大,或数据许可不允许发布,也把它加入 <code>.gitignore</code>。然后提交:</p>
<div class="omp-code-frame" data-lang="fish"><div class="omp-code-bar"><span>omp</span><span>fish</span></div><pre><code class="language-fish">git status --short
git add README.md docs reports src pyproject.toml uv.lock .gitignore
git commit -m &quot;Start statistical machine learning baseline project&quot;
</code></pre></div>
<p>如果这是你第一次在该目录使用 Git:</p>
<div class="omp-code-frame" data-lang="fish"><div class="omp-code-bar"><span>omp</span><span>fish</span></div><pre><code class="language-fish">git init
</code></pre></div>
<p>再执行上面的 <code>git add</code> 与 <code>git commit</code>。</p>
<h2>18. 本周练习</h2>
<ol>
<li>在 <code>docs/data_card.md</code> 中写完至少 10 个字段的说明。</li>
<li>在 README 中用 5 句话讲清楚问题定义。</li>
<li>加入 naive baseline,并在报告中比较 naive baseline 与 sklearn baseline。</li>
<li>把错误样本保存为 <code>reports/wrong_predictions.csv</code>,用 pandas 查看前 20 行。</li>
<li>尝试一个新特征,并说明它为什么可能有用。</li>
<li>用 Git 做两次提交:一次提交项目骨架,一次提交 baseline 结果。</li>
</ol>
<h2>19. 验收检查</h2>
<p>在项目根目录执行:</p>
<div class="omp-code-frame" data-lang="fish"><div class="omp-code-bar"><span>omp</span><span>fish</span></div><pre><code class="language-fish">source .venv/bin/activate.fish
python src/train_baseline.py
test -f docs/data_card.md; and echo &quot;data card exists&quot;
test -f reports/baseline_results.md; and echo &quot;baseline report exists&quot;
test -f reports/error_analysis.md; and echo &quot;error analysis exists&quot;
</code></pre></div>
<p>人工确认:</p>
<ul>
<li>项目目录结构完整。</li>
<li>README 能说明问题、数据、运行方式。</li>
<li><code>docs/data_card.md</code> 写明数据来源、字段、目标、限制。</li>
<li>baseline 脚本能从头运行。</li>
<li>报告有模型、指标、验证方式、结果表。</li>
<li>错误分析不是空模板,至少有 5 条观察。</li>
<li>Git 提交不包含 <code>.venv/</code>。</li>
</ul>
<h2>20. 常见错误</h2>
<h3>错误 1:项目没有明确目标</h3>
<p>“分析 Titanic 数据”不是明确目标。“预测乘客是否生还,并分析哪些群体错误率高”才是明确目标。</p>
<h3>错误 2:README 最后才写</h3>
<p>README 是项目导航,不是交作业时补的封面。Week 07 就写初稿,Week 08 再打磨。</p>
<h3>错误 3:notebook 里能跑,但脚本不能跑</h3>
<p>Notebook 适合探索,最终训练入口应该是 <code>src/train_baseline.py</code>。否则别人无法稳定复现。</p>
<h3>错误 4:数据来源不清楚</h3>
<p>报告里必须能回答:数据从哪里来、下载日期、许可或引用方式、是否可以公开。</p>
<h3>错误 5:只写模型分数,不写错误分析</h3>
<p>模型项目的价值不只在分数,还在你能否解释错误、提出下一步改进。</p>
<h2>21. 下一步</h2>
<p>进入 Week 08:<a href="/post/ustc-stat-ai-quant-plan/">统计建模项目收尾</a>。你会把 Week 07 的项目整理成可以给老师、导师或实习面试官看的版本:README 打磨、报告成稿、复现命令、提交历史清理与成果展示。</p>


    </article>
  </div>
</section>

喜欢的话,留下你的评论吧~