图解OneFlow中的学习率调整策略

背景 学习率调整策略(learning rate scheduler),其实单独拎出每一个来看都不难,但是由于方法较多,上来就看文档容易一头雾水, 以OneFlow v0.7.0为例,oneflow.optim.lr_scheduler模块中就包含了14种策略。 有没有一种更好的方法来学习呢?比如可视化出学习率的变化过程,此时,我脑海中突然浮现出Convolution arithmetic这个经典项目,作者将各种CNN卷积操作以gif形式展示,一目了然。 所以,就有了这篇文章,将学习率调整策略可视化出来,下面是两个例子(ConstantLR和LinearLR): 我将可视化代码分别托管在Hugging Face Spaces和Streamlit Cloud,建议大家访问第一个链接,然后自由调节参数,感受学习率的变化过程。 Hugging Face Space版本 Streamlit Cloud版本 学习率调整策略 学习率可以说是训练神经网络过程中最重要的参数(之一),目前大家都已接受用动态学习率调整策略来代替固定学习率,各种学习率调整策略层出不穷,下面我们就以OneFlow v0.7.0为例,学习下常用的几种策略。 基类LRScheduler LRScheduler(optimizer: Optimizer, last_step: int = -1, verbose: bool = False)是所有学习率调度器的基类,初始化参数中last_step和verbose一般不需要设置,前者主要和checkpoint相关,后者则是打印当前学习率。LRScheduler中最重要的方法是step(),这个方法的作用就是修改用户设置的初始学习率,然后应用到下一次的Optimizer.step()。 有些资料会讲LRScheduler根据epoch或iteration/step来调整学习率,两种说法都没问题,实际上,LRScheduler并不知道当前训练到第几个epoch或第几个iteration/step,只记录了调用step()的次数(last_step),如果每个epoch调用一次,那就是根据epoch来调整学习率,如果每个mini-batch 调用一次,那就是根据iteration来调整学习率,以Transformer为例,使用的是后者。 简单来说,LRScheduler根据调整策略本身、当前调用step()的次数(last_step)和用户设置的初始学习率来得到下一次梯度更新时的学习率。 ConstantLR oneflow.optim.lr_scheduler.ConstantLR( optimizer: Optimizer, factor: float = 1.0 / 3, total_iters: int = 5, last_step: int = -1, verbose: bool = False ) ConstantLR和固定学习率差不多,唯一的区别是在前total_iters,学习率为初始学习率 * factor。 注意:由于factor取值[0, 1],所以这是一个学习率递增的策略。...

June 5, 2022 · 2 min

DeepSpeed之ZeRO系列:将显存优化进行到底

前言 目前训练超大规模语言模型主要有两条技术路线:TPU + XLA + TensorFlow/JAX 和 GPU + PyTorch + Megatron-LM + DeepSpeed。前者由Google主导,由于TPU和自家云平台GCP深度绑定,对于非Googler来说, 只可远观而不可把玩,后者背后则有NVIDIA、Meta、MS大厂加持,社区氛围活跃,也更受到群众欢迎。 上面提到的DeepSpeed的核心是ZeRO(Zero Redundancy Optimizer),简单来说,它是一种显存优化的数据并行(data parallelism, DP)方案。而“优化“这个话题又永无止境,在过去两年DeepSpeed团队发表了三篇ZeRO相关的论文,提出了去除冗余参数、引入CPU和内存、引入NVMe等方法,从始至终都围绕着一个目标:将显存优化进行到底。 ZeRO: 一种去除冗余的数据并行方案 ZeRO: Memory Optimizations Toward Training Trillion Parameter Models 发表在SC 20,DeepSpeed项目最初就是论文中ZeRO方法的官方实现。 背景 如今训练大模型离不开各种分布式并行策略,常用的并行策略包括: 数据并行(data parallelism, DP):假设有 \(N\) 张卡,每张卡都保存一个模型,每一次迭代(iteration/step)都将batch数据分割成 \(N\) 个等大小的micro-batch,每张卡根据拿到的micro-batch数据独立计算梯度,然后调用AllReduce计算梯度均值,每张卡再独立进行参数更新。 # https://huggingface.co/docs/transformers/parallelism#model-parallelism # 假设模型有三层:L0, L1, L2 # 每层有两个神经元 # 两张卡 GPU0: L0 | L1 | L2 ---|----|--- a0 | b0 | c0 a1 | b1 | c1 GPU1: L0 | L1 | L2 ---|----|--- a0 | b0 | c0 a1 | b1 | c1 模型并行(model parallelism/tensor parallelism, MP/TP):有的tensor/layer很大,一张卡放不下,将tensor分割成多块,一张卡存一块。 # https://huggingface....

May 14, 2022 · 3 min

Hugging Face🤗 : NLP明星创业公司是如何炼成的

