面向PyTorch用户的JAX简易教程[2]: 如何训练一个神经网络

背景 上一篇文章我们学习了JAX的基本知识,主要是几个关键词: NumPy API、transformations、XLA。这一篇来点实际的,看下如何训练一个神经网络,我们先回忆下用PyTorch训练神经网络,都需要哪几步: 实现网络模型 实现数据读取流程 使用优化器/调度器更新模型参数/学习率 实现模型训练和验证流程 下面我们就以在MNIST数据集上训练一个MLP为例,看下在JAX中如何实现上面的流程。 NumPy API实现网络模型 MNIST是一个10分类问题,每张图片大小是 28 * 28=784 ,我们设计一个简单的MLP网络, 一个四层MLP (包含输入层) import jax from jax import numpy as jnp from jax import grad, jit, vmap # 创建 PRNGKey (PRNG State) key = jax.random.PRNGKey(0) ## 创建模型参数, 去除输入层,实际上三层Linear,每层都包含一组(w, b),共三组参数 def random_layer_params(m, n, key, scale=1e-2): """ A helper function to randomly initialize weights and biases for a dense neural network layer """ w_key, b_key = jax....

July 23, 2022 · 9 min

面向PyTorch用户的JAX简易教程[1]: JAX介绍

背景 前几天申请参加了Google TRC项目,TPU VM的配置相当可以,但是PyTorch/XLA做数据并行时的体验却并不那么丝滑,考虑到Google一直力推TPU+JAX的组合,所以决定学习下JAX。 JAX简介 什么是JAX? 官方在GitHub README中是这么介绍的: JAX is Autograd and XLA, brought together for high-performance machine learning research. 在Description中写的是: Composable transformations of Python+NumPy programs: differentiate, vectorize, JIT to GPU/TPU, and more. 在JAX官方文档又是这么介绍的: JAX is NumPy on the CPU, GPU, and TPU, with great automatic differentiation for high-performance machine learning research. 总结一下,有几个关键词:Autograd、XLA、NumPy和composable transformations。 XLA 先来说XLA,这个我了解的最少,所以介绍起来最简单,XLA (Accelerated Linear Algebra)是Google为TensorFlow设计的一款编译器,主打JIT (Just-in-Time)编译和跨设备(CPU/GPU/TPU)执行,所以JAX介绍中凡是涉及到JIT、high-performance、CPU/GPU/TPU,都指的是XLA。 NumPy NumPy就不用提了,Python生态下只要涉及到数据分析/机器学习/数值计算中对数组/tensor进行操作,都离不开它,不夸张的说,NumPy API已经成为了数组/tensor操作的半个工业标准,包括各家深度学习框架中对tensor操作的函数接口也都是尽量靠近NumPy,JAX则更夸张,jax.numpy重新实现一套了NumPy API ,让用户从NumPy无缝切入JAX: from jax import numpy as jnp Autograd 这里的Autograd是哈佛大学HIPS实验室在14年开始开发的一款自动微分框架,特点是可以对Python/NumPy函数进行高阶求导,直接看个例子,一个简单的函数 f(x) ,顺便求一下一阶、二阶、三阶导函数:...

July 21, 2022 · 4 min

图解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

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