链桨PaddleDTX-基于区块链的联邦学习解决方案

2021.12月12日,在WAVE SUMMIT+2021深度学习开发者峰会上,飞桨与百度超级链联合发布了首款“产业级”可信分布式AI产品——链桨(Paddle DTX),并宣布开源。该产品基于区块链、去中心化存储、可信计算以及分布式机器学习等技术,推动实现数据采集、存储、计算、及流通全流程安全可信,打破数据孤岛,让数据发挥更大价值。
视频地址:https://www.bilibili.com/video/BV1SZ4y1974W?share_source=copy_web

演讲位于1:35:16处

  • 链桨微信文章:https://mp.weixin.qq.com/s/1ASfcpxgt7DjEs1m15fHxA
  • “链桨”开源代码:
    https://github.com/PaddlePaddle/PaddleDTX
  • “链桨”开源文档:
    https://paddledtx.readthedocs.io/

如果想快速了解,可以集直接进入快速精简PaddleDTX联邦学习实践

以下部分为一步步执行,可以从头实现链桨部署实践,更有利于学习和加深理解。本项目步骤要比精简实践模式复杂很多,不可控因素也更多,建议fork本项目后,启动后先直接打开快速精简执行PaddleDTXfasttrain.ipynb页面,而不是本页面main.ipynb,因为这个主页面真的相当复杂,而且非常卡!

本项目好几次出问题之后百思不得其解,在通过咨询链桨工程师、报bug,百度搜索以及看官方手册、代码等多渠道方法后,又柳暗花明又一村。大部分问题都已解决,目前大约只剩下一个编译合约问题遗留。附录中记录了bug解决过程,希望大家都少踩坑!

PaddleDTX简介

PaddleDTX,是一个基于去中心化存储的专注于分布式机器学习技术的解决方案,攻克海量隐私数据的安全存储问题,并且实现多方数据的安全交换,助其突破数据孤岛,共同建模,联合发挥数据的最大价值。

一、项目简介

PaddleDTX的计算层是由计算需求节点(Requester)、任务执行节点(Executor)以及数据持有节点(DataOwner)共同组建的网络。训练样本和预测数据集存储于由数据持有节点和存储节点(Storage)共同组建的去中心化存储网络。底层的区块链网络支撑计算层和去中心化存储网络。

1.1 多方安全计算网络

有预测需求的一方为计算需求节点。可获取样本数据进行模型训练和预测的一方为任务执行节点,多个任务执行节点组成一个SMPC(多方安全计算)网络。计算需求节点将任务发布到区块链网络,任务执行节点确认后执行任务。任务执行节点通过数据持有节点获取样本数据,同时,后者对数据做信任背书。

SMPC是一个支持多个学习过程并行运行的框架,会陆续集成更多纵向联邦学习、横向联邦学习算法。

1.2 去中心化存储网络

数据持有节点将自己的隐私数据进行加密、切分、副本复制后分发到存储节点,存储节点通过应答数据持有节点的挑战证明自己持有数据分片。通过这些机制,实现了在不泄漏隐私的前提下充分且安全地利用存储资源。更多原理和实现请参见 XuperDB

1.3 区块链网络

训练任务和预测任务通过区块链网络广播到任务执行节点,后者继而执行训练任务和预测任务。数据持有节点和存储节点在副本保持证明、健康状态监控过程中,通过区块链网络实现信息交换。

目前,支持的底链技术为XuperChain。

二、纵向联邦学习

PaddleDTX 开源部分目前支持两方的纵向联邦学习算法,包括多元线性回归和多元逻辑回归。算法具体原理和实现参见 crypto/ml,未来将支持更丰富的两方纵向联邦学习算法、多方的纵向联邦学习和横向联邦学习算法。

纵向联邦训练和预测步骤如下:

2.1 数据准备

计算任务会指定参与方的样本数据,数据存在去中心化存储系统(XuperDB)中。任务启动前,计算方(即数据持有方)需要从XuperDB获取自己的样本数据。

2.2 样本对齐

纵向的模型训练或预测任务,都需要对数据进行样本对齐,即:根据各自样本ID找到多个参与方的样本交集,用交集样本进行训练或预测。

项目采用了PSI(隐私求交)技术,可以在不泄露各方样本ID的前提下,实现样本求交的功能。PSI算法原理和实现详见 crypto/psi

2.3 训练过程

模型训练是多次迭代和交互的过程,依赖于两方数据的协同计算,需要双方不断传递中间参数来计算出各自的模型。

为保护样本数据的隐私,迭代过程的模型中间参数采用Paillier同态算法进行加密,Paillier支持密文加法和数乘操作。Paillier算法原理和实现详见 crypto/paillier

2.4 预测过程

预测任务需要指定模型,因此在预测任务启动前,指定的模型训练任务必须已经成功完成。模型分别存储在训练双方的本地,在预测时分别利用各自的模型进行计算,并汇总得到最终结果。

对于线性回归算法,预测结果汇总后需要进行逆标准化操作,这个操作只有拥有标签的那一方才能完成,因此需要将预测结果汇总到标签方,由标签方计算最终的预测结果,并将结果以文件的形式存到XuperDB中,供需求方获取。

三、安装

我们提供两种方式安装PaddleDTX,您可以根据自己的实际情况进行选择:

3.1 通过Docker安装

强烈建议您通过docker安装PaddleDTX。
您可以参考 PaddleDTX镜像制作脚本XuperDB镜像制作脚本 制作docker镜像,也可以使用我们提供的镜像构建系统,请参考 docker-compose部署PaddleDTX

3.2 源码安装

编译依赖

  • go 1.13.x 及以上

    # In dai directory
    make
    
    # In xdb directory 
    make
    

您可以在./output中获取安装包,然后手动安装。

四、测试

我们提供了 测试脚本方便您测试、了解和使用。(此脚本需要docker环境)

五、在AIStudio项目中部署链桨PaddleDTX实践

使用docker可以快速了解和PaddleDTX学习,不过如果想在AIStudio项目中学习怎么办呢?实际上PaddleDTX的非docker部署相对比较繁琐,好消息就是:本项目宗旨就是为大家提供notebook的链桨部署实践全流程!

AIStudio项目中,可以单步执行,方便大家更细化的学习和了解链桨!

PaddleDTX源码编译和安装

环境准备

PaddleDTX 使用 golang 进行开发,当您使用源码进行编译和安装时,首先需要准备源码以及编译的环境:

系统环境, 推荐使用Linux或MacOS操作系统

  • golang编译器, 推荐版本1.13+ 点击下载安装golang
  • git源码下载工具 BML项目内自带。
  • make编译工具 BML项目内自带。

下载go程序、解压,并设置环境变量

# 下载并解压go程序
# !wget -nc https://studygolang.com/dl/golang/go1.16.13.linux-amd64.tar.gz  && tar -xzvf go1.16.13.linux-amd64.tar.gz
!wget -nc https://studygolang.com/dl/golang/go1.17.6.linux-amd64.tar.gz && tar -xzvf go1.17.6.linux-amd64.tar.gz
# 配置go编译器环境变量,并把PaddleTDX的相关路径也加上。
import os
import time
os.environ['PATH'] = os.environ['PATH'] + ":/home/aistudio/go/bin" + ":/home/aistudio/PaddleDTX/xdb/output" + ":/home/aistudio/PaddleDTX/dai/output"

# 设置go下载镜像以便编译的时候下载速度加速(新版本PaddleDTX自带加速,不需要设置),并看看go的版本
!go env -w GOPROXY=https://goproxy.cn,direct
!go version

go version go1.17.6 linux/amd64
# 系统里有make,不用安装,版本为4.1
!make --version

下载PaddleDTX源代码并编译

下载PaddleDTX源代码

# 根据网络选择最快的下载源.
!git clone https://github.com/PaddlePaddle/PaddleDTX
# !git clone https://hub.fastgit.org/PaddlePaddle/PaddleDTX

源码编译XuperDB

编译链桨的超级链数据库系统。

# 编译XuperDB cpu版161秒,高端版83秒,至尊版40秒。
!cd ~/PaddleDTX/xdb && make 

编译产出为 output 文件夹,内容为:

├── conf
│   ├── config-dataowner.toml
│   └── config-storage.toml
├── xdb                   //数据存储服务启动二进制,根据配置文件的不同有数据持有节点或存储节点两种类型
└── xdb-cli               //数据存储服务操作客户端

老版本对应的文件为(不用管,只是踩过的坑留念):
├── xdata                   //数据存储服务启动二进制,根据配置文件的不同有数据持有节点或存储节点两种类型
└── xdata-cli               //数据存储服务操作客户端

编译Distributed AI

这是PaddleDTX的计算节点和计算的相关部分。

# 编译Distributed AI cpu版38秒,高端版21秒,至尊版12秒。
!cd ~/PaddleDTX/dai && make 

编译产出为 output 文件夹,内容为:


├── conf
│   ├── config-cli.toml     //客户端配置,也可以使用config.toml作为客户端配置
│   └── config.toml         //服务配置
├── executor                //DAI任务执行节点服务启动二进制
├── executor-cli            //DAI任务执行节点操作客户端
└── requester-cli           //计算需求节点操作客户端

编译区块链合约

编译产出为 paddlempc 合约文件,为安装在xchain 区块链上的合约文件。文件位于~/PaddleDTX/dai目录,后面要用。

后来一度编译失败,可能是网络的问题,所以就将编译好的合约文件放置在~/work目录下备用。若自己编译,则后面用面部分安装合约的时候,路径要相应改变。

# 编译区域链合约
# !cd ~/PaddleDTX/dai &&  go build -o paddlempc ./blockchain/xchain/contract

网络部署

部署区块链网络

PaddleDTX 使用区块链网络支撑计算层和去中心化存储网络,底层依赖可以使用同一个区块链网络。
这里我们使用的百度超级链 xchain 作为底层区块链网络,可参考 XuperChain环境部署 来搭建区块链网络。
您需要了解如何创建合约账户、部署智能合约,详细参考 部署 native 合约 ,更多内容请参考XuperChain官方文档
合约安装过程如下,在BML项目环境中,有些语句需要适当修改:

# 定义合约账户和合约名称
$ export contractAccount='1234567890123456'
$ export contractName='paddlempc'

# 创建区块链账户, 并转 token
$ ./xchain-cli account newkeys --strength 1 -o ukeys
$ export address=`cat ./ukeys/address`
$ ./xchain-cli transfer --to $address --amount 1000000000000

# 创建区块链合约账户, 并转 token
$ ./xchain-cli account new --account $contractAccount --fee 1000 --keys ./ukeys

# 给合约账户转 token
$ ./xchain-cli transfer --to XC${contractAccount}@xuper --amount 100000000000 --keys ./ukeys

