加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 创业 > 正文

训练提速60%!只需5行代码,PyTorch 1.6即将原生支持自动混合精度训练

发布时间:2020-07-15 04:57:05 所属栏目:创业 来源:站长网
导读:副问题#e# PyTorch 1.6 nightly增进了一个子模块 amp,支持自动殽杂精度实习。值得等候。来看看机能怎样,对比Nvidia Apex 有哪些上风? 即将在 PyTorch 1.6上宣布的 torch.cuda.amp 殽杂精度实习模块实现了它的理睬,只需增进几行新代码就可以进步峻型模子

self.train() X = torch.tensor(X, dtype=torch.float32) y = torch.tensor(y, dtype=torch.float32)   optimizer = torch.optim.Adam(self.parameters(), lr=self.max_lr) scheduler = torch.optim.lr_scheduler.OneCycleLR(     optimizer, self.max_lr,     cycle_momentum=False,     epochs=self.n_epochs,     steps_per_epoch=int(np.ceil(len(X) / self.batch_size)), ) batches = torch.utils.data.DataLoader(     torch.utils.data.TensorDataset(X, y),     batch_size=self.batch_size, shuffle=True )   # NEW scaler = torch.cuda.amp.GradScaler()   for epoch in range(self.n_epochs):     for i, (X_batch, y_batch) in enumerate(batches):         X_batch = X_batch.cuda()         y_batch = y_batch.cuda()         optimizer.zero_grad()           # NEW         with torch.cuda.amp.autocast():             y_pred = model(X_batch).squeeze()             loss = self.loss_fn(y_pred, y_batch)           # NEW         scaler.scale(loss).backward()         lv = loss.detach().cpu().numpy()         if i % 100 == 0:             print(f"Epoch {epoch + 1}/{self.n_epochs}; Batch {i}; Loss {lv}")           # NEW         scaler.step(optimizer)         scaler.update()          scheduler.s 

新的 PyTorch GradScaler 工具是 PyTorch 实现的丧失缩放。追念一下在“殽杂精度怎样事变”一节中提到,在实习时代,为了防备梯度变小到0,某种情势的缩放是须要的。最佳的丧失乘数得足够高以保存很是小的梯度,同时不能太高以至于导致很是大的梯度四舍五入到 inf发生相反的题目。

PyTorch行使指数退避(exponential backoff)来办理这个题目。Gradscalar 以一个小的丧失乘数开始,这个乘数每次会翻倍。这种逐渐更加的举动一向一连到 GradScalar 碰着包括 inf 值的梯度更新。Gradscalar 扬弃这批数据(譬喻跳过梯度更新) ,将丧失乘数减半,并重置其倍增时刻。

通过这种方法逐级上下移动丧失乘数,PyTorch 可以跟着时刻的推移近似获得吻合的丧失乘数。认识 TCP 拥塞节制的读者应该会发明这里的焦点头脑很是认识!该算法行使的精确数字是可设置的,你可以直接从docstring中看到默认值:

torch.cuda.amp.GradScaler(     init_scale=65536.0, growth_factor=2.0, backoff_factor=0.5,     growth_interval=2000, enabled=True )  

Gradscalar 必要对梯度更新计较(搜查是否溢出)和优化器(将扬弃的batches转换为 no-op)举办节制,以实现其操纵。这就是为什么 loss.backwards()被 scaler.scale(loss).backwards()代替, 以及 optimizer.step()被 scaler.step(optimizer)替代的缘故起因。

值得留意的是,GradScalar 可以检测并遏制overflows(由于 inf 老是坏的) ,可是它无法检测和遏制underflows(由于0凡是是一个正当值)。假如你选择的初始值太低,增添隔断太长,你的收集也许会在 GradScalar 参与之前underflow并发散。因为这个缘故起因,选择一个很是大的初始值也许是一个好主意。

最后,留意 GradScalar 是一个有状态工具。行使此成果生涯模子checkpoint必要和模子权重一路写入和读取磁盘。用 state _ dict 和 load _ state _ dict 工具要领(在 PyTorch 文档中有先容)可以很轻易地做到这一点。

自动殽杂精度实习拼图的另一半是 torch.cuda.amp.autocast 上下文打点器。Autocast实现了 fp32-> fp16转换。追念一下“殽杂精度是怎样事变的“中的内容,因为差异的操纵以差异的速度累积偏差,并非全部的操纵都可以在 fp16中安详运行。下面的截图来自 amp 模块文档,先容了autocast如那里理赏罚 PyTorch 中可用的各类操纵:

这个列表首要由矩阵乘法和卷积两部门构成,尚有简朴的线性函数。

这些操纵在 fp16中是安详的,可是在输入有 fp16和 fp32殽杂的环境下,这些操纵具有向上适配(up-casting)法则,以确保它们不会出题目。留意,这个列表还包罗其它两个根基的线性代数运算: 矩阵/向量点积和向量叉积。

实习提速60%!只需5行代码,PyTorch 1.6即将原生支持自动殽杂精度实习

对数、指数、三角函数、正规函数、离散函数和(大)和在 fp16中是不安详的,必需在 fp32中执行。

通过赏识这个列表,在我看来,大大都层城市从autocasting中受益,这要归功于它们内部对根基线性代数操纵的依靠,但大大都激活函数却不是。卷积层是最大赢家。

启用sutocasting很是简朴。你只必要做的就是行使autocast上下文打点器包好模子的正向撒播:

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读