# 逻辑回归中的零知识证明

### **逻辑回归的执行流程**

先来看看Delta中的逻辑回归任务的执行流程，这里我们使用横向联邦学习的方式来运行逻辑回归任务（纵向的零知识证明实现是类似的）：

<figure><img src="/files/JNnNI0mNWWlhJMXxTrBY" alt=""><figcaption><p>用安全聚合执行的逻辑回归流程</p></figcaption></figure>

在逻辑回归任务中，参与方有一个"任务发起者"，就是购买者，还有多个"计算节点"，也就是数据持有者。图中只画出了一个计算节点，因为每个计算节点的流程都是一样的。

每个任务的执行分为多个轮次，图中画出的是其中一个。首先任务发起者将当前的模型权重发送给全部的计算节点，计算节点用其当作初始权重，在本地的隐私数据上进行训练，得到了更新的梯度值，发送回任务发起者。任务发起者将多个计算节点的梯度值求和后，得到了全局的梯度值，用全局的梯度值更新模型权重，就完成了一轮计算。如果全局梯度值不为零，说明模型还没有收敛，就继续执行下一轮。

注意计算节点发送回任务发起者的单节点梯度值，实际上不是明文发送的，因为单节点梯度值某种程度上也暴露了节点上数据的隐私。这里使用了横向联邦学习的安全聚合方法，每个计算节点给自己的梯度值加上一个掩码，再发送出来。安全聚合方法保证了所有计算节点的掩码后梯度值求和，可以得到准确的全局梯度值，但是无法获取到任何一个掩码前的单节点梯度值。

在最后一轮训练后，任务发起者发现全局梯度值等于零（小于某个设定好的阈值），即可判断模型已经收敛，本次任务已经成功结束：

<figure><img src="/files/vFNX7ooeewikbIMVlGz5" alt=""><figcaption><p>模型收敛的最后一轮训练</p></figcaption></figure>

### **逻辑回归任务的验证**

在最后一轮训练结束，任务发起者判断模型已经收敛后，就要开始互相猜疑的付费过程了。任务发起者怀疑计算是假的，或者数据是假的。计算节点害怕任务发起者不付费。两方都可能出于各种原因不配合后续的流程。因此我们的验证流程需要站在"支付宝"，就是区块链的角度，看看做为一个中间人，为了能够验证逻辑回归的正确执行，都需要哪些信息。

#### **从"过程验证"到"结果验证"**

由于逻辑回归任务是一轮一轮执行的，最直接的验证流程设计，就是每一轮计算都由计算节点生成一个零知识证明，提交给区块链，证明自己按照要求完成了计算。这就是"计算过程验证"。

在逻辑回归中，每一轮计算节点的输出是一个经过掩码的梯度值，如果对这个梯度值生成零知识证明，就需要把安全聚合的整个计算过程也嵌入进去，会导致零知识证明极其复杂。同时零知识证明的生成成本也很高，速度很慢，如果每一轮都需要生成的话，系统就不可用了。

Delta中对此做了一个优化，不在每一轮都要求计算过程验证，只在最后计算完成后，要求计算节点提交一个"模型收敛"的证明。站在任务发起者的视角，只要最后得到的模型收敛，并且是在我要求的数据上收敛，结果就已经满意了，而不在意计算节点到底是怎么计算的。

这样在整个任务过程中，计算节点只需要在最后生成一个零知识证明，提交给区块链，区块链验证通过，就可以结束了。

#### **零知识证明需要验证的内容**

我们回到区块链的视角，一个数据交易任务到底怎么样才算成功完成？除了模型收敛以外，需要包括从原始数据到模型传输的全部过程，其中任何一步没有完成，数据交易都不算成功：

1. 计算节点在任务中使用了之前上链的数据（原始数据证明）
2. 计算节点最终给出的模型收敛（模型收敛证明）
3. 最终模型给到了任务发起者（模型接收证明）

第1、2点前文已经介绍过了。第3点是一个新的要求，因为如果计算节点仅仅是算出了正确的模型，但是没有发送给对方，那交易是失败的。

零知识证明是提交给区块链的，而模型是提交给任务发起者的，如果计算节点没有把最终的模型发送给任务发起者，只是把生成正确模型的证据给了区块链，这时候是需要区块链自行判断模型是否给到了任务发起者，如果计算节点说给了，发起者说没给，这个交易是否成功完成，就无从判断了。

除了上述3点以外，还有一点需要验证的，就是计算节点提交的证明，是针对任务发起者这次的任务。保证计算节点不能用一个以前的任务的有效证明，通过这次这个任务的验证。