# 安装合约
$ ./xchain-cli native deploy --account XC${contractAccount}@xuper --runtime go -a '{"creator":"XC${contractAccount}@xuper"}' --cname $contractName ./$contractName --fee 19267894 --keys ./ukeys

# 查询合约安装的状态
$ ./xchain-cli contract query $contractName

哦,有一点很重要时的事情:安装合约前,首先要编译安装超级链XuperChain并启动!

编译超级链XuperChain

# 选择最快的网络下载XuperChain源代码,有时候会碰到网络很慢的情况,加油,你可以的!
%cd ~/
!git clone https://github.com/xuperchain/xuperchain
# !git clone https://hub.fastgit.org/xuperchain/xuperchain
# !wget -nc https://hub.fastgit.org/xuperchain/xuperchain/archive/refs/heads/master.zip && unzip  master.zip && mv xuperchain-master xuperchain
# !wget -nc https://github.com/xuperchain/xuperchain/archive/refs/heads/master.zip && unzip master.zip && mv xuperchain-master xuperchain

# 编译xuperchain,在output目录得到产出xchain和xchain-cli make耗时cpu188秒,gpu版68秒
!cd ~/xuperchain/ && make

编译显示:

......
go: downloading github.com/fxamacker/cbor/v2 v2.2.0
go: downloading github.com/x448/float16 v0.8.4
go build -o /home/aistudio/xuperchain/output/bin/xchain-cli -ldflags "-X main.Version=master -X main.BuildTime=2021-12-25-09:28:06 -X main.CommitID=bd852b5" /home/aistudio/xuperchain/cmd/client/main.go
compile done!

启动超级链xuperchain

后台启动,这里直接运行启动就行了。后面可以用netstat -an 来观察端口情况。

# 启动单点超级链。

# 先杀死超级链进程,以便每次都初始化,方便调试,提高程序运行成功率
!ps -aux |grep xchain |awk '{print $2}'| xargs kill -9
# 启动
!cd ~/xuperchain/output/ && bash control.sh start 
import time
time.sleep(6)
/home/aistudio/xuperchain/output/bin/xchain
/home/aistudio/xuperchain/output/conf/env.yaml
2022/01/10 10:51:21 start create chain.bc_name:xuper genesis_conf:./data/genesis/xuper.json env_conf:./conf/env.yaml
2022/01/10 10:51:21 create ledger succ.bc_name:xuper
start xchain. cmd:nohup /home/aistudio/xuperchain/output/bin/xchain startup --conf /home/aistudio/xuperchain/output/conf/env.yaml >/home/aistudio/xuperchain/output/logs/nohup.out 2>&1 &
.start proc succ.
start finish.pid:25262
Done!
# 看看服务是否正常启动,37101端口是否监听
time.sleep(4)
!netstat -an |grep 37101
tcp        0      0 127.0.0.1:60394         127.0.0.1:37101         ESTABLISHED
tcp        0      0 127.0.0.1:60392         127.0.0.1:37101         ESTABLISHED
tcp6       0      0 :::37101                :::*                    LISTEN     
tcp6       0      0 127.0.0.1:37101         127.0.0.1:60392         ESTABLISHED
tcp6       0      0 127.0.0.1:37101         127.0.0.1:60394         ESTABLISHED
# 确认超级链服务状态
!cd ~/xuperchain/output/ && ./bin/xchain-cli status
# !cd ~/xuperchain/output && ./bin/xchain-cli status -H 127.0.0.1:37101

创建部署智能合约

发现notebook下无法设置复合变量,如下面所示,前两种设置方法都只会设置出命令字符串,而无法得到命令字符串的输出字符串。因此对该命令进行了修改,使其能在notebook下正常赋值。如下所示前两句赋值均无法得到设想的address字符串。

env: address=!cat ~/xuperchain/output/ukeys/address
env: address1='cat ~/xuperchain/output/ukeys/address'
!cat ~/xuperchain/output/ukeys/address 'cat ~/xuperchain/output/ukeys/address'
RG9oMvUrF6VEyxARQoDGZoUT1CkEwYFci

下面的~/xuperchain/output/ukeys/address文件内容为区块链账户助记词,在后面的配置中需要使用该助记词,后面生成部署文件部分可以自动将其写入配置文件中。

# 定义合约账户和合约名称
%env  contractAccount=1234567890123456
%env  contractName=paddlempc

# 创建区块链账户, 并转 token
!cd ~/xuperchain/output/ && ./bin/xchain-cli account newkeys --strength 1 -o ukeys

address=!cat ~/xuperchain/output/ukeys/address
address = address[0]
!echo $address
!cat ~/xuperchain/output/ukeys/mnemonic
# 转 token,这里需要提前打开xuper超级链服务进程!
!cd ~/xuperchain/output && ./bin/xchain-cli transfer --to $address --amount 1000000000000

# 创建区块链合约账户, 并转 token
!cd ~/xuperchain/output && ./bin/xchain-cli account new --account $contractAccount --fee 1000 --keys ukeys
# 给合约账户转 token
!cd ~/xuperchain/output && ./bin/xchain-cli transfer --to XC${contractAccount}@xuper --amount 100000000000 --keys ukeys

# 安装合约
# !cd ~/xuperchain/output && ./bin/xchain-cli native deploy --account XC${contractAccount}@xuper --runtime go -a '{"creator":"XC${contractAccount}@xuper"}' --cname $contractName ~/PaddleDTX/dai/$contractName --fee 19267894 --keys ~/PaddleDTX/testdatatmp/blockchain/user
!cd ~/xuperchain/output && ./bin/xchain-cli native deploy --account XC${contractAccount}@xuper --runtime go -a '{"creator":"XC${contractAccount}@xuper"}' --cname $contractName ~/work/$contractName --fee 19267894 --keys ukeys

# 查询合约安装的状态
!cd ~/xuperchain/output && ./bin/xchain-cli contract query $contractName

生成部署配置文件

部署采用双执行节点,双数据持有节点,双数据存储节点拓扑构架。因为源代码中的部署文件是对应docker构架的,本项目对其进行了一些修改,主要是针对单机部署,将不能的节点部署到单机的不同端口。

将下面的代码放入~/PaddleDTX/scripts/testdemo.sh文件中,在~/PaddleDTX/scripts/目录执行,即可自动生成单机部署文件。

!cd ~/PaddleDTX && tar -xzvf ~/data/data124604/testdatatmp.tar.gz
%%writefile ~/PaddleDTX/scripts/testdemo.sh
#!/bin/bash

# 脚本启动生成的临时文件目录
TMP_CONF_PATH="testdatatmp"

# PaddleDTX contract name
# PaddleDTX服务启动需要安装的智能合约名称
CONTRACT_NAME=paddlempc
CONTRACT_ACCOUNT=1234567890123456
# User's blockchain account address, used invoke contract 
# 用户安装合约所使用的区块链账户地址
# ADDRESS_PATH=../$TMP_CONF_PATH/blockchain/user
ADDRESS_PATH=~/xuperchain/output/ukeys

TRANSFER_AMOUNT=110009887797
# Executor1 private key, same as paddledtx_test.sh's EXECUTOR1_PRIVATEKEY
# 任务执行节点1私钥,同paddledtx_test.sh的EXECUTOR1_PRIVATEKEY
EXECUTOR1_PRIVATEKEY=14a54c188d0071bc1b161a50fe7eacb74dcd016993bb7ad0d5449f72a8780e21
# Executor2 private key, same as paddledtx_test.sh's EXECUTOR2_PRIVATEKEY
# 任务执行节点2私钥,同paddledtx_test.sh的EXECUTOR2_PRIVATEKEY
EXECUTOR2_PRIVATEKEY=858843291fe4ed4bd2afc1120efd7315f3cae2d3f79e582f7df843ac6eb0543b
# The namespace of the sample files and prediction files store, same as paddledtx_test.sh's NAMESPACE
# 样本文件存储的命名空间,同paddledtx_test.sh的NAMESPACE
NAMESPACE=paddlempc

function standardizeConf() {
  # rm -rf ../$TMP_CONF_PATH && mkdir ../$TMP_CONF_PATH && cp -r ~/work/testdatatmp/* ../$TMP_CONF_PATH/
  # Generate standard config.toml file
  # 生成标准配置文件
  sampleConfigFiles=`find $(dirname ${PWD})/$TMP_CONF_PATH -name "config.toml.sample"`
  MNEMONIC=`cat $ADDRESS_PATH/mnemonic`
  for file in $sampleConfigFiles
  do
    conf=${file%.sample}
    eval "cat <<EOF
$(< $file)
EOF
"  > $conf
  done
}

standardizeConf
Overwriting /home/aistudio/PaddleDTX/scripts/testdemo.sh
!cd PaddleDTX/scripts/ && bash testdemo.sh

部署 XuperDB

每一个 XuperDB 的节点都有一对公私钥,用来标识节点的账户,公私钥可以通过如下XuperDB的客户端命令进行获取:

$ ./xdata-cli nodes genkey

这是手册中用到的公私钥

# Requester private key 
# 计算需求方私钥
REQUESTERKEY="40816c779f624a8fbc4e37be1ef8bbddc6c07b5f91e704953a599f9080458f60"
# Requester public key 
# 计算需求方公钥
REQUESTER_PUBLICKEY="6cb69efc0439032b0d0f52bae1c9aada3f8fb46a5f24fa99065910055b77a1174d4afbac3c0529c8927587bb0e2ad90a85eaa600cfddd6b99f1212112135ef2b"
# Executor1 private key, same as network_up.sh's EXECUTOR1_PRIVATEKEY
# 任务执行节点1私钥,同network_up.sh的EXECUTOR1_PRIVATEKEY
EXECUTOR1_PRIVATEKEY="14a54c188d0071bc1b161a50fe7eacb74dcd016993bb7ad0d5449f72a8780e21"
EXECUTOR1_PUBLICKEY="4637ef79f14b036ced59b76408b0d88453ac9e5baa523a86890aa547eac3e3a0f4a3c005178f021c1b060d916f42082c18e1d57505cdaaeef106729e6442f4e5"
# Executor2 private key, same as network_up.sh's EXECUTOR2_PRIVATEKEY
# 任务执行节点2私钥,同network_up.sh的EXECUTOR2_PRIVATEKEY
EXECUTOR2_PRIVATEKEY="858843291fe4ed4bd2afc1120efd7315f3cae2d3f79e582f7df843ac6eb0543b"
EXECUTOR2_PUBLICKEY="e4530d81ccddc478978070e8f9fcc9f101dfc3b5c3ca1519c522c5e9698f394a35aab9145f242765185689a64b7338e9929c6a32e09050ff15645bb121ce1754"

# 手工生成公私钥对
# !cd PaddleDTX/xdb/output/ && ./xdb-cli nodes genkey

请妥善保存您创建的公私钥对,在后续的配置及命令行使用时您将会频繁的用到它;如果您是第一次搭建网络的话,建议使用默认配置文件中的公私钥。

