控制流:条件判断与循环
让程序根据情况做不同的事,或重复执行某些操作。AI 训练循环的本质就是 for 循环加上条件判断。
if / elif / else —— 条件判断
if 让程序做决策:"如果...就做...,否则做..."。Python 用缩进表示代码块,冒号 : 后面的缩进内容属于这个 if 块。
if / elif / else 结构
if 是"如果",elif 是"否则如果"(else if 的缩写),else 是"以上都不是时"。elif 和 else 都是可选的,可以有多个 elif。
accuracy = 0.85
# 基本 if-elif-else
if accuracy >= 0.95:
print("优秀!可以部署")
elif accuracy >= 0.85:
print("良好,继续调优") # ← 这行会执行
elif accuracy >= 0.70:
print("一般,需要改进")
else:
print("较差,重新设计模型")
# 组合条件(and、or、not)
loss = 0.3
epoch = 50
if accuracy >= 0.9 and loss < 0.2:
print("模型达标")
if epoch > 100 or loss < 0.01:
print("停止训练")
# 三元表达式(简洁写法)
status = "通过" if accuracy > 0.8 else "不通过"
print(status) # 通过
# Early Stopping(早停):常见的 AI 训练策略
best_val_loss = float('inf') # 初始设为无穷大
patience = 5 # 允许连续 5 轮没提升
wait = 0
current_val_loss = 0.35
if current_val_loss < best_val_loss:
best_val_loss = current_val_loss
wait = 0
print("验证损失改善,保存模型")
else:
wait += 1
if wait >= patience:
print("早停触发,停止训练!")
# 选择设备(GPU 还是 CPU)
import torch
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"使用设备: {device}")
for 循环 —— 遍历迭代
for 循环用于遍历一个序列(列表、字典、范围等),对每个元素执行相同的操作。AI 训练的核心就是 for 循环:每轮(epoch)遍历一次训练集。
可迭代对象(Iterable)
凡是可以用 for 循环遍历的对象都是"可迭代对象":列表、字典、字符串、range()、文件对象等都是可迭代的。理解这个概念后,你就明白为什么 for 循环可以用在这么多地方了。
# 遍历列表
models = ["GPT-4o", "Claude", "Gemini"]
for model in models:
print(f"评估模型: {model}")
# range() 生成数字范围
# range(start, stop, step) - stop 不包含在内
for epoch in range(1, 6): # 1, 2, 3, 4, 5
print(f"Epoch {epoch}/5")
# enumerate() - 同时获得索引和值
losses = [2.5, 1.8, 1.2, 0.9]
for i, loss in enumerate(losses):
print(f"Epoch {i+1}: loss = {loss}")
# zip() - 同时遍历两个列表
train_losses = [2.5, 1.8, 1.2]
val_losses = [2.8, 2.0, 1.4]
for t_loss, v_loss in zip(train_losses, val_losses):
print(f"训练: {t_loss:.2f}, 验证: {v_loss:.2f}")
# 遍历字典
config = {"lr": 0.001, "batch": 32, "epochs": 100}
for key, value in config.items():
print(f"{key} = {value}")
break 和 continue
# break:立即退出循环
losses = [2.5, 1.8, 1.2, 0.05, 0.8] # 第4个达标
for i, loss in enumerate(losses):
print(f"Epoch {i}: {loss}")
if loss < 0.1:
print("达到目标!停止训练")
break # 退出循环,不再继续
# continue:跳过当前这一次,继续下一次
data = [1.0, None, 3.0, None, 5.0] # 含有空值的数据
for x in data:
if x is None:
continue # 跳过 None,继续下一个
print(x ** 2) # 1.0, 9.0, 25.0
控制流核心概念
- 控制流(Control Flow) 程序执行的顺序。默认是从上到下逐行执行,控制流语句(if/for/while)可以改变这个顺序——跳过某些代码、重复执行某些代码,或在满足条件时提前退出。
-
条件表达式(Conditional Expression)
产生 True 或 False 结果的表达式,用于 if 和 while 的判断。在 Python 中,所有对象都可以作为条件:空列表
[]、数字0、None、空字符串""都被视为 False,其余为 True。 -
迭代(Iteration)
对一个序列中的每个元素逐一处理的过程。
for循环就是迭代的语法糖。Python 中任何实现了__iter__方法的对象都可以被迭代,称为"可迭代对象"。 -
短路求值(Short-Circuit Evaluation)
and和or运算符的优化特性。A and B中如果 A 为 False,B 不会被求值;A or B中如果 A 为 True,B 不会被求值。可以利用这个特性写出更简洁的代码:data and data.process()。
while 循环 —— 条件循环
while 循环在条件为 True 时一直重复,直到条件变 False。与 for 循环的区别:for 循环知道要循环多少次,while 循环不知道,只要条件满足就继续。
# 训练直到 loss 足够小
loss = 10.0
epoch = 0
target_loss = 0.5
while loss > target_loss:
# 模拟损失下降(实际是模型训练)
loss = loss * 0.7
epoch += 1
print(f"Epoch {epoch}: loss = {loss:.4f}")
print(f"训练完成,共 {epoch} 轮")
# 输出:
# Epoch 1: loss = 7.0000
# Epoch 2: loss = 4.9000
# ...最终达到目标
# 防死循环:加一个最大迭代次数限制
max_epochs = 1000
epoch = 0
while loss > 0.01 and epoch < max_epochs:
epoch += 1
# ... 训练逻辑
小心无限循环
while 循环如果条件永远为 True,程序就会卡死(无限循环)。一定要确保循环内部有能使条件变 False 的逻辑,或者设置最大迭代次数。
综合示例:AI 训练循环
把本章学的所有控制流组合起来,看一个模拟的完整 AI 训练循环:
import random
# 训练配置
config = {
"epochs": 20,
"target_loss": 0.3,
"patience": 3 # 早停等待轮数
}
best_loss = float('inf')
wait = 0
loss_history = []
# 训练循环(核心是 for + if)
for epoch in range(1, config["epochs"] + 1):
# 模拟损失(真实代码是跑一遍训练集)
loss = 2.0 / epoch + random.uniform(-0.05, 0.05)
loss_history.append(loss)
# 每5轮打印一次
if epoch % 5 == 0:
print(f"[Epoch {epoch:02d}] loss: {loss:.4f}")
# 检查是否改善(早停逻辑)
if loss < best_loss:
best_loss = loss
wait = 0
else:
wait += 1
# 早停:连续 patience 轮没改善就停止
if wait >= config["patience"]:
print(f"早停触发(Epoch {epoch})")
break
# 目标达成
if loss < config["target_loss"]:
print(f"✅ 目标达成!Epoch {epoch}, loss = {loss:.4f}")
break
print(f"最低损失: {best_loss:.4f}")
print(f"损失曲线: {[round(l,2) for l in loss_history[:5]]}...")
这就是 AI 训练的骨架
真实的 PyTorch 训练循环和上面这段代码结构几乎完全一样,只是把"模拟损失"替换成了真正的前向传播、反向传播和参数更新。掌握这个结构,你就理解了 AI 训练的核心逻辑。
边界情况与常见误区
Python 的真假值规则
Python 中"假值(Falsy)"包含的范围比很多人预想的更广,这在 AI 数据处理中会造成意外 bug:
# 所有这些都被视为 False(Falsy)
if 0: print("不会执行") # 0 是 Falsy
if 0.0: print("不会执行") # 0.0 是 Falsy
if "": print("不会执行") # 空字符串是 Falsy
if []: print("不会执行") # 空列表是 Falsy
if {}: print("不会执行") # 空字典是 Falsy
if None: print("不会执行") # None 是 Falsy
# AI 中的陷阱:损失值为 0 时的误判
loss = 0.0
if loss: # ← 这会被视为 False!
print("有损失") # 即使 loss=0 也不会打印
# 正确做法:明确比较
if loss is not None: # 检查是否存在
print(f"损失为: {loss}")
# 检查模型权重列表是否为空
weights = []
if not weights: # 推荐写法
print("权重未初始化")
if len(weights) == 0: # 等价写法,更明确
print("权重未初始化")
for 循环中修改列表
在 for 循环中修改正在遍历的列表,会导致意外的跳过行为!如 for x in my_list: if condition: my_list.remove(x)。正确做法是创建新列表:new_list = [x for x in my_list if not condition],或遍历列表的副本:for x in my_list[:]。
range 不包含终止值
range(1, 10) 生成 1 到 9,不包含 10。range(n) 生成 0 到 n-1。在 AI 训练循环中,for epoch in range(1, epochs+1) 是常见写法,否则 epoch 从 0 开始,日志打印不直观。
match-case 语句(Python 3.10+)
Python 3.10 引入了结构模式匹配,类似其他语言的 switch,但功能更强大。在处理 AI API 的不同响应类型时特别有用:
# match-case:结构模式匹配
def handle_response(response):
"""处理 AI API 的不同响应类型"""
match response["type"]:
case "text":
print(f"文本回复: {response['content']}")
case "error":
print(f"错误: {response['message']}")
case "tool_call":
print(f"工具调用: {response['tool_name']}")
case _: # 默认分支,匹配所有其他情况
print("未知响应类型")
# 也可以匹配数据结构(更强大的用法)
def process_batch(batch):
match batch:
case []: # 空列表
print("空批次")
case [single]: # 只有一个元素
print(f"单样本: {single}")
case [first, *rest]: # 一个或多个元素
print(f"批次大小: {1 + len(rest)}")
本章小结
控制流是程序逻辑的骨架。if/elif/else 实现条件分支;for 遍历可迭代对象;while 在条件满足时持续循环;break 提前退出,continue 跳过当次迭代。AI 训练循环本质上是 for + if 的组合:外层 for 遍历 epoch,内层 for 遍历 batch,if 判断是否触发早停。Python 3.10+ 的 match-case 为处理不同类型响应提供了更清晰的语法。注意 Python 的"真假值"规则——0 和空容器都是 Falsy。