2016年,两位法国人怀揣着对聊天机器人(chatbot)行业未来的美好向往,创立了Hugging Face 🤗,次年推出了一款和公司同名的机器人聊天App。最初,他们只是想为无聊的年轻人提供一个打发时间的地方,"Its entire purpose is to be fun" 可是不论是从技术难度还是商业模式上看,在2016年的时间点选择做开放领域的闲聊机器人,都不是一个明智选择。 时间来到了2018年10月29号,这一天公司首席科学家Thomas Wolf在GitHub上创建了一个名为pytorch-pretrained-BERT的项目,提交了第一个commit,这个项目最初的目的是如此简单,将Google基于tensorflow实现的BERT模型用pytorch进行了重写,并且可以加载Google公开的模型参数。但是,项目的火热程度超出了所有人的预期,Hugging Face也在开源模式中一路高歌猛进,顺利完成了公司转型,成为了当下NLP领域最火的创业公司(之一)。 入局聊天机器人 现在当你打开Hugging Face的官网,映入眼帘的都是"AI community"、“SOTA models”、“Open Source"等词汇,或许很多人都不知道,这曾经是一家做聊天机器人(chatbot)的公司,而且做的还是开放领域(open domain)的闲聊机器人,对,就是类似微软小冰,让我们把时间线拨回2016年。 Clem Delangue1和Julien Chaumond2一起参加了风投机构Betaworks举办的Botcamp加速器项目,专门为聊天机器人创业公司提供指导,在此期间(或者更早?)他们俩创立了Hugging Face3,研发一款为青少年打发时间找点乐子的陪聊型机器人,不论是公司名字(来自于emoji表情)还是产品,画风都既不商业(Enterprise)也不严肃,从这段时间的PR来看,他们坚信AI friend是大有未来的,We really have this vision where we think everyone will have an AI friend and everyone will discuss things every day with Hugging Face, so that’s really what we’re focused on right now and for the next few years4 左边 是CTO Julien Chaumond,右边 是CEO Clem Delangue 在2017年3月9号,他们在iOS App Store正式推出了Hugging Face App,产品的界面是这样的:...

April 21, 2022 · 2 min

K-Means从入门到调包

在做数据挖掘项目时,拿到数据,首先要分析问题和观察数据,我在“观察数据”这一阶段主要是看看有没有直观的数据规律以及异常点,对于那些特征维度较低的数据,比如仅仅2维,我选择画散点图观察,高纬度数据可以用t-SNE降维后再画图。除了可视化,聚类算法也是找到异常点的常用手段之一。 这篇博客介绍一种最基本的聚类算法:K-Means。 算法描述与EM 聚类算法的作用是将数据集自动划分为多个不同的集合。 K-Means算法是典型的无监督算法,对于数据集\(D\), 我们设定参数k(k个集合),她就能自动地学习出k个类别,简单又神奇。那么K-Means是如何学习到这k个集合呢?专业一点说就是,K-Means的目标函数是啥?如何优化她的目标函数?先回答第一个问题,下面就是K-Means的目标函数: 物理意义:我们希望找到的k个集合,每个集合内的点都距离此集合内平均值点最近(每个集合中的点都紧密团结在一起)。 知道了目标函数,下一步就要考虑如何求解,最常见的求解方法是Lloyd算法,也就是使用EM算法,注意,Lloyd算法得到的结果是局部极小值而不是全局最小值哦。 EM算法求解步骤很简单,总共分三步: 将所有数据点都分配到某个集合 -> 计算每个点到集合平均值点的欧氏距离 计算每个集合内点的平均值 -> 计算每个特征的平均值 重复上面两步直到局部收敛 -> 前后两次迭代的集合结果相同 上面的三步概括起来就是 E->M->E->M->……….. import numpy as np from collections import defaultdict from random import uniform class KMeans(object): """ kmeans 聚类算算 """ def __init__(self): pass def cluster(self, X, k, initializer="random"): self.X = X self.k = k self.centers = defaultdict(list) self.assignment = np.zeros(self.X.shape[0]) #记录每个样本属于哪个中心点 if initializer == "random": self._initialize() #初始化得到k个点 elif initializer == "kmeans++": self....

July 19, 2016 · 2 min

Gradient Boosting 从入门到调包 (调包篇)

Gradient Boosting的开源实现很多,当然首选还是XGBoost。调包,就是学习API的过程,最好的学习资料就是官方文档以及demo。我这里把基本的调用罗列出来: xgboost调包之 基础篇.ipynb xgboost调包之 模型篇.ipynb xgboost调包之 sklearn接口.ipynb xgboost调包之 特征重要性可视化.ipynb xgboost调包之 early stopping.ipynb xgboost调包之 结合pandas.ipynb

July 9, 2016 · 1 min