框架模型层
使用了 PyTorch XLA
来在 XLA(如 TPU 等加速设备)上运行张量操作。
-
引入
torch
、torch_xla
和torch_xla.core.xla_model
,用于在 XLA 设备上执行 PyTorch 操作。 -
使用
torch.randn(2, 2, device=xm.xla_device())
创建一个 2x2 的随机张量t
,并将其分配到 XLA 设备。 -
创建两个 2x2 的随机张量
t0
和t1
,并进行逐元素加法和矩阵乘法,打印结果。 -
创建一个大小为 10 的随机输入向量
l_in
,并将其分配到 XLA 设备。 -
定义一个输入特征为 10、输出特征为 20 的线性层
linear
,并迁移到 XLA 设备。 -
将输入
l_in
传入线性层,得到输出l_out
,并打印输出结果。
import torch
import torch_xla
import torch_xla.core.xla_model as xm
t = torch.randn(2, 2, device=xm.xla_device())
print(t.device)
print(t)
t0 = torch.randn(2, 2, device=xm.xla_device())
t1 = torch.randn(2, 2, device=xm.xla_device())
print(t0 + t1)
print(t0.mm(t1))
#神经网络
l_in = torch.randn(10, device=xm.xla_device())
linear = torch.nn.Linear(10, 20).to(xm.xla_device())
l_out = linear(l_in)
print(l_out)
结果
xla:0
tensor([[ 0.1028, -1.4783],
[-0.4271, 1.3415]], device='xla:0')
tensor([[ 1.7679, 0.2210],
[ 0.5831, -1.5733]], device='xla:0')
tensor([[ 0.6698, -0.5113],
[ 0.9527, 0.2601]], device='xla:0')
tensor([-0.8333, 0.4356, 0.4277, -0.3944, 0.8075, 0.3516, 0.0455, 0.0778,
-0.0822, 0.4418, -0.7217, 0.3582, -0.7285, 0.1117, -0.0466, -0.7045,
-0.1443, 0.3461, -0.3151, -0.6094], device='xla:0',
grad_fn=<AddBackward0>)
实现了一个使用 PyTorch XLA
再 TPU 训练和评估 MNIST 手写数字分类模型的完整流程,包括数据加载、模型构建、训练、保存和推理。
- 引入所需的 PyTorch 和 Torch XLA 库,以及 MNIST 数据集和数据处理工具。设置设备为 TPU,使用
xm.xla_device()
。 - 使用
transforms.Compose
创建数据转换,将 MNIST 数据集中的图像转换为张量。下载 MNIST 训练集并创建数据加载器train_loader
,设置批量大小为 64,并随机打乱数据。 - 定义一个简单的神经网络模型,包括:扁平化层,将 28x28 的图像展平成一维。128 单元的全连接层,使用 ReLU 激活函数。10 单元的全连接层,使用 LogSoftmax 激活函数。将模型迁移到 TPU 设备。
- 使用负对数似然损失函数
NLLLoss
。使用随机梯度下降优化器SGD
,学习率为 0.01,动量为 0.9。 - 对训练数据进行迭代:清零优化器的梯度。将数据和目标迁移到 TPU 设备。通过模型进行前向传播,计算损失。进行反向传播以计算梯度。更新模型参数。调用
xm.mark_step()
同步 TPU。 - 使用
torch.save()
保存训练好的模型到mnist_model_full.pth
文件中。 - 加载保存的模型,并将其迁移到 TPU 设备,切换到评估模式。
- 在不计算梯度的上下文中:遍历测试数据,迁移到 TPU 设备。进行前向传播,计算输出。使用
torch.max()
获取预测结果的最大值索引。打印预测结果,且仅处理一个批次作为示例。
import torch
import torch.nn as nn
import torch.optim as optim
import torch_xla.core.xla_model as xm
from torch.utils.data import DataLoader
from torchvision.datasets import MNIST
from torchvision import transforms
# 设备设定(TPU)
device = xm.xla_device()
# 数据集与数据加载器设定
transform = transforms.Compose([transforms.ToTensor()])
train_dataset = MNIST(root='data', train=True, transform=transform, download=True)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
# 模型设定
model = nn.Sequential(
nn.Flatten(),
nn.Linear(28*28, 128),
nn.ReLU(),
nn.Linear(128, 10),
nn.LogSoftmax(dim=1)
).to(device)
# 损失函数和优化器设定
loss_fn = nn.NLLLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
# 训练循环
for data, target in train_loader:
optimizer.zero_grad()
data = data.to(device)
target = target.to(device)
output = model(data)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
xm.mark_step() # TPU同步
# 保存整个模型
torch.save(model, 'mnist_model_full.pth')
# 模型推理
import torch
# 加载整个模型
model = torch.load('mnist_model_full.pth').to(device)
model.eval() # 切换到评估模式
# 加载测试数据
test_dataset = MNIST(root='data', train=False, transform=transform, download=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)
# 使用模型进行推理
with torch.no_grad(): # 禁用梯度计算以加快推理
for data, _ in test_loader:
data = data.to(device)
output = model(data)
xm.mark_step() # TPU同步
# 获取预测结果
_, predicted = torch.max(output, 1)
print(predicted)
break # 仅处理一个批次的示例
结果
tensor([7, 2, 1, 0, 4, 1, 4, 9, 6, 9, 0, 6, 9, 0, 1, 5, 9, 7, 3, 4, 9, 6, 6, 5,
4, 0, 7, 4, 0, 1, 3, 1, 3, 6, 7, 2, 7, 1, 2, 1, 1, 7, 4, 2, 3, 5, 1, 2,
4, 4, 6, 3, 5, 5, 6, 0, 4, 1, 9, 5, 7, 8, 4, 3], device='xla:0')
将一个 PyTorch 模型导出并转换为一种适合跨平台应用的格式( StableHLO ),以便进行优化、部署和进一步分析。
- 模型加载:加载了预训练的 ResNet-18 模型,使用
torchvision
提供的默认权重。 - 样本输入生成:创建了一个形状为
(4, 3, 224, 224)
的随机张量,模拟输入的图像数据。 - 模型导出:使用
export
函数将 ResNet-18 模型导出为中间表示,以便后续处理。 - 转换为 StableHLO:将导出的模型转换为 StableHLO 格式,适用于跨平台优化和部署。
- 输出 StableHLO 文本:打印模型前向计算图的 StableHLO 文本表示的前 400 个字符,以供检查和分析。
import torch
import torchvision
from torch.export import export
resnet18 = torchvision.models.resnet18(weights=torchvision.models.ResNet18_Weights.DEFAULT)
sample_input = (torch.randn(4, 3, 224, 224), )
exported = export(resnet18, sample_input)
from torch_xla.stablehlo import exported_program_to_stablehlo
stablehlo_program = exported_program_to_stablehlo(exported)
print(stablehlo_program.get_stablehlo_text('forward')[0:400],"\n...")
结果
module @IrToHlo.484 attributes {mhlo.cross_program_prefetches = [], mhlo.is_dynamic = false, mhlo.use_auto_spmd_partitioning = false} {
func.func @main(%arg0: tensor<1000xf32>, %arg1: tensor<1000x512xf32>, %arg2: tensor<512xf32>, %arg3: tensor<512xf32>, %arg4: tensor<512xf32>, %arg5: tensor<512xf32>, %arg6: tensor<512x256x1x1xf32>, %arg7: tensor<256xf32>, %arg8: tensor<256xf32>, %arg9: tensor<25
...
- 定义一个简单的加法模型,并创建输入数据。
- 将模型导出为中间表示,并转换为 StableHLO 格式,便于跨平台应用和优化。
- 最后,输出转换后的模型信息,便于分析和调试。
import torch
import torch.nn as nn
from torch.export import export
from torch_xla.stablehlo import exported_program_to_stablehlo
# 定义一个简单的加法模型
class AddModel(nn.Module):
def __init__(self):
super(AddModel, self).__init__()
def forward(self, x, y):
return x + y
# 创建模型实例
add_model = AddModel()
# 创建示例输入
x_input = torch.randn(4, 3, 224, 224) # 第一个输入
y_input = torch.randn(4, 3, 224, 224) # 第二个输入
# 使用 export 函数导出模型
exported = export(add_model, (x_input, y_input))
# 将导出的模型转换为 StableHLO 格式
stablehlo_program = exported_program_to_stablehlo(exported)
# 打印 StableHLO 程序文本的一部分
print(stablehlo_program.get_stablehlo_text('forward')[0:400], "\n...")
结果
module @IrToHlo.8 attributes {mhlo.cross_program_prefetches = [], mhlo.is_dynamic = false, mhlo.use_auto_spmd_partitioning = false} {
func.func @main(%arg0: tensor<4x3x224x224xf32>, %arg1: tensor<4x3x224x224xf32>) -> tensor<4x3x224x224xf32> {
%0 = stablehlo.add %arg1, %arg0 : tensor<4x3x224x224xf32>
return %0 : tensor<4x3x224x224xf32>
}
}
实现了使用 TensorFlow 定义一个简单的神经网络模型,生成随机输入,并使用 XLA(加速线性代数)优化进行前向传播。
- 使用
tf.config.list_physical_devices('GPU')
检查可用的 GPU 数量。输出可用 GPU 的数量。 - 使用
tf.keras.Sequential
创建一个顺序模型。第一层是一个全连接层(Dense),有 10 个单元,输入维度为 10,激活函数为 ReLU。第二层是另一个全连接层,包含 5 个单元,激活函数为 softmax。 - 定义批量大小(
batch_size
)为 16,输入向量维度(input_vector_dim
)为 10。使用tf.random.normal
生成形状为(16, 10)
的随机输入。 - 使用
@tf.function(jit_compile=True)
装饰器定义前向传播函数,以启用 XLA 优化。函数接受输入并返回模型的输出。 - 调用前向传播函数
forward_pass
,传入随机输入进行计算。
import tensorflow as tf
print("Num GPUs Available: ", len(tf.config.list_physical_devices('GPU')))
# Define the model
model = tf.keras.Sequential(
[tf.keras.layers.Dense(10, input_shape=(10,), activation="relu"),
tf.keras.layers.Dense(5, activation="softmax")]
)
# Generate random inputs for the model
batch_size = 16
input_vector_dim = 10
random_inputs = tf.random.normal((batch_size, input_vector_dim))
# Run a forward pass
_ = model(random_inputs)
# Compile the model function with XLA optimization
@tf.function(jit_compile=True)
def forward_pass(inputs):
return model(inputs)
# Run the forward pass with XLA
_ = forward_pass(random_inputs)
结果
I0000 00:00:1727407770.382644 1007512 service.cc:146] XLA service 0x8ec22c0 initialized for platform CUDA (this does not guarantee that XLA will be used). Devices:
I0000 00:00:1727407770.382662 1007512 service.cc:154] StreamExecutor device (0): NVIDIA GeForce RTX 4080 SUPER, Compute Capability 8.9
2024-09-27 11:29:30.387574: I tensorflow/compiler/mlir/tensorflow/utils/dump_mlir_util.cc:268] disabling MLIR crash reproducer, set env var `MLIR_CRASH_REPRODUCER_DIRECTORY` to enable.
2024-09-27 11:29:31.040309: I external/local_xla/xla/stream_executor/cuda/cuda_dnn.cc:531] Loaded cuDNN version 8907
I0000 00:00:1727407771.151882 1007512 device_compiler.h:188] Compiled cluster using XLA! This line is logged at most once for the lifetime of the process.