当前位置: 首页 > news >正文

深度解析 Google JAX 全栈:带你上手开发,从零构建神经网络

目前来看Google 是唯一一家在 AI 价值链上实现端到端垂直整合的公司。从基础模型 (Gemini)、应用层 (ImageFX, Search with Gemini, NotebookLM),到云架构 (Google Cloud, Vertex AI) 以及硬件 (TPUs),几乎全都有所布局。

长期以来Google 一直在通过提升自身能力来减少对 NVIDIA GPU 的依赖。这种技术积累逐渐演变成了现在的 JAX AI 栈。

更有意思的是这套技术栈现在不仅 Google 自己用,Anthropic、xAI 甚至 Apple 这些头部 LLM 提供商也都在用

所以我们就很有必要这就很有必要深入聊聊这套技术栈了。

什么是 JAX AI 栈?

简单来说,JAX AI 栈是一套面向超大规模机器学习的端到端开源平台。

核心组件主要由以下四个部分构成:

1、JAX

Google 和 NVIDIA 联合开发的 Python 高性能数值计算库。

接口设计极其类似 NumPy,但区别在于它能自动、高效地在 CPU、GPU 或 TPU 上运行,无论是本地还是分布式环境。

底层的技术在于XLA (Accelerated Linear Algebra)编译器,它能把 JAX 代码转译成针对不同硬件深度优化的机器码。对比之下NumPy 的操作默认只能在 CPU 上跑,效率天差地别。

2、Flax

基于 JAX 的神经网络训练库。Flax 的核心现在是 NNX (NeuralNetworks for JAX)。这是一个简化版的 API,让创建、调试和分析 JAX 神经网络变得更直观。

之前有个 Flax Linen,是那种无状态、函数式风格的 API。而 NNX 作为继任者,引入了面向对象和有状态的特性,对于习惯了 PyTorch 的开发者来说,构建和调试 JAX 模型会顺手很多。

3、Optax

JAX 生态里的梯度处理和优化库。

它的优势在于灵活性,几行代码就能把标准优化器和复杂的技巧(比如梯度裁剪、梯度累积)链式组合起来。

4. Orbax

专门处理 Checkpoint 的库,用于保存和恢复大规模训练任务。

支持异步分布式检查点,这在大模型训练里至关重要——万一硬件挂了,能从断点恢复,不至于让昂贵的算力打了水漂。

下面这张图展示了完整栈的架构,除了上面这四个核心,还有很多其他组件,建议细看。

实战:用 JAX 训练神经网络

JAX 之所以在 GPU 和 TPU 上能跑赢 PyTorch,主要归功于即时 (JIT) 优化和 XLA 的后端编译效率。

我们直接上手用 JAX 撸一个简单的神经网络,搞个手写数字识别,看看这套栈在实际工作流里到底怎么用。

1、环境配置

JAX AI 栈现在整合成了一个 metapackage,安装很简单。然后我们还需要

sklearn

(加载数据)和

matplotlib

(画图)。

!uv pip install jax-ai-stack sklearn matplotlib

2、加载数据

直接用 sklearn 加载 UCI ML 手写数字数据集。

fromsklearn.datasetsimportload_digits # Load dataset digits=load_digits()

数据是

8 x 8

的像素化手写数字图像(0 到 9)及其对应的标签。

print(f"Number of samples × features: {digits.data.shape}") print(f"Number of labels: {digits.target.shape}") """ Number of samples × features: (1797, 64) Number of labels: (1797,) """

3、 数据可视化

先看看数据长什么样,挑 100 张图画出来。

import matplotlib.pyplot as plt fig, axes = plt.subplots(10, 10, figsize=(6, 6), subplot_kw={'xticks':[], 'yticks':[]}, gridspec_kw=dict(hspace=0.1, wspace=0.1)) for i, ax in enumerate(axes.flat): ax.imshow(digits.images[i], cmap='binary', interpolation='gaussian') ax.text(0.05, 0.05, str(digits.target[i]), transform=ax.transAxes, color='green')