XuperDB 包含两种类型的节点服务,数据持有节点和存储节点,我们需要分别启动这两种服务。

启动服务:

# 打开数据节点服务
# import os
# import time
# os.environ['PATH'] = os.environ['PATH'] + ":/home/aistudio/PaddleDTX/xdb/output"


import os
%cd ~/PaddleDTX/testdatatmp/xdb
# 启动xdb持有节点
os.system("nohup xdb -c data1/conf/config.toml > dataowner1.log &") # 8121
time.sleep(3)
os.system("nohup xdb -c data2/conf/config.toml > dataowner2.log &") # 8122
time.sleep(3)
# 启动数据存储节点1
os.system("nohup xdb -c storage1/conf/config.toml > datastorage1.log &") # 8131
time.sleep(3)
# 启动数据存储节点2
os.system("nohup xdb -c storage2/conf/config.toml > datastorage2.log &") # 8132
time.sleep(3)
# 启动数据持有节点3
os.system("nohup xdb -c storage3/conf/config.toml > datastorage3.log &") # 8133
time.sleep(3)

%cd ~/
# 看看8121 8122 8131 8132四个端口是否启动
time.sleep(2)
!netstat -an |grep 81
tcp        0      0 172.22.68.114:8888      172.16.2.134:48164      TIME_WAIT  
tcp6       0      0 :::8121                 :::*                    LISTEN     
tcp6       0      0 :::8122                 :::*                    LISTEN     
tcp6       0      0 :::8131                 :::*                    LISTEN     
tcp6       0      0 :::8132                 :::*                    LISTEN     
tcp6       0      0 :::8133                 :::*                    LISTEN     
unix  2      [ ACC ]     流        LISTENING     2656477781 /tmp/pymp-th3v3_ss/listener-mhu1btl4
unix  3      [ ]         流        已连接     2656666181 
# 如果启动失败,可以看下log日志信息纠错
!cat ~/PaddleDTX/testdatatmp/xdb/datastorage1.log
Now listening on: http://localhost:8131
Application started. Press CTRL+C to shut down.

这步是调通是花费时间最多的。总结起来就是要按照手册填写,需要把私钥和助记词都改成相对应的。整个系统一共用了5套公私密钥对,一套助记词,对新手来说,光看手册几乎是无法完成正确的配置的。

后来参考docker demo例子里的代码,采用这样的网络拓扑:2个执行节点,2个数据持有节点,2个数据存储节点。对比例子里的代码,终于把密钥对和助记词弄明白,并可以在notebook中一键部署。

注意:一般构建 PaddleDTX 网络至少需要两方参与,即两个数据持有节点

查看服务状态

使用 xdb-cli 客户端执行如下命令,请求数据持有节点查看存储节点的在线状态:

!cd PaddleDTX/xdb/output/ && ./xdb-cli nodes list --host http://127.0.0.1:8122

部署Distributed AI

一般多方安全计算至少由两个任务执行节点,所以这里部署两个任务执行节点。

注意: 任务执行节点的账户也是通过公私钥对来标明, 通常我们一个任务执行节点对应了一个数据持有节点, 这种情况下任务执行节点和对应的数据持有节点需要使用相同的公私钥对。

启动执行节点

分别在对应文件夹下执行如下命令,启动任务执行节点:

$ nohup ./executor &

# import os
# os.environ['PATH'] = os.environ['PATH'] + ":/home/aistudio/PaddleDTX/dai/output"

%cd ~/PaddleDTX/testdatatmp/executor/node1/
# 启动任务执行节点1
os.system("nohup executor &")
time.sleep(2)
%cd ~/PaddleDTX/testdatatmp/executor/node2/
# 启动任务执行节点2
os.system("nohup executor &")
time.sleep(2)
%cd ~/
# 看看8181和8182两个端口起来了不。
!netstat -an |grep 818
tcp6       0      0 :::8181                 :::*                    LISTEN     
tcp6       0      0 :::8182                 :::*                    LISTEN     
# 看看两个进程起来了不?
!ps -aux | grep executor
aistudio 25657  3.2  0.0 1244288 25592 ?       Sl   10:52   0:00 executor
aistudio 25675  5.5  0.0 1162360 24804 ?       Sl   10:52   0:00 executor
aistudio 25692  0.0  0.0  13192  3248 pts/0    Ss+  10:52   0:00 /bin/bash -c ps -aux | grep executor
aistudio 25694  0.0  0.0  14720   956 pts/0    S+   10:52   0:00 grep executor

链桨纵向联邦学习训练-前期准备

以波士顿房价为例进行链桨纵向联邦学习训练。

操作XuperDB

创建命名空间

使用 XuperDB 的第一步是在每一个数据持有节点创建文件存储的命名空间,使用如下命令:
./xdb-cli files addns --host http://127.0.0.1:8122 -k $prikey2 -n paddlempc -r 2
为了简化操作,使命令更加清爽,直接在python里面定义了公私钥的变量,在shell命令中调用。

# 公私密钥对,数据持有节点1和执行节点1使用。
prikey1 = "14a54c188d0071bc1b161a50fe7eacb74dcd016993bb7ad0d5449f72a8780e21"
pubkey1 = "4637ef79f14b036ced59b76408b0d88453ac9e5baa523a86890aa547eac3e3a0f4a3c005178f021c1b060d916f42082c18e1d57505cdaaeef106729e6442f4e5"
# 公私密钥对,数据持有节点2和执行节点2使用。
prikey2 = "858843291fe4ed4bd2afc1120efd7315f3cae2d3f79e582f7df843ac6eb0543b"
pubkey2 = "e4530d81ccddc478978070e8f9fcc9f101dfc3b5c3ca1519c522c5e9698f394a35aab9145f242765185689a64b7338e9929c6a32e09050ff15645bb121ce1754"
# 公私密钥对,数据存储节点1使用
prikey3 = "b7ba7d04fe47a308f3730f3cf14cb2719f14b700b1bbf9f50889541bd79249cb"
pubkey3 = "1d9b71a6f3c978deb45a0bf4f53478d190333c610d86b6ebd5bb0438c8e62a636226c53de462dddd3279f1d936fe814bb066b4353608f3c2ac8a5047e117fb6b"
# 公私密钥对,数据存储节点2使用
prikey4 = "69d69ea9596ea930ce36ca22d3a7919186d1a7e380e379035b7eb0259ff9e72e"
pubkey4 = "12489bd965d1b6dddff8c7bf7b20e54802c70bfba998573843b7e443de07698eeb37b4c88c06898929e5e67ecd2a46ae19b15d2d1c410e9020ec97694c86c61b"

# Requester private key 
# 计算需求方私钥
REQUESTERKEY="40816c779f624a8fbc4e37be1ef8bbddc6c07b5f91e704953a599f9080458f60"
# Requester public key 
# 计算需求方公钥
REQUESTER_PUBLICKEY="6cb69efc0439032b0d0f52bae1c9aada3f8fb46a5f24fa99065910055b77a1174d4afbac3c0529c8927587bb0e2ad90a85eaa600cfddd6b99f1212112135ef2b"

# 创建命名空间
# !cd ~/PaddleDTX/xdb/output &&  ./xdb-cli files addns  --host http://127.0.0.1:8123 -k eae7344064e1d5b53af6da1a23407b1e7e265d15eaf0442c476e3caac3003406 -n paddlempc  -n paddlempc -r 1
!cd ~/PaddleDTX/xdb/output &&  ./xdb-cli files addns  --host http://127.0.0.1:8121 -k $prikey1 -n paddlempc -r 2
!cd ~/PaddleDTX/xdb/output &&  ./xdb-cli files addns  --host http://127.0.0.1:8122 -k $prikey2 -n paddlempc -r 2

OK


2022/01/10 10:52:05 contract response: [{"ID":"NTVjY2Y0NTA2NzA0ZTRkYTllNTlhMWE5NWJkOWRmOGNiYTM0OWJhZmUzYzdmNGIxNWQxZjg1ODE0NTdkNGM5OTU0YWMwOGVmODllMDI0NjVjYTU4N2NiMGNkMzBkYmEzODVjNDg4MzA1YTVhMGJlNWMxMmViM2JjYzJjOTE0YzQ=","Name":"storage-node3","Address":"127.0.0.1:8133","Online":true,"RegTime":1641783115442346536,"UpdateAt":1641783115442346536},{"ID":"YzdkMjk5YzkyNTA5MDM2ZGRiNTNhNzZhOWI2ZmRmYWJhMzdhYjRiMTk5MDI1MDZmMGQ3ZDkxNTBjYzUwZDNlZGM1ZjcxMzc0Y2UzNWFiOTU1NDliNmQ0YmY2ZGIxYzQ0ZDU4ZWFhMDI2MjRiZTIwOWU4ZmZjMDZlZTc3ZDlmNTI=","Name":"storage-node2","Address":"127.0.0.1:8132","Online":true,"RegTime":1641783112418522665,"UpdateAt":1641783112418522665},{"ID":"OTY4ZDA2ZjEzNzg5YmE3NWUyMDg2OTYwNGI4ZTI1YWRmNDk2NDljMGM3MjY4NjY3YzlmZjFlYTk3NjBjYTJiMzQwMjk2MjYwYjRiMjU4NmM0Njc1MDYzOGYwYmI5ZTM0YmE2NGUyODM1YzFkZDdlNTQwNzFkYjU0MzUyOWVkNzE=","Name":"storage-node1","Address":"127.0.0.1:8131","Online":true,"RegTime":1641783109407162681,"UpdateAt":1641783109407162681}]
2022/01/10 10:52:05 Gas will cost: 1
2022/01/10 10:52:05 Gas will cost: 824
2022/01/10 10:52:05 contract response: OK


OK


2022/01/10 10:52:06 contract response: [{"ID":"NTVjY2Y0NTA2NzA0ZTRkYTllNTlhMWE5NWJkOWRmOGNiYTM0OWJhZmUzYzdmNGIxNWQxZjg1ODE0NTdkNGM5OTU0YWMwOGVmODllMDI0NjVjYTU4N2NiMGNkMzBkYmEzODVjNDg4MzA1YTVhMGJlNWMxMmViM2JjYzJjOTE0YzQ=","Name":"storage-node3","Address":"127.0.0.1:8133","Online":true,"RegTime":1641783115442346536,"UpdateAt":1641783115442346536},{"ID":"YzdkMjk5YzkyNTA5MDM2ZGRiNTNhNzZhOWI2ZmRmYWJhMzdhYjRiMTk5MDI1MDZmMGQ3ZDkxNTBjYzUwZDNlZGM1ZjcxMzc0Y2UzNWFiOTU1NDliNmQ0YmY2ZGIxYzQ0ZDU4ZWFhMDI2MjRiZTIwOWU4ZmZjMDZlZTc3ZDlmNTI=","Name":"storage-node2","Address":"127.0.0.1:8132","Online":true,"RegTime":1641783112418522665,"UpdateAt":1641783112418522665},{"ID":"OTY4ZDA2ZjEzNzg5YmE3NWUyMDg2OTYwNGI4ZTI1YWRmNDk2NDljMGM3MjY4NjY3YzlmZjFlYTk3NjBjYTJiMzQwMjk2MjYwYjRiMjU4NmM0Njc1MDYzOGYwYmI5ZTM0YmE2NGUyODM1YzFkZDdlNTQwNzFkYjU0MzUyOWVkNzE=","Name":"storage-node1","Address":"127.0.0.1:8131","Online":true,"RegTime":1641783109407162681,"UpdateAt":1641783109407162681}]
2022/01/10 10:52:06 Gas will cost: 1
2022/01/10 10:52:06 Gas will cost: 824
2022/01/10 10:52:06 contract response: OK

