Transformer 模型,如 BERT 或其轻量化版本,在自然语言处理任务中表现出色。然而,由于其复杂的矩阵乘法和注意力机制,它们对移动端性能提出了巨大挑战。iPhone 上的神经引擎(ANE)是实现高性能端侧推理的关键,但需要模型以 Core ML 格式进行优化。
本文将重点介绍如何使用 coremltools 将 PyTorch 模型转换为 Core ML 格式,并利用 FP16 精度优化,从而最大化地利用 ANE 的加速潜力。
准备工作
确保你安装了必要的库:PyTorch 用于模型定义,以及 Core ML Tools 用于转换。
pip install torch torchvision coremltools onnx
步骤一:定义并导出 PyTorch 模型
为了演示,我们创建一个简化的 PyTorch 模型,模拟 Transformer 中的一个关键线性层和激活层。
import torch
import torch.nn as nn
import coremltools as ct
# 1. 定义一个简化的 PyTorch 模型 (例如,一个Transformer Feed-Forward层)
class SimpleTransformerBlock(nn.Module):
def __init__(self, input_size, hidden_size):
super(SimpleTransformerBlock, self).__init__()
self.linear1 = nn.Linear(input_size, hidden_size)
self.relu = nn.ReLU()
self.linear2 = nn.Linear(hidden_size, input_size)
def forward(self, x):
x = self.linear1(x)
x = self.relu(x)
x = self.linear2(x)
return x
# 实例化模型并加载权重 (此处随机初始化)
input_size = 512
hidden_size = 2048
model = SimpleTransformerBlock(input_size, hidden_size)
model.eval()
# 准备示例输入 (批次大小 1, 序列长度 64, 特征维度 512)
sample_input = torch.randn(1, 64, input_size)
# 2. 导出为 ONNX 格式 (可选步骤,但推荐作为中间检查)
input_names = ["input_tensor"]
output_names = ["output_tensor"]
onnx_path = "simple_transformer_block.onnx"
torch.onnx.export(
model,
sample_input,
onnx_path,
verbose=False,
input_names=input_names,
output_names=output_names,
opset_version=14 # 推荐使用较新的 opset
)
print(f"PyTorch模型已导出至 {onnx_path}")
步骤二:使用 Core ML Tools 进行 FP16 优化转换
Core ML Tools 允许我们指定 compute_precision 为 FLOAT16。这是实现 ANE 加速的关键步骤,因为 ANE 在处理 FP16 数据类型时效率最高,同时对模型精度损失很小。
我们还将设置 minimum_deployment_target。对于复杂的 Transformer 操作,建议将目标设置为 iOS 16 或更高版本,以确保 Core ML 编译器能够利用最新的 ANE特性和优化融合。
# 3. 使用 coremltools 转换 ONNX 模型,并应用 FP16 优化
# 定义输入规范
# 形状需要设置为 (1, 64, 512) 并且指定尺寸是固定的或可变动的。
# 对于 NLP 任务,通常序列长度是可变的,但为简化,我们先定义固定尺寸。
input_shape = ct.Shape(shape=(1, 64, input_size))
input_spec = ct.TensorType(name="input_tensor", shape=input_shape)
# 执行转换
coreml_model = ct.convert(
model=onnx_path,
inputs=[input_spec],
compute_precision=ct.precision.FLOAT16, # 核心优化:使用半精度浮点数
minimum_deployment_target=ct.target.iOS16, # 确保支持最新的 ANE 特性
convert_to="mlprogram" # 推荐使用新的 mlprogram 格式,它提供更好的优化
)
# 4. 保存 Core ML 模型
coreml_path = "OptimizedTransformerBlock.mlpackage"
coreml_model.save(coreml_path)
print(f"模型已成功转换为 Core ML 格式并优化为 FP16:{coreml_path}")
# 5. 验证模型优化信息 (可选)
print("\n--- 模型优化详情 ---")
print(f"计算精度: {coreml_model.compute_precision}")
print(f"部署目标: {coreml_model.minimum_deployment_target}")
优化原理与总结
- FLOAT16 精度:iPhone 的 ANE 是针对低精度计算(主要是 FP16 和 INT8)设计的。通过将模型从标准的 FP32 转换为 FP16,我们大幅减少了数据传输量,并确保操作可以被 ANE 高效地硬件加速。
- ML Program 格式:使用 convert_to=”mlprogram”(这是 Core ML Tools 7+ 的推荐做法)可以生成更灵活、更优化的模型格式,允许 Core ML 编译器在部署时执行更多的图层融合和内存优化。
- Deployment Target:设置较高的部署目标(如 iOS 16+)能够确保转换器使用最新的 Core ML 操作集,这些操作集对复杂的 Transformer 结构(如多头注意力)具有更好的原生支持和优化融合。
汤不热吧