4、 数据集切分

常规操作,把数据切成训练集和测试集。

from sklearn.model_selection import train_test_split # Create dataset splits splits = train_test_split(digits.images, digits.target, random_state=0)

5、转为 JAX 数组

这一步很关键,输入到模型之前,需要用 JAX Numpy 把数据转成 JAX 数组格式。

import jax.numpy as jnp # Convert splits to JAX arrays images_train, images_test, label_train, label_test = map(jnp.asarray, splits)

看一眼数据维度:

print(f"Training images shape: {images_train.shape}") print(f"Training labels shape: {label_train.shape}") print(f"Test images shape: {images_test.shape}") print(f"Test labels shape: {label_test.shape}") """ Training images shape: (1347, 8, 8) Training labels shape: (1347,) Test images shape: (450, 8, 8) Test labels shape: (450,) """

6、用 Flax 构建网络

用 Flax NNX 搭建一个带 SELU 激活函数的简单前馈网络。习惯写 PyTorch 的朋友会发现,这语法看着非常眼熟。

from flax import nnx class DigitClassifier(nnx.Module): def __init__(self, n_features, n_hidden, n_targets, rngs): self.n_features = n_features self.layer_1 = nnx.Linear(n_features, n_hidden, rngs = rngs) self.layer_2 = nnx.Linear(n_hidden, n_hidden, rngs = rngs) self.layer_3 = nnx.Linear(n_hidden, n_targets, rngs = rngs) def __call__(self, x): x = x.reshape(x.shape[0], self.n_features) [#Flatten](#Flatten) images x = nnx.selu(self.layer_1(x)) x = nnx.selu(self.layer_2(x)) x = self.layer_3(x) return x

7、实例化模型

JAX 处理随机数的方式比较特别。这里用

nnx.Rngs(0)

初始化一个种子为 0 的随机数生成器 (RNG) 对象。这个对象负责管理网络操作里的所有随机性,比如参数初始化和 Dropout。

注意,这和 PyTorch 直接设全局种子

torch.manual_seed(seed)

的逻辑不一样。

# Initialize random number generator rngs = nnx.Rngs(0) # Create instance of the classifier model = DigitClassifier(n_features=64, n_hidden=128, n_targets=10, rngs = rngs)

8、定义优化器与训练步骤

用 Optax 定义优化器和损失函数。

import jax import optax # SGD optimizer with learning rate 0.05 optimizer = nnx.ModelAndOptimizer( model, optax.sgd(learning_rate=0.05)) # Loss function def loss_fn(model, data, labels): # Forward pass logits = model(data) # Compute mean cross-entropy loss loss = optax.softmax_cross_entropy_with_integer_labels( logits=logits, labels=labels).mean() return loss, logits # Single training step with automatic differentiation and optimization @nnx.jit # JIT compile for faster execution def training_step(model, optimizer, data, labels): loss_gradient = nnx.grad(loss_fn, has_aux=True) # 'has_aux=True' allows returning auxiliary outputs (logits) grads, logits = loss_gradient(model, data, labels) # Forward + backward pass optimizer.update(grads) # Update model parameters using computed gradients

代码里用到了两个核心变换,这是 JAX 高效的秘诀:

jax.jit

:即时编译,把训练函数扔给 XLA 编译器,重复执行速度极快。

jax.grad

:利用自动微分计算梯度。

Flax NNX 把它俩封装成了装饰器

nnx.jit

nnx.grad

,用起来更方便。

9、训练循环

跑 500 epoch,每 100 轮显示 Loss。

num_epochs=500 print_every=100 forepochinrange(num_epochs+1): # Training step training_step(model, optimizer, images_train, label_train) # Evaluate and print metrics periodically ifepoch%print_every==0: train_loss, _=loss_fn(model, images_train, label_train) test_loss, _=loss_fn(model, images_test, label_test) print(f"Epoch {epoch:3d} | Train Loss: {train_loss:.4f} | Test Loss: {test_loss:.4f}") """ Epoch 0 | Train Loss: 0.0044 | Test Loss: 0.1063 Epoch 100 | Train Loss: 0.0035 | Test Loss: 0.1057 Epoch 200 | Train Loss: 0.0029 | Test Loss: 0.1054 Epoch 300 | Train Loss: 0.0024 | Test Loss: 0.1052 Epoch 400 | Train Loss: 0.0021 | Test Loss: 0.1051 Epoch 500 | Train Loss: 0.0019 | Test Loss: 0.1050 """

10. 效果评估

最后看看在测试集上的表现。

# Evaluate model accuracy on test set logits = model(images_test) predictions = logits.argmax(axis=1) correct = jnp.sum(predictions == label_test) total = len(label_test) accuracy = correct / total print(f"Test Accuracy: {correct}/{total} correct ({accuracy:.2%})") # Test Accuracy: 437/450 correct (97.11%)

97% 的准确率,对于这么简单的网络来说相当不错了。

最后把预测结果可视化一下,绿色是对的,红色是错的。

fig, axes = plt.subplots(10, 10, figsize=(6, 6), subplot_kw={'xticks':[], 'yticks':[]}, gridspec_kw=dict(hspace=0.1, wspace=0.1)) for i, ax in enumerate(axes.flat): ax.imshow(images_test[i], cmap='binary', interpolation='gaussian') color = 'green' if label_pred[i] == label_test[i] else 'red' ax.text(0.05, 0.05, str(label_pred[i]), transform=ax.transAxes, color=color)

到这里,你就已经在 JAX 生态里跑通了第一个神经网络。JAX 的门槛其实没那么高,但它带来的性能收益,特别是在大规模训练场景下,绝对值得投入时间去学。

作者:Dr. Ashish Bamania

http://www.cnnetsun.cn/news/77146.html

相关文章:

  • 雀魂数据分析终极指南:如何用牌谱屋3周提升段位?
  • 解锁船舶设计新维度:开源船舶设计软件的实战应用指南
  • 5大脚本工具实战:让ESP32 AI助手开发效率飙升90%
  • 1、深入了解Solaris 10:从操作系统基础到实践操作
  • 3、Solaris 系统启动与关机操作全解析
  • 15、Solaris高级安装方法全解析
  • OpenModScan工业通讯调试全攻略:从入门到精通
  • CIDR合并工具终极指南:简单快速管理IP地址
  • 桌面宠物终极选择指南:从使用场景到性能实测的完整决策方案
  • MQTT Explorer:可视化你的MQTT网络世界
  • ML307 4G模块:xiaozhi-esp32移动网络终极接入方案
  • 树莓派系统烧录神器:Raspberry Pi Imager 5大实战技巧全解析
  • 开源Android输入法终极选择:OpenBoard完全使用指南
  • ExoPlayer状态恢复黑科技:告别进度丢失的终极指南
  • Foliate电子书阅读器:重新定义数字时代的阅读艺术
  • 36、系统管理工具与网络技术实用指南
  • JavaScript反混淆终极指南:快速处理Obfuscator混淆代码的完整教程
  • 2、探索 PC - BSD:开源操作系统的新选择
  • 11、PC-BSD系统常见操作与设置指南
  • 微信自动化技术探秘:打造智能微信机器人的完整指南
  • WinUtil插件开发深度实战:从零构建高效系统工具
  • Obsidian Zotero集成:科研工作流自动化的完整指南
  • 探索Unitree RL Gym强化学习的无限可能:从仿真到实体的智能机器人进化之路
  • 38、搭建Web和FTP服务及数据备份与恢复指南
  • 5分钟上手OCAT:让OpenCore配置变得像玩游戏一样简单![特殊字符]
  • CSS网格生成器:可视化布局设计的终极解决方案
  • JPEGView:重新定义极简图像浏览体验的5个关键特性
  • 终极指南:在Vue项目中快速集成轻量级Markdown编辑器
  • 24、在 Fedora 系统中搭建 Web 和 FTP 服务
  • Synology硬盘兼容性终极解决方案:让群晖NAS支持所有第三方硬盘