可以通过替换 host 来实现请求不同的数据持有节点;-k 参数为对应数据持有节点的私钥,不同的数据持有节点有不同私钥,可以通过对应的配置 config.toml 来获取;-n 参数为命名空间的名称,这里命名空间会被配置到任务执行节点中,所以需要创建任务执行节点中使用的命名空间;-r 参数为副本数,一般取大于 1 的数,这里取2 。

使用 listns 命令可以查看已有的命名空间:

!xdb-cli files listns  --host http://127.0.0.1:8121 -o $pubkey1
!xdb-cli files listns  --host http://127.0.0.1:8122 -o $pubkey2
Name: paddlempc
FileTotalNum: 0
Replica: 2
NsDescription: 
UpdateTime: 2022-01-10 10:52:05
CreateTime: 2022-01-10 10:52:05



2022/01/10 10:52:06 contract response: [{"Name":"paddlempc","Description":"","Owner":"RjfvefFLA2ztWbdkCLDYhFOsnluqUjqGiQqlR+rD46D0o8AFF48CHBsGDZFvQggsGOHVdQXNqu7xBnKeZEL05Q==","Replica":2,"FilesStructSize":0,"FileTotalNum":0,"CreateTime":1641783125776072104,"UpdateTime":1641783125776072104}]
2022/01/10 10:52:06 Gas will cost: 1



no ns, please add first



2022/01/10 10:52:06 contract response: null
2022/01/10 10:52:06 Gas will cost: 1

-o 参数为数据持有节点的公钥

上传训练数据

根据网络拓扑和纵向联邦学习规划,训练数据被分成两份,每份携带一部分数据,被分别上传到两个数据持有节点。

训练数据划分模式采用纵向分割的方法,即将一份数据id,CRIM,ZN,INDUS,CHAS,NOX,RM,AGE,DIS,RAD,TAX,PTRATIO,B,LSTAT,MEDV拆分成id,CRIM,ZN,INDUS,CHAS,NOX,RMid,AGE,DIS,RAD,TAX,PTRATIO,B,LSTAT,MEDV两份,这样单独任何一份都没有完整的数据,只有通过同一id将数据组合在一起,才是完整的数据。

因为后面还要用到FileID变量,所以这里将返回信息赋值给tmp临时变量,并使用切片的方式取值。

# 上传第一部分文件到8121。输出的FileID需要记录在train_fileid_1变量,在后面查询和训练时需要使用。
tmp = !xdb-cli --host http://127.0.0.1:8121 files upload \
-k 14a54c188d0071bc1b161a50fe7eacb74dcd016993bb7ad0d5449f72a8780e21 -n paddlempc \
-m train_dataA.csv -i ~/PaddleDTX/dai/mpc/testdata/vl/linear_boston_housing/train_dataA.csv \
--ext '{"FileType":"csv","Features":"id,CRIM,ZN,INDUS,CHAS,NOX,RM", "TotalRows":457}' \
-e '2022-12-10 12:00:00' -d LINEAR_TRAIN_SAMPLE_FILE_DES
train_fileid_1 = tmp[0].split()[1]
print(train_fileid_1)
# 上传第二部分文件到8122。输出的FileID记录在train_fileid_2变量,在后面查询和训练时需要使用。
tmp = !xdb-cli --host http://127.0.0.1:8122 files upload \
-k 858843291fe4ed4bd2afc1120efd7315f3cae2d3f79e582f7df843ac6eb0543b -n paddlempc \
-m train_dataB.csv -i ~/PaddleDTX/dai/mpc/testdata/vl/linear_boston_housing/train_dataB.csv \
--ext '{"FileType":"csv","Features":"id,AGE,DIS,RAD,TAX,PTRATIO,B,LSTAT,MEDV", "TotalRows":457}' \
-e '2022-12-10 12:00:00' -d LINEAR_TRAIN_SAMPLE_FILE_DES
train_fileid_2 = tmp[0].split()[1]
print(train_fileid_2)

通过修改 host 来指定不同的数据持有节点;-k 参数为数据持有节点使用的私钥;-n 为命名空间的名称;-m 为文件名称;-i 指定了上传的文件;–ext指定了样本或者预测文件中的标签;-e 为文件在 XuperDB 中的过期时间;-d 为文件描述。

上传文件后,可以使用getbyid命令进行文件的查询:

!xdb-cli files getbyid  -i $train_fileid_1 --host http://127.0.0.1:8121
# !xdb-cli files getbyid  -i 233d0382-9923-4abc-9938-5d3e1c001fc7 --host http://127.0.0.1:8121



# 拼合两个FileID到一起,以便后面训练时调用
# train_fileid = "233d0382-9923-4abc-9938-5d3e1c001fc7,06146e03-12eb-4fb4-869f-f74eda0a0d11"
# print(train_fileid)
train_fileid = train_fileid_1 + "," + train_fileid_2
print(train_fileid)
050d418f-849a-417f-b5b1-ea9d86bcdecd,ee8ac30a-6f9a-4845-875e-efefcf93ec87

链桨纵向联邦学习训练

开始训练

链桨的训练过程要比普通训练复杂一些。普通训练只需要发布一次训练指令即可。而在链桨中,因为是多节点执行,整个训练需要如下几步:

  • 计算需求方发起训练任务
  • 每个任务执行节点都需要确认训练任务
  • 所有的任务执行节点对任务进行确认后,计算需求方触发启动命令
# 训练任务由计算需求方发起:
tmp = !requester-cli task publish -a "linear-vl" -l "MEDV" \
-k $REQUESTERKEY -t "train" \
-n "房价预测-训练任务v1" -d "用飞桨,划时代" -p "id,id" \
--conf ~/PaddleDTX/testdatatmp/executor/node1/conf/config.toml \
-f $train_fileid
taskid = tmp[0].split()[1]
print(taskid)
time.sleep(1)
1cbd82b2-22f9-4e60-b7a8-bb7a4fe1c214
# 启动命令执行后,查看节点状态,状态会呈现两种:TaskStatus: ToProcess TaskStatus: Processing,最终会TaskStatus: Finished
!requester-cli task list --conf ~/PaddleDTX/testdatatmp/executor/node1/conf/config.toml  \
-p $pubkey1
TaskID: 1cbd82b2-22f9-4e60-b7a8-bb7a4fe1c214
TaskType: LEARN
TaskName: 房价预测-训练任务v1
Description: 用飞桨,划时代
TaskStatus: Confirming
PublishTime: 2022-01-10 10:52:07

taskNum : 1
# 确认训练任务节点1

# 计算需求方发布任务之后,需要各个任务执行节点进行确认,确认时通过 executor-cli 客户端进行操作。
!executor-cli task confirm  --id  $taskid --host 127.0.0.1:8181 \
-k $prikey1
time.sleep(1)

# 确认训练任务节点2
!executor-cli task confirm  --id  $taskid --host 127.0.0.1:8182 \
-k $prikey2

time.sleep(1)
ok


2022/01/10 10:52:09 Gas will cost: 879
2022/01/10 10:52:09 contract response: OK


ok


2022/01/10 10:52:10 Gas will cost: 908
2022/01/10 10:52:10 contract response: OK
2022/01/10 10:52:11 contract response: null
2022/01/10 10:52:11 Gas will cost: 1
# 启动训练任务,只要发一个启动命令即可。

# 当所有的任务执行节点对任务进行确认后,需要计算需求方触发启动命令的执行,训练任务的执行结果是产出一个预测模型。
!requester-cli task start --id $taskid \
-k $REQUESTERKEY \
--conf ~/PaddleDTX/testdatatmp/executor/node1/conf/config.toml
time.sleep(1)
ok
# 启动命令执行后,查看节点状态,状态会呈现两种:TaskStatus: ToProcess TaskStatus: Processing,最终会TaskStatus: Finished
time.sleep(1)
!requester-cli task list --conf ~/PaddleDTX/testdatatmp/executor/node1/conf/config.toml  \
-p $pubkey1
# 查看节点任务详细情况,有问题时通过详细报错调试纠错。 
!requester-cli task getbyid -i $taskid --conf ~/PaddleDTX/testdatatmp/executor/node1/conf/config.toml 

整个训练大约需要40多秒的时间,趁链桨在后台训练,我们可以先开始预测任务的准备。

链桨纵向联邦学习预测

波士顿房价预测任务。

上传预测文件

跟训练文件一样,我们的预测文件也是由两部分组成,分别上传到数据持有节点1和节点2

# 上传第一部分文件到8121。输出的FileID需要记录在predict_fileid_1变量,在后面查询和训练时需要使用。
tmp = !xdb-cli --host http://127.0.0.1:8121 files upload \
-k 14a54c188d0071bc1b161a50fe7eacb74dcd016993bb7ad0d5449f72a8780e21 -n paddlempc \
-m predict_dataA.csv -i ~/PaddleDTX/dai/mpc/testdata/vl/linear_boston_housing/predict_dataA.csv \
--ext '{"FileType":"csv","Features":"id,CRIM,ZN,INDUS,CHAS,NOX,RM", "TotalRows":50}' \
-e '2022-12-10 12:00:00' -d LINEAR_PREDICT_SAMPLE_FILE_DES
predict_fileid_1 = tmp[0].split()[1]
print(tmp, predict_fileid_1)