接下来我们详细介绍零知识证明对这几点的实现。我们把零知识证明抽象成一组输入和输出：公开输入、秘密输入、公开输出。输入和输出是和计算步骤对应的，零知识证明一个是可以将某些输入设置为外部不可见的，在此基础上，证明提交Proof数据的人**知道一组秘密输入，和公开输入一起，按照之前定义的计算步骤，确实计算出了公开输出。**&#x516C;开输入和公开输出能够从Proof数据中提取出来，对外部可见，秘密输入无法提取。

零知识证明的设计，就转变为了输入和输出的设计。

#### **原始数据证明**

零知识证明的其中一个秘密输入，是原始数据。通过在零知识证明中计算原始数据的哈希值，并且把哈希值做为公开输出公布出来，就实现了对原始数据的溯源。如果Proof通过了验证，说明本次计算使用的数据，其哈希值确实是输出的值。区块链进一步将哈希值和链上记录的哈希值进行比对，就可以确认执行计算所用到的数据，确实是之前链上登记过的。

#### **模型收敛证明**

模型收敛的判断方法是所有的计算节点输出的梯度值的和小于阈值。因此单个节点生成的零知识证明无法直接证明模型收敛。因此需要在零知识证明中，将梯度值作为公开输出公布出来，区块链拿到所有节点的梯度值后求和，即可判断模型是否已经收敛。

由于只在模型收敛后计算一轮零知识证明，只公开最后一轮的梯度值，不会暴露节点的隐私数据。

#### **模型接收证明**

这一步的证明比较巧妙。因为一般来说，如果对方抵赖的话，我们很难证明模型已经发送给了对方。

我们回头去看最后一轮的执行流程。在执行开始的时候，任务发起方需要将初始的模型权重发送给计算节点。而这一轮模型训练得到的梯度值是接近零的，就是说，这一轮任务发起方发出去的模型，其实就是最终收敛的模型。

这样我们就可以实现证明了。在零知识证明的秘密输入中，加入上一轮模型权重，然后在公开输出中输出上一轮权重的哈希。然后在轮次启动时，要求任务发起者将模型权重的哈希值上链。这样当零知识证明通过验证时，说明模型收敛，并且模型权重的哈希值是A。然后A实际上已经由任务发起者上过链了，任务发起者既然可以生成其哈希值A，说明它已经拥有哈希值A对应的收敛的模型了。

至此，零知识证明的设计已经完成了。完整的设计如下图所示：

<figure><img src="/files/FtT6SwUvxkY6TfH1GtLI" alt=""><figcaption><p>Delta中零知识证明的设计</p></figcaption></figure>

加上区块链和零知识证明的任务执行流程如下图所示：

<figure><img src="/files/eLkxpULJzfD4VkPSWHtt" alt=""><figcaption><p>带零知识证明的逻辑回归任务执行流程</p></figcaption></figure>

每一轮的执行由任务发起者开始，任务发起者首先根据自己的任务类型，选择对应的链上ZK验证合约，做为参数放入任务中。这一步是为了实现上文提到的，保证零知识证明和任务的对应关系，防止计算节点提交一个其他任务的零知识证明而欺骗系统。另外，由于目前Delta只支持逻辑回归的证明，而所有的逻辑回归任务的零知识证明结构都是一样的，只有样本维度数量的差异。通过在链上预置其验证方法，避免了任务发起者每次提交任务，都要生成一个对应的新合约。并且计算节点也不用每次都去验证这个合约的正确性。

然后开始执行任务了，任务发起者先将当前的模型权重的哈希值上链，然后将权重发送给各个计算节点，开始本轮的计算。计算节点收到初始权重后，需要自行验证其哈希值和链上一致，否则最后的零知识证明无法通过，就收不到钱。

当任务发起者判断模型收敛后，可以发起结算流程。为避免任务发起者不做为，结算流程也可由计算节点在任务超时后发起。

结算流程开始后，计算节点按照上面的零知识证明设计生成Proof数据，提交到区块链。当全部计算节点的Proof数据都上链了以后，区块链开始执行验证流程：

<figure><img src="/files/wxWNZHB9Gpi8w3ccHPQN" alt=""><figcaption><p>区块链上的逻辑回归任务验证流程</p></figcaption></figure>

区块链首先用任务选定的ZK验证合约验证每一个Proof数据的正确性，保证计算节点提交的Proof数据是针对当前任务的，并且能通过验证。

然后从Proof数据中提取出隐私数据哈希、上一轮权重哈希和梯度值。

验证隐私数据哈希之前都已经上链。验证上一轮权重哈希和任务发起者之前上链的哈希值一致。

将所有计算节点的梯度值相加，判断是否小于阈值，即模型是否收敛。

如果全部验证通过，说明交易成功完成。可以走后续的转账流程了。Delta中目前没有实现转账相关的流程，到这里就标记任务成功了。

至此我们就完成了整个逻辑回归的验证流程设计。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.deltampc.com/system-design/zero-knowledge-proof-in-logistical-regression-task.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
