使用pysyft发送模型给带数据集的远端WebsocketServerWorker作联合训练

27 篇文章 7 订阅
11 篇文章 12 订阅

WebsocketServerWorker端代码:start_worker.py

import argparse

import torch as th
from syft.workers.websocket_server import WebsocketServerWorker

import syft as sy

# Arguments
parser = argparse.ArgumentParser(description="Run websocket server worker.")
parser.add_argument(
    "--port", "-p", type=int, help="port number of the websocket server worker, e.g. --port 8777"
)
parser.add_argument("--host", type=str, default="localhost", help="host for the connection")
parser.add_argument(
    "--id", type=str, help="name (id) of the websocket server worker, e.g. --id alice"
)
parser.add_argument(
    "--verbose",
    "-v",
    action="store_true",
    help="if set, websocket server worker will be started in verbose mode",
)


def main(**kwargs):  # pragma: no cover
    """Helper function for spinning up a websocket participant."""

    # Create websocket worker
    worker = WebsocketServerWorker(**kwargs)

    # Setup toy data (xor example)
    data = th.tensor([[0.0, 1.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]], requires_grad=True)
    target = th.tensor([[1.0], [1.0], [0.0], [0.0]], requires_grad=False)

    # Create a dataset using the toy data
    dataset = sy.BaseDataset(data, target)

    # Tell the worker about the dataset
    worker.add_dataset(dataset, key="xor")

    # Start worker
    worker.start()

    return worker


if __name__ == "__main__":
    hook = sy.TorchHook(th)

    args = parser.parse_args()
    kwargs = {
        "id": args.id,
        "host": args.host,
        "port": args.port,
        "hook": hook,
        "verbose": args.verbose,
    }

    main(**kwargs)

启动worker

  python start_worker.py --host 172.16.5.45 --port 8777 --id alice

客户端代码:

import inspect
import start_worker

print(inspect.getsource(start_worker.main))

# Dependencies
import torch as th
import torch.nn.functional as F
from torch import nn

use_cuda = th.cuda.is_available()
th.manual_seed(1)
device = th.device("cuda" if use_cuda else "cpu")

import syft as sy
from syft import workers

hook = sy.TorchHook(th)  # hook torch as always :)