# 上传第二部分文件到8122。输出的FileID需要记录在predict_fileid_2变量,在后面查询和训练时需要使用。
tmp = !xdb-cli --host http://127.0.0.1:8122 files upload \
-k 858843291fe4ed4bd2afc1120efd7315f3cae2d3f79e582f7df843ac6eb0543b -n paddlempc \
-m predict_dataB.csv -i ~/PaddleDTX/dai/mpc/testdata/vl/linear_boston_housing/predict_dataB.csv \
--ext '{"FileType":"csv","Features":"id,AGE,DIS,RAD,TAX,PTRATIO,B,LSTAT", "TotalRows":50}' \
-e '2022-12-10 12:00:00' -d LINEAR_PREDICT_SAMPLE_FILE_DES
predict_fileid_2 = tmp[0].split()[1]
print(tmp, predict_fileid_2)
# 拼合两个FileID到一起,以便后面预测时调用
predict_fileid = predict_fileid_1 + "," + predict_fileid_2
print(predict_fileid)
# predict_fileid = "a81ddead-86b2-44f7-987b-7c1163d6fede,ee9649d2-a917-4d23-80fd-5418c5d963dc"
# print(predict_fileid)
db1f3b00-8883-4761-8368-946100f3e144,f185371e-a304-4b68-9d7e-94e029df5d3f
# 等待42秒的时间,以保证前面训练任务完成。
time.sleep(46)

开始预测

跟训练时一样,需求方发起预测任务,所有的执行节点进行确认,最后需求方启动预测命令。

# 预测任务由计算需求方发起:
tmp = !requester-cli task publish -a "linear-vl" -l "MEDV" \
-k $REQUESTERKEY -t "predict" \
-n "房价预测-预测任务v1" -d "用飞桨,划时代" -p "id,id" --conf ~/PaddleDTX/testdatatmp/executor/node1/conf/config.toml \
-f $predict_fileid -i $taskid
pretaskid = tmp[0].split()[1]
print(tmp, pretaskid)
time.sleep(1)
['TaskID: 0d419944-78fd-4ebb-b924-b9d01be02860'] 0d419944-78fd-4ebb-b924-b9d01be02860
# 计算需求方发布任务之后,需要各个任务执行节点进行确认,确认时通过 executor-cli 客户端进行操作。

# 确认预测任务节点1
!executor-cli task confirm  --id  $pretaskid --host 127.0.0.1:8181 \
-k $prikey1
time.sleep(1)

# 确认训练任务节点2
!executor-cli task confirm  --id  $pretaskid --host 127.0.0.1:8182 \
-k $prikey2

time.sleep(1)
ok


2022/01/10 10:53:02 Gas will cost: 945
2022/01/10 10:53:02 contract response: OK
2022/01/10 10:53:03 contract response: null
2022/01/10 10:53:03 Gas will cost: 1


ok


2022/01/10 10:53:03 Gas will cost: 974
2022/01/10 10:53:03 contract response: OK
# 启动命令执行后,查看节点状态,状态会呈现两种:TaskStatus: ToProcess TaskStatus: Processing,最终会TaskStatus: Finished
!requester-cli task list --conf ~/PaddleDTX/testdatatmp/executor/node1/conf/config.toml  \
-p $pubkey1
TaskID: 0d419944-78fd-4ebb-b924-b9d01be02860
TaskType: PREDICT
TaskName: 房价预测-预测任务v1
Description: 用飞桨,划时代
TaskStatus: Ready
PublishTime: 2022-01-10 10:53:01

TaskID: 1cbd82b2-22f9-4e60-b7a8-bb7a4fe1c214
TaskType: LEARN
TaskName: 房价预测-训练任务v1
Description: 用飞桨,划时代
TaskStatus: Finished
PublishTime: 2022-01-10 10:52:07

taskNum : 2
# 启动训练任务,只要发一个启动命令即可。

# 当所有的任务执行节点对任务进行确认后,需要计算需求方触发启动命令的执行,训练任务的执行结果是产出一个预测模型。
!requester-cli task start --id $pretaskid \
-k $REQUESTERKEY \
--conf ~/PaddleDTX/testdatatmp/executor/node1/conf/config.toml
time.sleep(8)
# 启动命令执行后,查看节点状态,状态会呈现两种:TaskStatus: ToProcess TaskStatus: Processing,最终会TaskStatus: Finished
!requester-cli task list --conf ~/PaddleDTX/testdatatmp/executor/node1/conf/config.toml  \
-p $pubkey1
TaskID: 0d419944-78fd-4ebb-b924-b9d01be02860
TaskType: PREDICT
TaskName: 房价预测-预测任务v1
Description: 用飞桨,划时代
TaskStatus: Finished
PublishTime: 2022-01-10 10:53:01

TaskID: 1cbd82b2-22f9-4e60-b7a8-bb7a4fe1c214
TaskType: LEARN
TaskName: 房价预测-训练任务v1
Description: 用飞桨,划时代
TaskStatus: Finished
PublishTime: 2022-01-10 10:52:07

taskNum : 2

获取预测结果

预测任务执行成功后,计算需求方可以获取到预测的结果。

$ ./requester-cli task result --id a7dfac43-fa51-423e-bd05-8e0965c708a8 -k 14a54c188d0071bc1b161a50fe7eacb74dcd016993bb7ad0d5449f72a8780e21 --conf ./testdata/executor/node1/conf/config.toml -o ./output.csv

本项目中将预测的结果输出到根目录,文件名为output.csv。当然我们等了8秒来等待预测结束。

# 获取线性预测任务的预测结果
!requester-cli task result --id $pretaskid \
-k $REQUESTERKEY \
--conf ~/PaddleDTX/testdatatmp/executor/node1/conf/config.toml  -o ~/output.csv
# 看看预测输出的文件
!cat ~/output.csv

计算均方根误差

从官方代码中找到计算均方根误差部分,使用%%bash命令在cell框中执行bash指令来均方根误差。

输出======> 均方根误差Root mean square error of Boston house price prediction is: 4.568173732895245就证明整个项目成功跑通!

%%bash
function calculateRMSE() {
  sumOfSquares=0
  logisticPredictAccuracy=0
  for line in $2
  do
    IFS=',' read -r -a targetArray <<<"$line"
    targetKey=${targetArray[1]}
    targetValue=${targetArray[2]}
    if [ "$3" = "IrisPlants" ];then
      if [ "$targetValue" = "Iris-setosa" ];then
        targetValue=1
      else
        targetValue=0
      fi
    fi
    # Read the predicted value of the same sample ID
    # 读取相同样本ID的预测值
    predictValueLine=`echo "$1" | grep "^$targetKey,"`
    IFS=',' read -r -a predictArray <<<"$predictValueLine"
    predictValue=${predictArray[1]}
   
    predictError=`echo "scale=15;$targetValue-$predictValue"|bc|awk '{printf "%.15f", $0}'`
    sumOfSquare=`echo "scale=15;$predictError*$predictError"|bc|awk '{printf "%.15f", $0}'`
    sumOfSquares=`echo "scale=15;$sumOfSquares+$sumOfSquare"|bc|awk '{printf "%.15f", $0}'`
  done
  num=`echo "$2"| wc -l | awk 'BEGIN{RS="\r";ORS="";}{print $0}' | awk '$1=$1'`
  avg=`echo "scale=15;$sumOfSquares/$num"|bc|awk '{printf "%.15f", $0}'`
  rmse=`echo "scale=15;sqrt($avg)"|bc|awk '{printf "%.15f", $0}'`
  echo "======> $4: $rmse"
}

# 计算均方根误差
housePricePredictFile=`cat output.csv | awk 'NR>1'`
housePriceTargetFile=`cat ~/PaddleDTX/dai/mpc/testdata/vl/linear_boston_housing/targetValues.csv | awk 'NR>1' \
| awk 'BEGIN{RS="\r";ORS="";}{print $0}' | awk '$1=$1'`
calculateRMSE "$housePricePredictFile" "$housePriceTargetFile" "HousePrice" "均方根误差Root mean square error of Boston house price prediction is"

======> 均方根误差Root mean square error of Boston house price prediction is: 4.568173732895245

附录1 超级链存证保全函使用

比如我们拿到PPDE的证书的时候,会拿到一个超级链存证保全函,里面有存证哈希,区块链保全ID,以及区块链账户地址/文件名称/存证时间等信息。
那么我们拿到这些信息有什么用呢?

首先拿到区块链保全ID,在超级链网站百度存证链证据查验页面里:
https://xuper.baidu.com/n/verify
输入存证保全ID,可以看到返回存证哈希、存证保全ID、存证时间等信息。
亲爱的PPDE朋友们,快来查一下把。

附录2调试纠错

调试提醒

在2021.12.22日左右PaddleTDX更新版本,正好这个项目的调试时间处于更新前后,导致走了更多弯路。所以一定要及时更新版本,软件版本和手册版本要一致。

环境变量设置出问题

%set_env PATH=/usr/bin/: P A T H 命 令 之 后 , 发 现 环 境 变 量 成 为 : / u s r / b i n / : PATH 命令之后,发现环境变量成为: /usr/bin/: PATH/usr/bin/:PATH

解决方法:
手工写上

%env PATH=/home/aistudio/.data/webide/pip/bin:/opt/conda/envs/python35-paddle120-env/bin:/opt/conda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/nvidia/bin:/home/aistudio/work/go/bin

后来的解决方法为:

import os
os.environ['PATH'] = os.environ['PATH'] + ":/home/aistudio/go/bin"

xdb make报错

go env -w GO111MODULE=on
go env -w GONOSUMDB=\*
go mod download
go mod download: github.com/Joker/hpp@v1.0.0: Get "https://proxy.golang.org/github.com/%21joker/hpp/@v/v1.0.0.info": dial tcp 142.251.42.241:443: i/o timeout
go mod download: 
......
go mod download: github.com/xuperchain/xuperchain@v0.0.0-20210208123615-2d08ff11de3e: Get "https://proxy.golang.org/github.com/xuperchain/xuperchain/@v/v0.0.0-20210208123615-2d08ff11de3e.info": dial tcp 142.251.43.17:443: i/o timeout
go mod download: github.com/yudai/pp@v2.0.1+incompatible: Get "https://proxy.golang.org/github.com/yudai/pp/@v/v2.0.1+incompatible.info": dial tcp 142.251.43.17:443: i/o timeout
go mod download: golang.org/x/crypto@v0.0.0-20210920023735-84f357641f63: Get "https://proxy.golang.org/golang.org/x/crypto/@v/v0.0.0-20210920023735-84f357641f63.info": dial tcp 142.251.43.17:443: i/o timeout
Makefile:26: recipe for target 'gomod' failed
make: *** [gomod] Error 1

初步观察是go要下载软件导致的。
解决方法:
采用代理方式

即在执行前先设置好环境变量“GOPROXY”和“GO111MODULE”:

export GO111MODULE=on

export GOPROXY=https://goproxy.io或者export GOPROXY=https://goproxy.cn

对于1.13及以上版本,可直接如下这样:

go env -w GOPROXY=https://goproxy.cn,direct

最新2021.12.22日更新的版本,Makefile文件中已经加入该命令:

$(GO) env -w GOPROXY=https://goproxy.cn

因此这条命令可以省略了。同时新版本修改的还有xdb的命令文件,由xdata修改为xdb。

创建区块链账户报错:

执行这条命令./xchain-cli account newkeys --strength 1 -o ukeys的时候报错:

