Files
flykhan 2536c937e3 feat: 完整中文翻译 maths-cs-ai-compendium(数学·计算机科学·AI 知识大全)
翻译自英文原版 maths-cs-ai-compendium,共 20 章全部完成。

第01章 向量 | 第02章 矩阵 | 第03章 微积分
第04章 统计学 | 第05章 概率论 | 第06章 机器学习
第07章 计算语言学 | 第08章 计算机视觉 | 第09章 音频与语音
第10章 多模态学习 | 第11章 自主系统 | 第12章 图神经网络
第13章 计算与操作系统 | 第14章 数据结构与算法
第15章 生产级软件工程 | 第16章 SIMD与GPU编程
第17章 AI推理 | 第18章 ML系统设计
第19章 应用人工智能 | 第20章 前沿人工智能

翻译说明:
- 所有数学公式 $...$ / $$...$$、代码块、图片引用完整保留
- mkdocs.yml 配置中文导航 + language: zh
- README.md 已翻译为中文(兼 docs/index.md)
- docs/ 目录包含指向各章文件的 symlink
- 约 29,000 行中文内容,排除 .cache/ 构建缓存
2026-05-03 10:23:20 +08:00

219 lines
9.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Git 与版本控制
*Git 是软件团队在不相互覆盖工作的情况下进行协作的方式。本文涵盖 Git 的心智模型、分支策略、合并与变基、冲突解决、拉取请求,以及管理机器学习特定挑战(如大文件和实验追踪)的方法。*
- 每个严肃的软件项目都使用版本控制。**Git** 是主导系统,几乎所有开源项目和公司都在使用。没有 Git,协作就是通过电子邮件发送 zip 文件并祈祷没人覆盖你的更改。有了 Git,每次更改都可追踪、可撤销、可追溯。
- 对于机器学习工程师:Git 追踪你的代码、配置和实验脚本。结合实验追踪工具,它能提供可重现性:"是哪个确切的代码和配置产生了这个模型?"
## 心智模型
- Git 追踪项目的**快照**。每次提交都是那一刻所有追踪文件的完整快照,而不是差异(在内部,Git 为效率存储差异,但从概念上讲,每次提交都是一个完整状态)。
- 文件的四个"位置"
1. **工作目录**:磁盘上的实际文件。你在这里编辑。
2. **暂存区**(索引):你标记为下一次提交的文件。`git add` 将更改移到这里。
3. **本地仓库**:你的提交历史,存储在 `.git/` 中。`git commit` 将暂存区保存为新的快照。
4. **远程仓库**(例如 GitHub):一个共享副本。`git push` 上传你的提交,`git pull` 下载他人的提交。
```
Working Dir → git add → Staging → git commit → Local Repo → git push → Remote
← git pull ←
```
- 暂存区正是 Git 强大之处。你可以编辑 10 个文件,但只提交其中的 3 个,将其他更改保留给另一次提交。这使得清晰的、有重点的提交成为可能。
### 基本命令
```bash
git init # 创建新仓库
git clone url # 下载远程仓库
git status # 有什么变化?(最常用的命令)
git add file.py # 暂存特定文件
git add . # 暂存所有更改(谨慎使用)
git commit -m "descriptive msg" # 提交暂存的更改
git push # 将提交上传到远程
git pull # 下载并合并远程更改
git log --oneline # 紧凑的提交历史
git diff # 显示未暂存的更改
git diff --staged # 显示已暂存的更改
```
## 分支
- **分支**是指向一次提交的指针。默认分支是 `main`(或 `master`)。创建分支让你拥有独立的开发线:你可以在不影响 `main` 的情况下进行更改。
```bash
git branch feature-x # 创建分支
git checkout feature-x # 切换到此分支
git checkout -b feature-x # 创建并切换(一步完成)
git branch -d feature-x # 删除分支(合并后)
git branch -a # 列出所有分支(本地 + 远程)
```
- **何时分支**:始终需要。永远不要直接提交到 `main`。每个功能、错误修复或实验都有其自己的分支。这保持了 `main` 的稳定性和可部署性。
### 分支策略
- **功能分支**(最常见):每个功能/修复从 `main` 创建一个分支。完成后,打开拉取请求(PR)以合并回去。简单,适用于大多数团队。
- **主干开发**:开发人员频繁(每天多次)提交到 `main`,使用特性标记隐藏未完成的工作。持续部署的团队(Google、Facebook)更偏好这种方式。需要优秀的 CI/CD。
- **Gitflow**:为功能、发布和热修复设置单独的分支。更复杂,适用于有版本化发布的软件(移动应用、打包软件)。对大多数机器学习项目来说过于复杂。
- 对于机器学习团队:**功能分支**配合短生命周期的分支(1-3 天内合并)是最佳选择。生命周期长的分支会与 `main` 产生分歧,导致痛苦的合并冲突。
## 合并与变基
- **合并**创建一个新的"合并提交",将两个分支合并:
```bash
git checkout main
git merge feature-x
```
- 这保留了完整的历史记录:你可以看到工作是在分支上完成的,以及何时合并的。合并提交有两个父节点。
- **变基**在你的分支上重放提交到目标分支之上:
```bash
git checkout feature-x
git rebase main
```
- 这会重写历史:你的分支上的提交会获得新的哈希值,就好像你是从 `main` 的当前顶端开始工作一样。结果是线性的历史记录(没有合并提交),阅读起来更清晰。
- **何时使用哪种**
- **变基**用于使用最新的 `main` 更改更新你的功能分支(保持分支整洁和最新)。
- **合并**用于将你的功能分支集成到 `main`(保留分支历史)。
- **永远不要变基已经推送并与他人共享**的提交。变基会重写历史;如果其他人已经基于原始提交开展工作,变基会导致混乱。
## 解决冲突
- **冲突**发生在两个分支修改同一文件的同一行时。Git 无法自动决定保留哪个更改,需要你手动解决。
```
<<<<<<< HEAD
learning_rate = 0.001
=======
learning_rate = 0.0005
>>>>>>> feature-x
```
- `<<<<<<< HEAD``=======` 之间是当前分支的版本。`=======``>>>>>>> feature-x` 之间是传入分支的版本。你决定保留哪个(或组合它们),删除标记,保存,然后运行 `git add` 添加已解决的文件。
- **陷阱**:不要在已提交的文件中留下冲突标记。它们是会破坏你代码的字面文本。解决后始终搜索 `<<<<<<<`
- **减少冲突**:保持分支短生命周期,频繁将 `main` 合并到你的分支中,避免多人同时编辑同一个文件。
## 编写良好的提交信息
- 提交信息是为了未来的你和你的队友。"修复错误"告诉不了你什么。"修复批次大小计算中的差一错误,该错误导致 8-GPU 训练时 OOM"告诉你一切。
- **格式**
```
简短摘要(50 字以内,祈使语气)
如果需要,可附带更长的描述。解释 WHY,而不是 WHAT
(差异显示了什么改变了)。每行不超过 72 个字符。
Fixes #123
```
- **祈使语气**"添加功能"而不是"已添加功能"或"添加了功能"。将其视为完成句子:"如果应用此提交,它将**添加功能**。"
- **原子提交**:每个提交应做一件事。"添加数据加载器"是一个提交。"添加数据加载器并修复无关的错误并更新 README"应该是三个提交。这使得 `git bisect`(找到哪个提交引入了错误)成为可能。
## 拉取请求与代码审查
- **拉取请求(PR)**提议将一个分支合并到 `main`。它是代码审查的门户:队友阅读你的更改,提出改进建议,并在合并前批准。
- **良好的 PR 实践**
- 保持 PR 小(少于 400 行更改)。大的 PR 会被敷衍批准,因为没人想审查 2000 行。
- 编写清晰的描述:更改了什么、为什么以及如何测试。
- 链接到促使更改的问题或工单。
- 及时回复审查评论。
- 在合并前压缩琐碎的提交(这样 `main` 就有干净的历史记录)。
- **代码审查不是为了找错误**(测试来做这个)。它的目的是:知识分享(审查者学习代码库)、设计反馈(这是正确的方法吗?)和维护标准(命名、风格、架构)。
## .gitignore
- `.gitignore` 文件告诉 Git 排除哪些文件不被追踪。对于机器学习项目:
```gitignore
# Python
__pycache__/
*.pyc
*.egg-info/
.venv/
env/
# 数据和模型(对 git 来说太大)
data/
*.csv
*.parquet
models/
*.pt
*.onnx
*.bin
checkpoints/
# 密钥
.env
*.pem
credentials.json
# IDE
.vscode/
.idea/
*.swp
# 操作系统
.DS_Store
Thumbs.db
# Jupyter
.ipynb_checkpoints/
# 实验输出
wandb/
mlruns/
outputs/
logs/
```
- **陷阱**:在文件已被提交后将文件添加到 `.gitignore` 不会将其从仓库中移除。你还必须使用 `git rm --cached file` 来取消追踪。该文件会永远留在历史中,除非你重写历史(这很麻烦)。
## Git 在机器学习中的应用
- 机器学习引入了传统软件不面临的挑战:
- **大文件**:数据集和模型权重可能有数 GB 或更大。Git 是为文本文件(源代码)设计的,而不是二进制 blob。解决方案:
- **Git LFS**(大文件存储):在 Git 中追踪指针,将实际文件存储在单独的服务器上。简单,但在 GitHub 上有限制存储/带宽。
- **DVC**(数据版本控制):将数据和模型文件与 Git 分开管理,使用远程存储(S3、GCS)。像 Git 一样用于数据:`dvc add data.csv``dvc push``dvc pull`
- **实验追踪**:哪个提交 + 哪些超参数 + 哪个数据产生了哪些指标?Git 追踪代码,但不追踪完整的实验上下文。
- **Weights & BiasesW&B**:记录指标、超参数、系统信息,并链接到 Git 提交。提供用于比较运行结果的仪表板。
- **MLflow**:开源的实验追踪,带有模型注册表。记录参数、指标和产物。
- **简单方法**:在你的训练脚本中记录 Git 哈希值:`git_hash = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip()`。将其与你的结果一起存储。
- **可重现性检查清单**(每个实验需要追踪的内容):
- Git 提交哈希值(确切的代码版本)
- 配置文件 / 超参数
- 随机种子
- Python 和库版本(`pip freeze`
- 数据版本(DVC 哈希值或数据集版本标签)
- 硬件(GPU 类型、GPU 数量)
```bash
# 快速可重现性快照
echo "Commit: $(git rev-parse HEAD)" > experiment_info.txt
echo "Branch: $(git branch --show-current)" >> experiment_info.txt
echo "Dirty: $(git status --porcelain | wc -l) files" >> experiment_info.txt
pip freeze >> experiment_info.txt
nvidia-smi >> experiment_info.txt
```