class Net(th.nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(2, 20)
        self.fc2 = nn.Linear(20, 10)
        self.fc3 = nn.Linear(10, 1)
        
    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

# Instantiate the model
model = Net()

# The data itself doesn't matter as long as the shape is right
mock_data = th.zeros(1, 2)

# Create a jit version of the model
traced_model = th.jit.trace(model, mock_data)

type(traced_model)




# Loss function
@th.jit.script
def loss_fn(target, pred):
    return ((target.view(pred.shape).float() - pred.float()) ** 2).mean()

type(loss_fn)


optimizer = "SGD"

batch_size = 4
optimizer_args = {"lr" : 0.1, "weight_decay" : 0.01}
epochs = 1
max_nr_batches = -1  # not used in this example
shuffle = True


train_config = sy.TrainConfig(model=traced_model,
                              loss_fn=loss_fn,
                              optimizer=optimizer,
                              batch_size=batch_size,
                              optimizer_args=optimizer_args,
                              epochs=epochs,
                              shuffle=shuffle)


kwargs_websocket = {"host": "172.16.5.45", "hook": hook, "verbose": False}
alice = workers.websocket_client.WebsocketClientWorker(id="alice", port=8777, **kwargs_websocket)


# Send train config
train_config.send(alice)

# Setup toy data (xor example)
data = th.tensor([[0.0, 1.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]], requires_grad=True)
target = th.tensor([[1.0], [1.0], [0.0], [0.0]], requires_grad=False)

print("\nEvaluation before training")
pred = model(data)
loss = loss_fn(target=target, pred=pred)
print("Loss: {}".format(loss))
print("Target: {}".format(target))
print("Pred: {}".format(pred))


for epoch in range(10):
    loss = alice.fit(dataset_key="xor")  # ask alice to train using "xor" dataset
    print("-" * 50)
    print("Iteration %s: alice's loss: %s" % (epoch, loss))


new_model = train_config.model_ptr.get()

print("\nEvaluation after training:")
pred = new_model(data)
loss = loss_fn(target=target, pred=pred)
print("Loss: {}".format(loss))
print("Target: {}".format(target))
print("Pred: {}".format(pred))


运行:

python worker-client.py 

输出结果:

Evaluation before training
Loss: 0.4933376908302307
Target: tensor([[1.],
        [1.],
        [0.],
        [0.]])
Pred: tensor([[ 0.1258],
        [-0.0994],
        [ 0.0033],
        [ 0.0210]], grad_fn=<AddmmBackward>)
--------------------------------------------------
Iteration 0: alice's loss: tensor(0.4933, requires_grad=True)
--------------------------------------------------
Iteration 1: alice's loss: tensor(0.3484, requires_grad=True)
--------------------------------------------------
Iteration 2: alice's loss: tensor(0.2858, requires_grad=True)
--------------------------------------------------
Iteration 3: alice's loss: tensor(0.2626, requires_grad=True)
--------------------------------------------------
Iteration 4: alice's loss: tensor(0.2529, requires_grad=True)
--------------------------------------------------
Iteration 5: alice's loss: tensor(0.2474, requires_grad=True)
--------------------------------------------------
Iteration 6: alice's loss: tensor(0.2441, requires_grad=True)
--------------------------------------------------
Iteration 7: alice's loss: tensor(0.2412, requires_grad=True)
--------------------------------------------------
Iteration 8: alice's loss: tensor(0.2388, requires_grad=True)
--------------------------------------------------
Iteration 9: alice's loss: tensor(0.2368, requires_grad=True)

Evaluation after training:
Loss: 0.23491761088371277
Target: tensor([[1.],
        [1.],
        [0.],
        [0.]])
Pred: tensor([[0.6553],
        [0.3781],
        [0.4834],
        [0.4477]], grad_fn=<DifferentiableGraphBackward>)

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是使用 Pysyft 框架实现差分隐私保护的联邦学习线性回归模型的示例代码: ```python import torch import syft as sy import pandas as pd from sklearn.preprocessing import StandardScaler from torch.utils.data import TensorDataset, DataLoader from torch import nn, optim # 创建虚拟的工节点 hook = sy.TorchHook(torch) worker1 = sy.VirtualWorker(hook, id="worker1") worker2 = sy.VirtualWorker(hook, id="worker2") worker3 = sy.VirtualWorker(hook, id="worker3") # 加载数据集并进行预处理 df = pd.read_csv('https://raw.githubusercontent.com/mwaskom/seaborn-data/master/diamonds.csv') df = df.drop(['Unnamed: 0'], axis=1) df = pd.get_dummies(df, columns=['cut', 'color', 'clarity']) scaler = StandardScaler() scaled_features = scaler.fit_transform(df.drop('price', axis=1).values) target = df['price'].values X_train = torch.tensor(scaled_features[:30000]).float() y_train = torch.tensor(target[:30000]).float().view(-1, 1) X_test = torch.tensor(scaled_features[30000:]).float() y_test = torch.tensor(target[30000:]).float().view(-1, 1) # 将数据分别发送给三个工节点 X_train1 = X_train[:10000].send(worker1) y_train1 = y_train[:10000].send(worker1) X_train2 = X_train[10000:20000].send(worker2) y_train2 = y_train[10000:20000].send(worker2) X_train3 = X_train[20000:].send(worker3) y_train3 = y_train[20000:].send(worker3) # 创建模型 class LinearRegression(nn.Module): def __init__(self, input_size): super().__init__() self.linear = nn.Linear(input_size, 1) def forward(self, x): return self.linear(x) model = LinearRegression(X_train.shape[1]) # 定义损失函数和优化器 criterion = nn.MSELoss() optimizer = optim.SGD(model.parameters(), lr=0.01) # 训练模型 epochs = 10 batch_size = 32 epsilon = 0.1 for epoch in range(epochs): # 在每个工节点上训练模型 for i in range(0, len(X_train1), batch_size): X_batch1 = X_train1[i:i+batch_size] y_batch1 = y_train1[i:i+batch_size] X_batch2 = X_train2[i:i+batch_size] y_batch2 = y_train2[i:i+batch_size] X_batch3 = X_train3[i:i+batch_size] y_batch3 = y_train3[i:i+batch_size] model = model.fix_precision().send(X_batch1.location) optimizer.zero_grad() pred1 = model(X_batch1) loss1 = criterion(pred1, y_batch1) loss1.backward() optimizer.step() model = model.fix_precision().send(X_batch2.location) optimizer.zero_grad() pred2 = model(X_batch2) loss2 = criterion(pred2, y_batch2) loss2.backward() optimizer.step() model = model.fix_precision().send(X_batch3.location) optimizer.zero_grad() pred3 = model(X_batch3) loss3 = criterion(pred3, y_batch3) loss3.backward() optimizer.step() # 对模型进行差分隐私保护 model = model.get().float_precision() model.weight.data += torch.normal(torch.zeros_like(model.weight.data), epsilon) model.bias.data += torch.normal(torch.zeros_like(model.bias.data), epsilon) model = model.fix_precision().share(X_batch1.location, X_batch2.location, X_batch3.location) # 在测试集上评估模型的性能 with torch.no_grad(): model = model.get().float_precision() pred = model(X_test) loss = criterion(pred, y_test) print('Epoch {}/{} - Test loss: {}'.format(epoch+1, epochs, loss)) ``` 上述代码中,首先创建了三个虚拟的工节点,并加载并预处理了数据集。然后,将数据集分别发送给三个工节点进行训练。在每个工节点上,使用固定精度(fixed precision)对模型进行处理,以便在加密的状态下进行计算。然后,对模型进行差分隐私处理,以保护用户的隐私。最后,在测试集上评估模型的性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值