/bin/bash: ./xchain-cli: 没有那个文件或目录

就是没有这个文件啊,在哪里呢?
原来需要安装超级链xuperchain系统。
编译安装之后在xuperchain/output/bin目录执行即可。

执行区块链转 token报错

执行的命令是

!cd ~/xuperchain/output/bin && ./xchain-cli transfer --to $address --amount 1000000000000

报错是:

env: address=`cat /home/aistudio/xuperchain/output/bin/ukeys/address`
env: address=/home/aistudio/xuperchain/output/bin/ukeys/address
open data/keys/address: no such file or directory

经过测试,发现应该在output目录执行,最终执行命令为:

!cd ~/xuperchain/output/ && ./bin/xchain-cli transfer --to $address --amount 1000000000000

用这条命令之后报错

env: address=`cat bin/ukeys/address`
Select utxo error

终于明白了,这里需要打开超级链xuperchain服务进程!
于是打开xuper服务!打开之后报错:

报错address:no such file or directory

open data/keys/address: no such file or directory

不明白为什么会报错,因为确实有个文件啊!

变量设置命令是:export address=cat ./ukeys/address
哦哦,明白了,是路径问题,改成全路径试试。

改成全路径之后,能够执行下去,但是经过测试,发现在notebook下并没有按照设想把address文件内容赋值给变量address。经过实验,用这条命令解决这个问题:

address=!cat ~/xuperchain/output/ukeys/address
address = address[0]

BML CodeLab中插入视频但是不显示

用这个命令嵌入视频

<iframe  height=520 width=720 src="//player.bilibili.com/player.html?aid=379799392&bvid=BV1SZ4y1974W&cid=461940349&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>

在项目没执行前视频可以显示和播放,但是项目运行后(高端版)没有显示。
在老的经典版项目里同样的设置,是可以显示的。

暂时还没有解决问题。

在安装xuperchain的时候报错

按照手册执行!cd xuperchain/ && git checkout v5.1.0 %% make

error: pathspec '%%' did not match any file(s) known to git.
error: pathspec 'make' did not match any file(s) known to git.

通过对比操作,发现是书写错误,应该是&&,误写成%%了。虚惊一场。

超级链执行报错sh control.sh start

import os
os.system("cd ~/xuperchain/output/ && sh control.sh start")


/home/aistudio/xuperchain/output/bin/xchain
/home/aistudio/xuperchain/output/conf/env.yaml
control.sh: 160: control.sh: Syntax error: Bad for loop variable

经查,在AIStudio系统中应该使用bash而不是sh

import os
os.system("cd ~/xuperchain/output/ && bash control.sh start")

修改成启动成功!
最终使用如下民营启动超级链服务:

!cd ~/xuperchain/output/ && bash control.sh start 

验证时报错

!cd xuperchain && bin/xchain-cli status -H 127.0.0.1:37101

报错
/bin/bash: bin/xchain-cli: 没有那个文件或目录

发现目录里果然没有这个文件啊。重新倒命令行下去make
这回文件终于有了。

创建合约块的时候报错:

PreExe contract response : rpc error: code = Unknown desc = Err:500-50501-contract invoke failed+invoke NewAccount failed, account name length expect 16, actual: 18, logid:1640005476_4078206491125989

这是因为在notebook中,环境变量它把引号也算进去了。

后面安装合约的时候,也是同样的问题,报错:

open ./'paddlempc': no such file or directory

将这两个环境变量,在notebook中改为:

%env  contractAccount=1234567890123456
%env  contractName=paddlempc

即将变量赋值语句里的引号去掉。

安装合约的时候报错

open ./paddlempc: no such file or directory

原因是paddlempc文件根本就不在那个目录,加上路径使其能够找到那个文件,修改成:

"~/PaddleDTX/dai/$contractName"

启动数据存储节点服务时报错

命令为:!cd ~/PaddleDTX/xdb/output && ./xdata -c conf/config-storage.toml

ERRO[0000] app exit                                      error="missing log config"

不明白这里报错的原因和解决方法。只好一点点尝试。其实配置文件里是有log配置部分的,在把配置文件里的这句话# publicAddress = "10.144.94.17:8122"屏蔽后,报错开始变化,变成:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0xe8 pc=0xa8bb81]

goroutine 1 [running]:
github.com/spf13/viper.(*Viper).AllKeys(0x0)
	/home/aistudio/go/pkg/mod/github.com/spf13/viper@v1.7.1/viper.go:1824 +0xa1
github.com/spf13/viper.(*Viper).AllSettings(0x0)
	/home/aistudio/go/pkg/mod/github.com/spf13/viper@v1.7.1/viper.go:1904 +0x45
github.com/spf13/viper.(*Viper).Unmarshal(0xc000237cd8, {0x1165a40, 0xc0009168a0}, {0x0, 0x0, 0x0})
	/home/aistudio/go/pkg/mod/github.com/spf13/viper@v1.7.1/viper.go:908 +0x32
github.com/PaddlePaddle/PaddleDTX/xdb/config.InitConfig({0x7ffe1427ccce, 0x18})
	/home/aistudio/PaddleDTX/xdb/config/config.go:87 +0x1aa
main.init.0()
	/home/aistudio/PaddleDTX/xdb/main.go:63 +0xbe

没有方向的时候,就看手册吧。手册地址:https://github.com/PaddlePaddle/PaddleDTX/blob/master/xdb/README_CN.md
服务启动和命令说明:https://hub.fastgit.org/PaddlePaddle/PaddleDTX/blob/master/xdb/scripts/README.md

中间一度完全找不到方向,后来大约明白了,
应该还是需要publicAddress参数的,修改成publicAddress = "127.0.0.1:8122"

继续处理启动数据存储节点服务时报错

经过前面的修改,
现在报错为:

2021/12/25 12:06:19 Config yamlFile get error #open ./conf/sdk.yaml: no such file or directory
2021/12/25 12:06:19 GetConfig: &{10.144.94.18:8848 {false false 10 XBbhR82cB6PvaLJs3D4uB9f12bhmKkHeX TYyA3y8wdFZyzExtcbRNVd7ZZ2XXcfjdw} 100 xchain}

初步诊断,可能是fabric那边的问题。(但其实不是fabric那边的问题)
查看系统里有关yaml sdk的信息,在xdb/scripts/network_up.sh找到这句

# Copy fabric sdk yaml file into xdb configuration directory
  # 拷贝sdk yaml文件到xdb配置目录下
  CONFFILE_LIST="dataowner storage1 storage2 storage3"
  for CONF_PATH in $CONFFILE_LIST
  do
    mkdir -p ../$TMP_CONF_NAME/xdb/$CONF_PATH/conf/fabric/
    cp -f ../$TMP_CONF_NAME/blockchain/fabric/conf/config.yaml ../$TMP_CONF_NAME/xdb/$CONF_PATH/conf/fabric/
    cp -rf ../$TMP_CONF_NAME/blockchain/fabric/crypto-config ../$TMP_CONF_NAME/xdb/$CONF_PATH/conf/fabric/
  done
}

在另外一台机器上重新安装PaddleDTX,发现竟然有sdk.yaml这个文件(其实这个文件是自己创建的,把自己都骗了),把这个cp到本地。然后执行,有新的报错:

xdb启动服务报错:Config Unmarshal error: yaml: unmarshal errors

2021/12/25 14:17:43 Config Unmarshal error: yaml: unmarshal errors:
  line 3: cannot unmarshal !!str `type = ...` into config.CommConfig

自己乱写的sdk.yaml文件,不出错才真的奇怪呢。
把自己写的sdk.yaml文件删除掉。

后来了解到该错误是依赖模块提示,可参考https://github.com/xuperchain/xuper-sdk-go 配置,当前项目如果不配置不影响服务正常使用

弄明白就好了,这个报错可以不用管了

创建命名空间报错

使用的命令为:

!cd ~/PaddleDTX/xdb/output &&  ./xdb-cli files addns  --host http://127.0.0.1:8122 -k eae7344064e1d5b53af6da1a23407b1e7e265d15eaf0442c476e3caac3003406 -n paddlempc  -r 2

报错:
err:{"code":"XDAT0004","message":"from xdb api: request url not found"}

调试的时候百思不得其解,甚至一度怀疑端口监听到ipv6地址了。但是查看前面开服务的时候,已经测试连接,输出状态信息了。

后来仔细看,发现是连通数据持有节点,而8122端口是数据存储节点,原来文档上面写错端口号了。

修改命令端口号到8123,搞定!

!cd ~/PaddleDTX/xdb/output &&  ./xdb-cli files addns  --host http://127.0.0.1:8123 -k eae7344064e1d5b53af6da1a23407b1e7e265d15eaf0442c476e3caac3003406 -n paddlempc  -r 2

创建命名空间报错2

使用上面的命令,报错:

err:{"code":"XDAT0002","message":"from xdb api: invalid param: replica must no greater than nodes number"}

原来是我们这个项目里面只运行了一个数据持有节点,因此要把最后的参数改为1
!cd ~/PaddleDTX/xdb/output && ./xdb-cli files addns --host http://127.0.0.1:8123 -k eae7344064e1d5b53af6da1a23407b1e7e265d15eaf0442c476e3caac3003406 -n paddlempc -r 1

这样创建命名空间就执行好了!(数据持有节点单独一个是不行的,后来才知道)

创建文件存储命名空间时报错

# 命令
!cd ~/PaddleDTX/xdb/output &&  ./xdb-cli files addns  --host http://127.0.0.1:8123 -k eae7344064e1d5b53af6da1a23407b1e7e265d15eaf0442c476e3caac3003406 -n paddlempc  -n paddlempc -r 2
报错信息
err:{"code":"XDAT0002","message":"from xdb api: invalid param: replica must no greater than nodes number"}

这样就需要至少两个节点啊

docker里面没有ping等网络命令

解决方法:

apt-get update

apt install net-tools       # ifconfig 

apt install iputils-ping     # ping

双存储双数据持有节点双执行节点

总之每个节点都放两个

tcp6       0      0 :::8184                 :::*                    LISTEN     
tcp6       0      0 :::8185                 :::*                    LISTEN     
tcp6       0      0 :::8122                 :::*                    LISTEN     
tcp6       0      0 :::8123                 :::*                    LISTEN     
tcp6       0      0 :::8132                 :::*                    LISTEN     
tcp6       0      0 :::8133                 :::*                    LISTEN   

创建命名空间报错

# 创建新的命名存储空间,一般要副本数为2 
!cd ~/PaddleDTX/xdb/output &&  ./xdb-cli files addns  --host http://127.0.0.1:8123 -k eae7344064e1d5b53af6da1a23407b1e7e265d15eaf0442c476e3caac3003406 -n paddlempc  -n paddlempc -r 2

输出信息:
err:{"code":"XDAT0007","message":"from xdb api: duplicated file namespace"}

