使用 pytorch-lightning
在用 PyTorch 训练不同模型时,需要编写很多重复的逻辑。一个工程的代码无可避免地变得越来越长,难以管理。PyTorch Lightning 作为一个对 PyTorch 二次封装的框架,能让训练逻辑的编写像堆积木一样秩序井然。
虽然叫做 lightning,这个库的学习成本并低。好在一但熟悉,就能享受到很多便利。
安装
使用类似下面的指令安装 PyTorch Lightning。
python -m pip install lightning
完成后就可以在 Python 脚本里 import pytorch_lightning 了。
快速开始
PyTorch Lightning 的宗旨是:all in one。
不使用任何框架,写出来的训练代码会像是这样:
writer = SummaryWriter()
model = ResNet18().to(device)
optimizer = torch.optim.Adam(model.params, lr=1e-3)
for epoch in range(num_epochs):
for i, batch in enumerate(train_data):
x, y = batch
x = x.to(device)
output = model(x)
loss = criterion(output, y)
writer.add_scalar("train_loss", loss, num_epochs * len(train_data) + i)
loss.backward()
optimizer.step()
optimizer.zero_grad()
with torch.no_grad():
for batch in val_data:
x, y = batch
···
若使用 PyTorch Lightning,可以把这一切封装到一个 class 内:
import pytorch_lightning as L
class LightningModel(L.LightningModule):
def __init__(self):
super().__init__()
self.model = ResNet18()
def forward(self, x):
return model(x)
def configure_optimizers(self):
optimizer = torch.optim.Adam(self.model.parameters, lr=1e-3)
return optimizer
def training_step(self, train_batch, batch_idx):
x, y = train_batch
output = self.model(x)
loss = criterion(output, y)
self.log('train_loss', loss, on_step=True, on_epoch=False)
return loss
def validation_step(self, val_batch, batch_idx):
x, y = val_batch
output = criterion(output, y)
loss = criterion(output, y)
self.log('val_loss', loss)
可见 lightning 的特点以及省下的工作:
- 将训练各步骤的代码分配到不同的函数,层次分明
- 不需要
.to(device)。lightning 会自动转换 - 不需要手动
loss.backward()optimizer.step()optimizer.zero_grad() - validation 阶段不需要手动
torch.no_grad() - 记录 log 时 lightning 会帮助填写当前 step 和 epoch
- ……
接下来训练的代码就可以非常简明:
model = LightningModel()
trainer = L.Trainer(accelerator='gpu', max_epochs=15)
trainer.fit(model, train_data, val_data) # 正式开始训练
使用混合精度
若要在 lightning 的训练启用混合精度加速,需要先执行:
torch.set_float32_matmul_precision('high')
然后在实例化 trainer 时,传入参数 precision='bf16-mixed' 即可。参数可选的值随硬件条件改变而变化,请查阅文档。
学习率调度器(scheduler)
在自定义 configure_optimizers() 时,除了需要指定 optimizer,还可以设定一个学习率调度器 scheduler。
class LightningModel(L.LightningModule):
···
def configure_optimizers(self):
optimizer = torch.optim.Adam(self.model.parameters(), lr=0.001)
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=10)
return [optimizer], [scheduler]
lightning 会自动执行 scheduler.step()。