零知识证明使"证明计算正确"成为可能——zkML 将这个魔法带到 AI 领域:在不暴露模型权重和输入数据的前提下,证明"AI 模型的推理输出是正确计算的"。这是 2024 年最活跃的密码学前沿之一。
11.4.1 核心问题:为什么 AI 需要零知识证明?
AI 系统在链上应用面临三个信任缺口:
- 模型黑盒:如何相信"AI 没有作弊"或"使用了声称的模型"?
- 数据隐私:医疗/金融 AI 不能泄露训练数据/模型权重
- 算力验证:如何验证链下 GPU "确实执行了"计算
zkML 一次性解决这三个问题:
其中 是模型, 是输入, 是权重, 是输出。验证者仅看到 和证明 ,无法反推 或 。
11.4.2 将神经网络转化为可验证电路
The Problem: Non-linearities
线性运算(矩阵乘法、卷积)在有限域上可以直接表示为算术电路——zk-SNARK 的天然语言。但神经网络的核心是非线性激活函数:
- ReLU: — 不可微,但可表示为电路约束:
- Sigmoid: — 指数非多项式
- 特殊函数(sin, cos, tanh)— 无限级数
三种工程方案
| 方案 | 原理 | 精度损失 | 证明成本 |
|---|---|---|---|
| 分段线性化 | 将 ReLU/激活函数量化为多项式段(如 3-5 段) | 中 | 中(电路深度 ~) |
| 查找表(Lookup) | 将激活函数与预计算表进行对照 | 低 | 中(需要 IOP + 承诺) |
| 自定义门(Folding) | Nova/Supernova 支持非均匀电路段 Folding | 无 | 较低(递归折叠) |
浮点数向定点数转换
浮点运算在有限域电路中不可行。标准做法是变为定点数位宽(如 -bit 定点数):
典型选择:(缩放 65536x),域 为 254 位素数(BN254)。这增加了量化误差,但允许完整电路化。
typescript
/**
* 定点数量化与模拟激活函数的 zk-circuit 兼容版本
* 将浮点神经网络权重/激活量化到定点数空间
*/
interface FixedPointConfig {
scale: number; // 2^k scaling factor
bitWidth: number; // 总位宽
isSigned: boolean;
}
class QuantizedNeuralNet {
private weights: bigint[][][]; // [layer][neuron][input] 定点权重
private scale: number;
private fieldPrime: bigint = 21888242871839275222246405745257275088548364400416034343698204186575808495617n; // BN254
constructor(weights: number[][][], config: FixedPointConfig) {
this.scale = config.scale;
this.weights = weights.map(layer =>
layer.map(neuron =>
neuron.map(w => this.toFixedPoint(w))
)
);
}
toFixedPoint(x: number): bigint {
// x as Q_k: original value * scale, rounded, modulo field prime
return BigInt(Math.round(x * this.scale)) % this.fieldPrime;
}
fromFixedPoint(x: bigint): number {
// 必须有符号处理,这里简化
const halfP = this.fieldPrime / 2n;
const signed = x >= halfP ? x - this.fieldPrime : x;
return Number(signed) / this.scale;
}
/**
* 电路兼容的 ReLU:y = max(0, x)
* 在 zk 电路中实现为三路约束:
* (1) y >= 0
* (2) y - x >= 0
* (3) y * (y - x) = 0
*/
circuitReLU(x: bigint): bigint {
// 直接模拟:实际电路中用约束表示
return x > this.fieldPrime / 2n ? 0n : x; // 简化 unsigned 版本
}
// 前向传播(量子化 + 激活 = 定点数)
forward(input: number[]): bigint[] {
let current = input.map(x => this.toFixedPoint(x));
for (const layer of this.weights) {
const next = layer.map(neuron => {
const sum = neuron.reduce((s, w, i) => {
const prod = (w * current[i]) % this.fieldPrime;
// 缩放回燃:由于 w 和 x 都是 scaled 的,乘积有 scale^2
// 需要除以 scale 进行重规范化
const rescaled = prod / BigInt(this.scale);
return (s + rescaled) % this.fieldPrime;
}, 0n);
return this.circuitReLU(sum);
});
current = next;
}
return current;
}
}
// 安全量化限制:
// scale^2 * max(|w|) * max(|x|) < fieldPrime/2
const net = new QuantizedNeuralNet(
[ // 2层, 3-2-1
[[1.5, -0.5, 0.3], [-0.2, 1.0, -0.1]], // 层1: 3->2
[[0.8, -1.2]], // 层2: 2->1
],
{ scale: 1000, bitWidth: 16, isSigned: true }
);
console.log("定点前向:", net.forward([2.0, 1.0, -0.5]).map(o => net.fromFixedPoint(o)));
// 输出与浮点版本接近(量化误差范围内)11.4.3 递归证明与实时推理
对于大模型,证明生成依然是瓶颈。解决方案是递归折叠(Nova/Supernova):
最终只需要一个常数大小的最终证明。zkML 的产业链正在形成:
- EZKL(以太坊原生):用 Halo2 证明 ONNX 模型
- Orion(Cairo1.0):StarkNet 生态
- RISC Zero:zkVM 路线(任意 Rust 程序 -> ZK 证明)
graph LR
subgraph 模型层
ONNX[ONNX / PyTorch]
OP[算子分解]
end
subgraph 电路层
CIR[算术电路 / R1CS]
LOOKUP[查找表激活函数]
end
subgraph 证明层
SNARK[zk-SNARK / Halo2]
STARK[zk-STARK / STARKs]
VM[zkVM / RISC Zero]
end
ONNX --> OP --> CIR --> SNARK
CIR --> LOOKUP --> STARK
ONNX --> |"Rust 编译"| VM
style SNARK fill:#c8e6c9
style STARK fill:#c8e6c9
style VM fill:#c8e6c9
11.4.4 zkML 的局限与前沿
当前限制
| 模型规模 | 证明时间 | 验证时间 | 状态(2024) |
|---|---|---|---|
| MLP (< 1000 参数) | 秒级 | 毫秒 | 已可用 |
| 小 CNN (< 10K 参数) | 分钟级 | 毫秒 | 实验可用 |
| ResNet-50 | 小时级 | 毫秒 | 研究前沿 |
| GPT-2 级别 | 天级 | 毫秒 | 理论可行 |
| 现代大模型 | — | — | 开放研究 |
突破方向
- 混合推理:大部分模型在链下运行(TEE 保护),仅关键决策层用 zkML 验证
- 硬件加速:ASIC/FPGA 专门为 ZK 证明中的 FFT 和 MSM(多标量乘法)优化
- 聚合证明:1000 个推理请求生成 1000 个证明,递归压缩为 1 个
> ← 上一节:11.3 联邦学习 | 前往 → 11.5 AI 代理与智能合约 |*
评论
0评论加载中…