仔细一看,竟然真的写了两遍啊!
改写成一个
!cd ~/PaddleDTX/xdb/output && ./xdb-cli files addns --host http://127.0.0.1:8123 -k eae7344064e1d5b53af6da1a23407b1e7e265d15eaf0442c476e3caac3003406 -n paddlempc -r 2

结果还是报错:

err:{"code":"XDAT0007","message":"from xdb api: duplicated file namespace"}

找命令,发现一条update命令,按照手册修改成

!cd ~/PaddleDTX/xdb/output &&  ./xdb-cli files ureplica  --host http://127.0.0.1:8123 -k eae7344064e1d5b53af6da1a23407b1e7e265d15eaf0442c476e3caac3003406 -n paddlempc -r 2

输出ok,使用命令,果然,变成两个了。命令的输出不少啊

2021/12/31 12:34:42 contract response: {"Name":"paddlempc","Description":"","Owner":"rKa0OSCDjqSkBmea4oqn0r/TGNucaEZi2EzBjo13f7P4ZJoIeo2juPmPaAa9TH1PiydCoqNMok7fCXeER6VhSQ==","Replica":1,"FilesStructSize":1393,"FileTotalNum":1,"CreateTime":1640677816604468741,"UpdateTime":1640680262473574537}
2021/12/31 12:34:42 Gas will cost: 1
2021/12/31 12:34:42 contract response: [{"ID":"MzYzYzRjOTk2YTBhNmQ4M2YzZDhiMzE4MDAxOTcwMmJlMWI3YmI3YTVlMmE2MWNlMWVmOTUwM2E1YWQ1NWM0YmViMWM3OGQ2MTYzNTVhNTg1NTYwMTBhMzUxOGM2NjUyNmM2ZGMxN2IwYmVhM2ZlOTY1MDQyYWQzYWRjZmUzZTY=","Name":"storageNode2","Address":"127.0.0.1:8132","Online":true,"RegTime":1640917119094221006,"UpdateAt":1640925223380060112},{"ID":"YWNhNmI0MzkyMDgzOGVhNGE0MDY2NzlhZTI4YWE3ZDJiZmQzMThkYjljNjg0NjYyZDg0Y2MxOGU4ZDc3N2ZiM2Y4NjQ5YTA4N2E4ZGEzYjhmOThmNjgwNmJkNGM3ZDRmOGIyNzQyYTJhMzRjYTI0ZWRmMDk3Nzg0NDdhNTYxNDk=","Name":"storageNode1","Address":"127.0.0.1:8122","Online":true,"RegTime":1640612880351143962,"UpdateAt":1640925223327823002}]
2021/12/31 12:34:42 Gas will cost: 1
2021/12/31 12:34:42 contract response: {"ID":"MzYzYzRjOTk2YTBhNmQ4M2YzZDhiMzE4MDAxOTcwMmJlMWI3YmI3YTVlMmE2MWNlMWVmOTUwM2E1YWQ1NWM0YmViMWM3OGQ2MTYzNTVhNTg1NTYwMTBhMzUxOGM2NjUyNmM2ZGMxN2IwYmVhM2ZlOTY1MDQyYWQzYWRjZmUzZTY=","Name":"storageNode2","Address":"127.0.0.1:8132","Online":true,"RegTime":1640917119094221006,"UpdateAt":1640925223380060112}
2021/12/31 12:34:42 Gas will cost: 1
2021/12/31 12:34:42 contract response: 0
2021/12/31 12:34:42 Gas will cost: 1
2021/12/31 12:34:42 contract response: 114
2021/12/31 12:34:42 Gas will cost: 1
2021/12/31 12:34:42 contract response: {"ID":"YWNhNmI0MzkyMDgzOGVhNGE0MDY2NzlhZTI4YWE3ZDJiZmQzMThkYjljNjg0NjYyZDg0Y2MxOGU4ZDc3N2ZiM2Y4NjQ5YTA4N2E4ZGEzYjhmOThmNjgwNmJkNGM3ZDRmOGIyNzQyYTJhMzRjYTI0ZWRmMDk3Nzg0NDdhNTYxNDk=","Name":"storageNode1","Address":"127.0.0.1:8122","Online":true,"RegTime":1640612880351143962,"UpdateAt":1640925223327823002}
2021/12/31 12:34:42 Gas will cost: 1
2021/12/31 12:34:42 contract response: 8
2021/12/31 12:34:42 Gas will cost: 1
2021/12/31 12:34:42 contract response: 8
2021/12/31 12:34:42 Gas will cost: 1
2021/12/31 12:34:42 contract response: 105
2021/12/31 12:34:42 Gas will cost: 1
2021/12/31 12:34:42 contract response: 110
2021/12/31 12:34:42 Gas will cost: 1
2021/12/31 12:34:42 contract response: 456
2021/12/31 12:34:42 Gas will cost: 1
2021/12/31 12:34:42 contract response: 100
2021/12/31 12:34:42 Gas will cost: 1
2021/12/31 12:34:42 contract response: [{"ID":"8347350d-0904-49a7-ba19-0cca6df29a93","Name":"train_dataA4.csv","Description":"train_dataA4","Namespace":"paddlempc","Owner":"rKa0OSCDjqSkBmea4oqn0r/TGNucaEZi2EzBjo13f7P4ZJoIeo2juPmPaAa9TH1PiydCoqNMok7fCXeER6VhSQ==","Length":18083,"MerkleRoot":"vOKoBoAaYo9VleB3JrEetaRy1QAq4mR73b7M3NV3EX0=","Slices":[{"ID":"d810190d-6ae5-4cf5-9ba3-d3fb079ea7f9","CipherHash":"yNk8aIMq1aAb9KwK1nfTBiACqkfIvvWbFbvTZt/Gm9Q=","Length":4194320,"NodeID":"YWNhNmI0MzkyMDgzOGVhNGE0MDY2NzlhZTI4YWE3ZDJiZmQzMThkYjljNjg0NjYyZDg0Y2MxOGU4ZDc3N2ZiM2Y4NjQ5YTA4N2E4ZGEzYjhmOThmNjgwNmJkNGM3ZDRmOGIyNzQyYTJhMzRjYTI0ZWRmMDk3Nzg0NDdhNTYxNDk=","SliceIdx":1,"SigmaI":"VwBqSPoNuwz1K56DOQt3D+1ryxzp+bPE7njtoz44aSFbq5DbUabN+sLtSVWI7cPaiTcCzvhgIStonVv5FmnhaQ=="}],"Structure":"V1ySqZ/AbBueG3SRNeE7dDzqQclIWMr3ODy2v/u6J+6AjI3Q+1t+mlDm81AgvxcVzb3xW6ufxrD987hwXejhw59tcNN0z+FRB6Ysm4VZiTqWd0cfim18x5qVME4TwPYA7VTODt0/KdsO4WJrEwI5bg0/y0HEzd8fVBLSOsdKGw==","PublishTime":1640680262473574537,"ExpireTime":1670644800000000000,"PdpPubkey":"AVcT6JO4Ddcq+JjC2Vw/kGZSrCjEeCu1Lu1EFya9C96Nb/HtJkaHEJ4Ni89leAAaCbKu/oEFrfEpb3oAaEd2JqNuyBlWZ0MZk7PmFkaUlYaTVvQRUWRRSmiIZa+iNtJEIYC/AC5C88k1vRoXq3m7VonvJUFP95oLX3CSMMfSiUln","RandU":"AfM3n7CzmkbVEBRPOYV8gH1qpyaQdTNA1MZ7PHYfmWs=","RandV":"TKOt9kE7m5O7fCztoyy1J+WpNugLxKPS3hweeUK+09Y=","Ext":"eyJGaWxlVHlwZSI6ImNzdiIsIkZlYXR1cmVzIjoiaWQsQ1JJTSxaTixJTkRVUyxDSEFTLE5PWCxSTSIsICJUb3RhbFJvd3MiOjQ1N30="}]
2021/12/31 12:34:42 Gas will cost: 1
2021/12/31 12:34:42 Gas will cost: 830
2021/12/31 12:34:42 contract response: OK
2021/12/31 12:34:42 contract response: {"ID":"8347350d-0904-49a7-ba19-0cca6df29a93","Name":"train_dataA4.csv","Description":"train_dataA4","Namespace":"paddlempc","Owner":"rKa0OSCDjqSkBmea4oqn0r/TGNucaEZi2EzBjo13f7P4ZJoIeo2juPmPaAa9TH1PiydCoqNMok7fCXeER6VhSQ==","Length":18083,"MerkleRoot":"vOKoBoAaYo9VleB3JrEetaRy1QAq4mR73b7M3NV3EX0=","Slices":[{"ID":"d810190d-6ae5-4cf5-9ba3-d3fb079ea7f9","CipherHash":"yNk8aIMq1aAb9KwK1nfTBiACqkfIvvWbFbvTZt/Gm9Q=","Length":4194320,"NodeID":"YWNhNmI0MzkyMDgzOGVhNGE0MDY2NzlhZTI4YWE3ZDJiZmQzMThkYjljNjg0NjYyZDg0Y2MxOGU4ZDc3N2ZiM2Y4NjQ5YTA4N2E4ZGEzYjhmOThmNjgwNmJkNGM3ZDRmOGIyNzQyYTJhMzRjYTI0ZWRmMDk3Nzg0NDdhNTYxNDk=","SliceIdx":1,"SigmaI":"VwBqSPoNuwz1K56DOQt3D+1ryxzp+bPE7njtoz44aSFbq5DbUabN+sLtSVWI7cPaiTcCzvhgIStonVv5FmnhaQ=="}],"Structure":"V1ySqZ/AbBueG3SRNeE7dDzqQclIWMr3ODy2v/u6J+6AjI3Q+1t+mlDm81AgvxcVzb3xW6ufxrD987hwXejhw59tcNN0z+FRB6Ysm4VZiTqWd0cfim18x5qVME4TwPYA7VTODt0/KdsO4WJrEwI5bg0/y0HEzd8fVBLSOsdKGw==","PublishTime":1640680262473574537,"ExpireTime":1670644800000000000,"PdpPubkey":"AVcT6JO4Ddcq+JjC2Vw/kGZSrCjEeCu1Lu1EFya9C96Nb/HtJkaHEJ4Ni89leAAaCbKu/oEFrfEpb3oAaEd2JqNuyBlWZ0MZk7PmFkaUlYaTVvQRUWRRSmiIZa+iNtJEIYC/AC5C88k1vRoXq3m7VonvJUFP95oLX3CSMMfSiUln","RandU":"AfM3n7CzmkbVEBRPOYV8gH1qpyaQdTNA1MZ7PHYfmWs=","RandV":"TKOt9kE7m5O7fCztoyy1J+WpNugLxKPS3hweeUK+09Y=","Ext":"eyJGaWxlVHlwZSI6ImNzdiIsIkZlYXR1cmVzIjoiaWQsQ1JJTSxaTixJTkRVUyxDSEFTLE5PWCxSTSIsICJUb3RhbFJvd3MiOjQ1N30="}
2021/12/31 12:34:42 Gas will cost: 1
2021/12/31 12:34:42 Gas will cost: 1850
2021/12/31 12:34:42 contract response: OK

使用查看命令:

Name: paddlempc
FileTotalNum: 1
Replica: 2
NsDescription: 
UpdateTime: 2021-12-31 12:34:42
CreateTime: 2021-12-28 15:50:16

果然变成两个replica

发起训练任务报错

命令
!cd ~/PaddleDTX/dai/executor1 && ./requester-cli task publish -a "linear-vl" -l "MEDV" \
-k eae7344064e1d5b53af6da1a23407b1e7e265d15eaf0442c476e3caac3003406 -t "train" \
-n "房价预测任务v3" -d "hahahha" -p "id,id" --conf ~/PaddleDTX/dai/executor1/conf/config.toml \
-f "8347350d-0904-49a7-ba19-0cca6df29a93"
报错
Publish task failed: {"code":"XDAT0002","message":"not enough data set numbers, got: 1"}

快速训练文档中,上传文件报错

!cd ~/PaddleDTX/xdb/output && ./xdb-cli --host http://127.0.0.1:8121 files upload \
-k $REQUESTERKEY -n paddlempc \
-m train_dataA4t1.csv -i ~/PaddleDTX/dai/mpc/testdata/vl/linear_boston_housing/train_dataA.csv \
--ext '{"FileType":"csv","Features":"id,CRIM,ZN,INDUS,CHAS,NOX,RM", "TotalRows":457}' \
-e '2022-12-10 12:00:00' -d 'train_dataA41'
报错信息:
Error: required flag(s) "namespace" not set
Usage:
  xdb-cli files upload [flags]

经过调试,发现将-k $REQUESTERKEY 参数,修改为

-k 14a54c188d0071bc1b161a50fe7eacb74dcd016993bb7ad0d5449f72a8780e21

即不报错

拉起任务后报错

ErrMessage: {"code":"XDAT0002","message":"invalid addr: parse \"127.0.0.1:8121\": first path segment in URL cannot contain colon"}
Result: 

解决方法:
在执行节点里面设置持有节点的时候,需要加上http头:

 host = "http://127.0.0.1:8121"

上传数据报错

向数据持有节点上传数据,报错

err:open ./train_dataA.csv: no such file or directory

-m train_dataA4.csv -i ./train_dataA.csv
分别为文件名称和上传的文件。 问题没有在相关目录看见这个文件啊!

PaddleDTX/dai/mpc/testdata/vl/linear_boston_housing/train_dataA.csv 位置有这个文件,那就用这个文件吧。

命令为:

!cd ~/PaddleDTX/xdb/output &&  ./xdb-cli --host http://127.0.0.1:8123 files upload -k 14a54c188d0071bc1b161a50fe7eacb74dcd016993bb7ad0d5449f72a8780e21 -n paddlempc -m train_dataA4.csv -i ~/PaddleDTX/dai/mpc/testdata/vl/linear_boston_housing/train_dataA.csv --ext '{"FileType":"csv","Features":"id,CRIM,ZN,INDUS,CHAS,NOX,RM", "TotalRows":457}'  -e '2021-12-10 12:00:00' -d 'train_dataA4'

报错时间过期

执行上面命令后,报错

err:{"code":"XDAT0002","message":"from xdb api: invalid file expire time"}

原来是文档里面定义的文档过期时间已经过期,将时间改长

!cd ~/PaddleDTX/xdb/output &&  ./xdb-cli --host http://127.0.0.1:8123 files upload -k 14a54c188d0071bc1b161a50fe7eacb74dcd016993bb7ad0d5449f72a8780e21 -n paddlempc -m train_dataA4.csv -i ~/PaddleDTX/dai/mpc/testdata/vl/linear_boston_housing/train_dataA.csv --ext '{"FileType":"csv","Features":"id,CRIM,ZN,INDUS,CHAS,NOX,RM", "TotalRows":457}'  -e '2022-12-10 12:00:00' -d 'train_dataA4'

还有一些调试信息,因为篇幅限制,没有放在这个文档,而是放在debug.ipynb文件中了。

编译区域链合约报错

!cd ~/PaddleDTX/dai &&  go build -o paddlempc ./blockchain/xchain/contract

报错信息

../../go/pkg/mod/github.com/!paddle!paddle/!paddle!d!t!x/xdb@v0.0.0-20220105070447-3045ca6cf1af/blockchain/xchain/contract/core/challenging.go:25:2: missing go.sum entry for module providing package github.com/xuperchain/xuperchain/core/contractsdk/go/code (imported by github.com/PaddlePaddle/PaddleDTX/dai/blockchain/xchain/contract); to add:
	go get github.com/PaddlePaddle/PaddleDTX/dai/blockchain/xchain/contract
blockchain/xchain/contract/main.go:17:2: missing go.sum entry for module providing package github.com/xuperchain/xuperchain/core/contractsdk/go/driver (imported by github.com/PaddlePaddle/PaddleDTX/dai/blockchain/xchain/contract); to add:
	go get github.com/PaddlePaddle/PaddleDTX/dai/blockchain/xchain/contract

看这种报错,是没有写go代理啊?
加上代理也不行。

按照提示使用这条命令!cd go && go mod tidy
没有解决。

使用这条命令go mod download
显示信息:go mod download: no modules specified (see 'go help mod download')

查看代码,区域链合约相关代码近期并没有修改,那么为什么以前能编译,现在不能编译了呢?

重新下载、安装go,发现卡住
!wget https://go.dev/dl/go1.17.5.linux-amd64.tar.gz && tar -xzvf go1.17.5.linux-amd64.tar.gz
过了一会儿,估计是自动换了下载源,go终于重装好了。

然后再编译合约,就顺利过去了。
所以结论就是:go语言这里非常省心,但是如果网络有问题,有时候就不省心了。

并没有编译成功,继续报前面的错。自己看报错,它有提示:

go get github.com/PaddlePaddle/PaddleDTX/dai/blockchain/xchain/contract

按照提示发这条命令,输出信息;

go: downloading github.com/xuperchain/xuperchain v0.0.0-20210208123615-2d08ff11de3e
go: downloading github.com/go-playground/validator/v10 v10.4.1
go: downloading github.com/leodido/go-urn v1.2.0
go: downloading github.com/go-playground/universal-translator v0.17.0
go: downloading github.com/go-playground/locales v0.13.0
go get: installing executables with 'go get' in module mode is deprecated.
	Use 'go install pkg@version' instead.
	For more information, see https://golang.org/doc/go-get-install-deprecation
	or run 'go help get' or 'go help install'.

初步断定是go语言版本太高的缘故,它修改了包管理模式。按照提示,去看网页:https://golang.org/doc/go-get-install-deprecation,结果无法打开,判断还是网络有问题啊。

通过修改go版本来解决合约编译问题

使用15.14版本go,结果报错:note: module requires Go 1.16
那就用16版本试试。
使用16.13版本,区域链合约编译成功!
https://studygolang.com/dl/golang/go1.16.13.linux-amd64.tar.gz

在一次重新测试中,继续上面的报错。
报issue

任务提交报错:

ErrMessage: {"code":"XDAT0009","message":"from xdb api: file decryption failed: {\"code\":\"XDAT0001\",\"message\":\"failed to read: {\\\"code\\\":\\\"XDAT0004\\\",\\\"message\\\":\\\"failed to pull slice 7a0ffd2a-3ed1-4f64-8a47-6969ac78c300\\\"}\"}"}
Result: 

查找问题,发现重新上传数据集时报错:

err:{"code":"XDAT0001","message":"from xdb api: available healthy nodes smaller than replica"}

去查看节点,发现三个数据存储节点都在,这是怎么回事呢?

启动数据节点的时候报错:


2022/01/09 10:49:11 GetConfig: &{10.144.94.18:8848 {false false 10 XBbhR82cB6PvaLJs3D4uB9f12bhmKkHeX TYyA3y8wdFZyzExtcbRNVd7ZZ2XXcfjdw} 100 xchain}```



## 报issue:
https://github.com/PaddlePaddle/PaddleDTX/issues/30

https://github.com/PaddlePaddle/PaddleDTX/issues/32

https://github.com/PaddlePaddle/PaddleDTX/issues/34

https://hub.fastgit.org/PaddlePaddle/PaddleDTX/issues/38

# 附录3 相关参考资料
超级链文档;https://xuper.baidu.com/n/xuperdoc/quickstart/quickstart.html

Xuper Chain快速入门视频https://www.bilibili.com/video/BV1mX4y1P7Rt?share_source=copy_web

XuperDB手册
https://github.com/PaddlePaddle/PaddleDTX/blob/master/xdb/README_CN.md

XuperDB服务启动和命令使用说明
https://hub.fastgit.org/PaddlePaddle/PaddleDTX/blob/master/xdb/scripts/README.md

BSN第三届开发者大赛进阶培训—XuperChain专场视频https://www.bilibili.com/video/BV1R44y1v7Vp?share_source=copy_web

开发者大赛赛前培训讲座 |《区块链基础技术与XuperChain架构解读》
https://xuper.baidu.com/n/news/936a0b3a0a5522b1fb1558fc1fab47ac

开发者大赛赛前培训讲座 |《XuperChain存证系统开发案例讲解》
https://xuper.baidu.com/n/news/b8cf67906671b6e3b8f53be95e8b779b

杨强丨用户隐私,数据孤岛和联邦学习
https://www.bilibili.com/video/BV1n44y1278k


# 结束语

## 项目总结:
这是我最耗时完成的项目之一,中间一度想放弃,还好最后坚持下来了。
整个项目的难点有三处:
* github和go都有抽风的时候
* 链桨基于超级链,使用多方数据存储和计算,牵一发而动全身,调试比普通项目复杂和繁琐很多
* 对超级链和链桨不了解,很多地方是文档、代码一起看,要慢慢摸索调试

如果本项目一键执行没有成功,不要放弃,找到报错的地方,解决后再重新执行项目试试。也请大家把碰到的问题写出来,以便修正,提高大家的使用体验!


让我们荡起双桨,在AI的海洋乘风破浪!

飞桨官网:https://www.paddlepaddle.org.cn

因为水平有限,难免有不足之处,还请大家多多帮助。

作者:段春华, 网名skywalk 或 天马行空,济宁市极快软件科技有限公司的AI架构师,百度飞桨PPDE。

我在AI Studio上获得至尊等级,点亮10个徽章,来关注我啊~ https://aistudio.baidu.com/aistudio/personalcenter/thirdview/141218
Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