예제 #1
0
파일: Client.py 프로젝트: Carudy/sofl
class FL_client():
    def __init__(self, args):
        if args.dataset == 'cifar':
            self.net = CNNCifar(args=args).to(args.device)
        else:
            self.net = CNNMnist(args=args).to(args.device)
        self.net.train()
        self.loss_func = nn.CrossEntropyLoss()
        self.optimizer = torch.optim.SGD(self.net.parameters(), lr=args.lr)
        self.args = args
        self.w_glob = []
        # key exchange
        self.x = self.gx = 0
        self.keys = defaultdict(int)

    def set_data(self, dataset, idxs):
        self.data = DataLoader(DatasetSplit(dataset, idxs),
                               batch_size=self.args.local_bs,
                               shuffle=True)

    def load_state(self, state_dict):
        self.net.load_state_dict(state_dict)

    def train(self):
        epoch_loss = []
        for _ in range(self.args.local_ep):
            batch_loss = []
            for _, (images, labels) in enumerate(self.data):
                images, labels = images.to(self.args.device), labels.to(
                    self.args.device)
                pred = self.net(images)
                loss = self.loss_func(pred, labels)
                self.optimizer.zero_grad()
                loss.backward()
                self.optimizer.step()
                batch_loss.append(loss.item())
            epoch_loss.append(sum(batch_loss) / len(batch_loss))
        return self.net.state_dict(), sum(epoch_loss) / len(epoch_loss)
예제 #2
0
            #30 MALICIOUS
            w_locals_30.append(copy.deepcopy(w30))
            loss_locals_30.append(copy.deepcopy(loss30))

        # update global weights
        w_glob = FedAvg(w_locals)
        w_glob_1 = FedAvg(w_locals_1)
        w_glob_5 = FedAvg(w_locals_5)
        w_glob_10 = FedAvg(w_locals_10)
        w_glob_15 = FedAvg(w_locals_15)
        w_glob_20 = FedAvg(w_locals_20)
        w_glob_25 = FedAvg(w_locals_25)
        w_glob_30 = FedAvg(w_locals_30)

        # copy weight to net_glob
        net_glob.load_state_dict(w_glob)
        net_glob1.load_state_dict(w_glob_1)
        net_glob5.load_state_dict(w_glob_5)
        net_glob10.load_state_dict(w_glob_10)
        net_glob15.load_state_dict(w_glob_15)
        net_glob20.load_state_dict(w_glob_20)
        net_glob25.load_state_dict(w_glob_25)
        net_glob30.load_state_dict(w_glob_30)

        # print loss
        loss_avg = sum(loss_locals) / len(loss_locals)
        loss_avg_1 = sum(loss_locals_1) / len(loss_locals_1)
        loss_avg_5 = sum(loss_locals_5) / len(loss_locals_5)
        loss_avg_10 = sum(loss_locals_10) / len(loss_locals_10)
        loss_avg_15 = sum(loss_locals_15) / len(loss_locals_15)
        loss_avg_20 = sum(loss_locals_20) / len(loss_locals_20)
예제 #3
0
            w_locals_30.append(copy.deepcopy(w30))
            loss_locals_30.append(copy.deepcopy(loss30))

        # update global weights
        w_glob = FedAvg(w_locals)
        w_glob_1 = FedAvg(w_locals_1)
        w_glob_5 = FedAvg(w_locals_5)
        w_glob_10 = FedAvg(w_locals_10)
        w_glob_15 = FedAvg(w_locals_15)
        w_glob_20 = FedAvg(w_locals_20)
        w_glob_25 = FedAvg(w_locals_25)
        w_glob_30 = FedAvg(w_locals_30)

        # copy weight to net_glob
        net_glob.load_state_dict(w_glob)
        net_glob1.load_state_dict(w_glob_1)
        net_glob5.load_state_dict(w_glob_5)
        net_glob10.load_state_dict(w_glob_10)
        net_glob15.load_state_dict(w_glob_15)
        net_glob20.load_state_dict(w_glob_20)
        net_glob25.load_state_dict(w_glob_25)
        net_glob30.load_state_dict(w_glob_30)

        # print loss
        loss_avg = sum(loss_locals) / len(loss_locals)
        loss_avg_1 = sum(loss_locals_1) / len(loss_locals_1)
        loss_avg_5 = sum(loss_locals_5) / len(loss_locals_5)
        loss_avg_10 = sum(loss_locals_10) / len(loss_locals_10)
        loss_avg_15 = sum(loss_locals_15) / len(loss_locals_15)
        loss_avg_20 = sum(loss_locals_20) / len(loss_locals_20)
        loss_avg_25 = sum(loss_locals_25) / len(loss_locals_25)

            #30 MALICIOUS
            w_locals_10.append(copy.deepcopy(w10))
            loss_locals_10.append(copy.deepcopy(loss10))

        # update global weights
        w_glob = FedAvg(w_locals)
        w_glob1 = FedAvg(w_locals_1)
        w_glob5 = FedAvg(w_locals_5)
        w_glob7 = FedAvg(w_locals_7)
        w_glob10 = FedAvg(w_locals_10)

        # copy weight to net_glob
        net_glob.load_state_dict(w_glob)
        net_glob1.load_state_dict(w_glob1)
        net_glob5.load_state_dict(w_glob5)
        net_glob7.load_state_dict(w_glob7)
        net_glob10.load_state_dict(w_glob10)

        # print loss
        loss_avg = sum(loss_locals) / len(loss_locals)
        loss_avg_1 = sum(loss_locals_1) / len(loss_locals_1)
        loss_avg_5 = sum(loss_locals_5) / len(loss_locals_5)
        loss_avg_7 = sum(loss_locals_7) / len(loss_locals_7)
        loss_avg_10 = sum(loss_locals_10) / len(loss_locals_10)


        print('NO ATTACK ---> Round {:3d}, Average loss {:.3f}'.format(iter, loss_avg))
        print('C1 ATTACK ---> Round {:3d}, Average loss {:.3f}'.format(iter, loss_avg_1))
        print('C5 ATTACK ---> Round {:3d}, Average loss {:.3f}'.format(iter, loss_avg_5))
예제 #5
0
def main_worker(gpu, ngpus_per_node, args):
    print("gpu:", gpu)
    args.gpu = gpu
    if args.rank == 0:  #(第一台服务器只有三台GPU,需要特殊处理)
        newrank = args.rank * ngpus_per_node + gpu
    else:
        newrank = args.rank * ngpus_per_node + gpu - 1
    #初始化,使用tcp方式进行通信
    print("begin init")
    dist.init_process_group(init_method=args.init_method,
                            backend="nccl",
                            world_size=args.world_size,
                            rank=newrank)
    print("end init")

    #建立通信group,rank=0作为server,用broadcast模拟send和rec,需要server和每个client建立group
    group = []
    for i in range(1, args.world_size):
        group.append(dist.new_group([0, i]))
    allgroup = dist.new_group([i for i in range(args.world_size)])

    if newrank == 0:
        """ server"""

        print("使用{}号服务器的第{}块GPU作为server".format(args.rank, gpu))

        #在模型训练期间,server只负责整合参数并分发,不参与任何计算
        #设置cpu
        args.device = torch.device(
            'cuda:{}'.format(args.gpu)
            if torch.cuda.is_available() and args.gpu != -1 else 'cpu')

        net = CNNMnist().to(args.device)
        w_avg = copy.deepcopy(net.state_dict())
        for j in range(args.epochs):
            if j == args.epochs - 1:
                for i in w_avg.keys():
                    temp = w_avg[i].to(args.device)
                    w_avg[i] = average_gradients(temp, group, allgroup)
            else:
                for i in w_avg.keys():
                    temp = w_avg[i].to(args.device)
                    average_gradients(temp, group, allgroup)
        torch.save(w_avg, 'w_wag')
        net.load_state_dict(w_avg)
        #加载测试数据
        trans_mnist = transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize((0.1307, ), (0.3081, ))
        ])
        dataset_test = datasets.MNIST('data/',
                                      train=False,
                                      download=True,
                                      transform=trans_mnist)
        test_set = torch.utils.data.DataLoader(dataset_test,
                                               batch_size=args.bs)
        test_accuracy, test_loss = test(net, test_set, args)
        print("Testing accuracy: {:.2f}".format(test_accuracy))
        print("Testing loss: {:.2f}".format(test_loss))

    else:
        """clents"""

        print("使用{}号服务器的第{}块GPU作为第{}个client".format(args.rank, gpu, newrank))

        #设置gpu
        args.device = torch.device(
            'cuda:{}'.format(args.gpu)
            if torch.cuda.is_available() and args.gpu != -1 else 'cpu')

        print("begin train...")
        net = CNNMnist().to(args.device)
        print(net)
        data = torch.load("data/distributed/data_of_client{}".format(newrank))
        bsz = 64
        train_set = torch.utils.data.DataLoader(data, batch_size=bsz)

        optimizer = torch.optim.SGD(net.parameters(), lr=args.lr, momentum=0.5)
        num_batches = ceil(len(train_set.dataset) / float(bsz))
        start = time.time()
        for epoch in range(args.epochs):
            for iter in range(3):
                epoch_loss = 0.0
                for data, target in train_set:
                    data, target = data.to(args.device), target.to(args.device)
                    data, target = Variable(data), Variable(target)
                    optimizer.zero_grad()
                    output = net(data)
                    loss = F.nll_loss(output, target)
                    epoch_loss += loss.item()
                    loss.backward()
                    optimizer.step()
                if iter == 3 - 1:
                    print('Rank ', dist.get_rank(), ', epoch ', epoch, ': ',
                          epoch_loss / num_batches)
            """federated learning"""
            w_avg = copy.deepcopy(net.state_dict())

            for k in w_avg.keys():
                print("k:", k)
                temp = average_gradients(w_avg[k].to(args.device), group,
                                         allgroup)
                w_avg[k] = temp
            net.load_state_dict(w_avg)

        end = time.time()
        print(" training time:{}".format((end - start)))

        train_accuracy, train_loss = test(net, train_set, args)
        print("Training accuracy: {:.2f}".format(train_accuracy))
        print("Training loss: {:.2f}".format(train_loss))
예제 #6
0
def main_worker(gpu, ngpus_per_node, args):
    print("gpu:", gpu)
    args.gpu = gpu
    if args.rank == 0:  #(第一台服务器只有三台GPU,需要特殊处理)
        newrank = args.rank * ngpus_per_node + gpu
    else:
        newrank = args.rank * ngpus_per_node + gpu - 1
    #初始化,使用tcp方式进行通信
    dist.init_process_group(init_method=args.init_method,
                            backend="nccl",
                            world_size=args.world_size,
                            rank=newrank)

    #建立通信group,rank=0作为server,用broadcast模拟send和rec,需要server和每个client建立group
    group = []
    for i in range(1, args.world_size):
        group.append(dist.new_group([0, i]))
    allgroup = dist.new_group([i for i in range(args.world_size)])

    if newrank == 0:
        """ server"""

        print("{}号服务器的第{}块GPU作为server".format(args.rank, gpu))

        #在模型训练期间,server只负责整合参数并分发,不参与任何计算
        #设置cpu
        args.device = torch.device(
            'cuda:{}'.format(args.gpu)
            if torch.cuda.is_available() and args.gpu != -1 else 'cpu')

        #加载测试数据
        trans_mnist = transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize((0.1307, ), (0.3081, ))
        ])
        dataset_test = datasets.MNIST('data/',
                                      train=False,
                                      download=True,
                                      transform=trans_mnist)
        test_set = torch.utils.data.DataLoader(dataset_test,
                                               batch_size=args.bs)
        """calculate influence function"""
        model = CNNMnist().to(args.device)
        model.load_state_dict(torch.load('w_wag'))

        test_id = 0  #选择的test数据id
        data, target = test_set.dataset[test_id]
        data = test_set.collate_fn([data])
        target = test_set.collate_fn([target])

        print("begin grad")
        grad_test = grad_z(data, target, model, gpu, create_graph=False)  #v初始值
        print("end grad")
        v = grad_test
        s_test = []
        """server与client交互计算s_test"""
        for i in range(args.world_size - 1):
            #id_client=random.randint(1,args.world_size) #选择client
            #向选择的client发送当前v
            print("send v to client:", i + 1)
            for j in v:
                temp = j
                dist.broadcast(src=0, tensor=temp, group=group[i])
            #当client计算完成,从client接收v,准备发给下一个client
            print("rec v from client:", i + 1)
            v_new = copy.deepcopy(v)
            for j in v_new:
                temp = j
                dist.broadcast(src=i + 1, tensor=temp, group=group[i])
            s_test.append(v_new)

#s_test计算结束,将最终s_test发送给全体client
        e_s_test = s_test[0]
        for i in range(1, args.world_size - 1):
            e_s_test = [i + j for i, j in six.moves.zip(e_s_test, s_test[i])]
        for j in e_s_test:
            temp = j
            dist.broadcast(src=0, tensor=temp, group=allgroup)
        """交互结束"""

        #从client接收influence
        print("rec influence")
        allinfluence = []
        influence = torch.tensor([i for i in range(4285)], dtype=torch.float32)
        influence = influence.to(args.device)

        for i in range(args.world_size - 1):
            dist.broadcast(src=i + 1, tensor=influence, group=group[i])
            temp = copy.deepcopy(influence)
            allinfluence.append(temp)
        torch.save(allinfluence, 'influence')
    else:
        """clents"""

        print("{}号服务器的第{}号GPU作为第{}个client".format(args.rank, gpu, newrank))

        #设置gpu
        args.device = torch.device(
            'cuda:{}'.format(args.gpu)
            if torch.cuda.is_available() and args.gpu != -1 else 'cpu')
        #加载训练数据
        data = torch.load("data/distributed/data_of_client{}".format(newrank))
        bsz = 64
        train_set = torch.utils.data.DataLoader(data, batch_size=bsz)
        model = CNNMnist().to(args.device)
        model.load_state_dict(torch.load('w_wag'))  #加载模型
        data, target = train_set.dataset[0]
        data = train_set.collate_fn([data])
        target = train_set.collate_fn([target])
        grad_v = grad_z(data, target, model, gpu=gpu)
        v = grad_v
        """calculate influence function"""
        v_new = []
        #从server接收v
        """ 和server交互计算s_test,可以循环迭代(当前只进行了一次迭代,没有循环)"""
        for i in v:
            temp = i
            dist.broadcast(src=0, tensor=temp, group=group[newrank - 1])
            v_new.append(temp)
        s_test = stest(v_new,
                       model,
                       train_set,
                       gpu,
                       damp=0.01,
                       scale=1000.0,
                       repeat=5)  #计算s_test
        #向server发送s_test,进行下一次迭代
        for i in s_test:
            temp = copy.copy(i)
            dist.broadcast(src=newrank, tensor=temp, group=group[newrank - 1])
        #迭代完成后,从server接收最终的s_test,计算influence function
        s_test_fin = []
        for i in s_test:
            temp = copy.copy(i)
            dist.broadcast(src=0, tensor=temp, group=allgroup)
            s_test_fin.append(temp)
        """s_test计算结束,得到最终的s_test_fin,开始计算influence"""
        print("client:", newrank, "calculate influence")
        n = len(train_set.dataset)
        influence = np.array([i for i in range(n)], dtype='float32')
        for i in utility.create_progressbar(len(train_set.dataset),
                                            desc='influence',
                                            start=0):

            #计算grad
            data, target = train_set.dataset[i]
            data = train_set.collate_fn([data])
            target = train_set.collate_fn([target])
            grad_z_vec = grad_z(data, target, model, gpu=gpu)
            #计算influence
            inf_tmp = -sum([
                torch.sum(k * j).data.cpu().numpy()
                for k, j in six.moves.zip(grad_z_vec, s_test_fin)
            ]) / n
            influence[i] = inf_tmp
        influence = torch.tensor(influence).to(args.device)
        #向服务器发送influence
        print("client:", newrank, "send influence to server")
        dist.broadcast(src=newrank, tensor=influence, group=group[newrank - 1])
        print("client:", newrank, "end send influence to server")
예제 #7
0
def main_worker(gpu, ngpus_per_node, args):

    print("gpu:", gpu)
    args.gpu = gpu
    if args.rank == 0:  # (第一台服务器只有三台GPU,需要特殊处理)
        newrank = args.rank * ngpus_per_node + gpu
    else:
        newrank = args.rank * ngpus_per_node + gpu-1
    # 初始化,使用tcp方式进行通信
    dist.init_process_group(init_method=args.init_method, backend="nccl", world_size=args.world_size, rank=newrank)

    # 建立通信group,rank=0作为server,用broadcast模拟send和rec,需要server和每个client建立group
    group = []
    for i in range(1, args.world_size):
        group.append(dist.new_group([0, i]))
    allgroup = dist.new_group([i for i in range(args.world_size)])

    if newrank == 0:
        """ server"""

        print("{}号服务器的第{}块GPU作为server".format(args.rank, gpu))

        # 在模型训练期间,server只负责整合参数并分发,不参与任何计算
        # 设置cpu
        args.device = torch.device(
            'cuda:{}'.format(args.gpu) if torch.cuda.is_available() and args.gpu != -1 else 'cpu')

        # 加载测试数据
        trans_mnist = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
        dataset_test = datasets.MNIST('data/', train=False, download=True, transform=trans_mnist)
        test_set = torch.utils.data.DataLoader(dataset_test, batch_size=args.bs)

        """calculate influence function"""
        model = CNNMnist().to(args.device)
        model.load_state_dict(torch.load('w_wag'))

        test_id = 0  # 选择的test数据id
        data, target = test_set.dataset[test_id]
        data = test_set.collate_fn([data])
        target = test_set.collate_fn([target])

        print("begin grad")
        grad_test = grad_z(data, target, model, gpu, create_graph=False)  # grad_test
        print("end grad")
        v = grad_test


        """server与client交互计算s_test(采用rka算法)"""
        #计算模型总参数
        num_parameters=0
        for i in list(model.parameters()):
            # 首先求出每个tensor中所含参数的个数
            temp = 1
            for j in i.size():
                temp *= j
            num_parameters+=temp
        # 向client发送grad_test
        for i in range(args.world_size - 1):
            print("send grad_test to client:", i+1)
            for j in v:
                temp = j
                dist.broadcast(src=0, tensor=temp, group=group[i])

        for k in range(args.num_sample_rka):

            #向client发送采样id
            id=torch.tensor(random.randint(0,num_parameters-1)).to(args.device)
            for i in range(args.world_size-1):
                dist.broadcast(src=0,tensor=id,group=group[i])

            # 从server接收二阶导
            sec_grad = []
            second_grad = [torch.zeros(list(model.parameters())[i].size()).to(args.device) for i in
                           range(len(list(model.parameters())))]
            for i in range(args.world_size - 1):
                temp = copy.deepcopy(second_grad)
                for j in temp:
                    dist.broadcast(src=i + 1, tensor=j, group=group[i])
                sec_grad.append(temp)

            # 整合二阶导,然后分发给client
            e_second_grad = sec_grad[0]
            for i in range(1, args.world_size - 1):
                e_second_grad = [i + j for i, j in six.moves.zip(e_second_grad, sec_grad[i])]
            e_second_grad = [i / (args.world_size - 1) for i in e_second_grad]
            for j in e_second_grad:
                temp = j
                dist.broadcast(src=0, tensor=temp, group=allgroup)
        """交互结束"""

        # 从client接收influence
        print("rec influence")
        allinfluence = []
        influence = torch.tensor([i for i in range(4285)], dtype=torch.float32)
        influence = influence.to(args.device)

        for i in range(args.world_size - 1):
            dist.broadcast(src=i + 1, tensor=influence, group=group[i])
            temp = copy.deepcopy(influence)
            allinfluence.append(temp)
        torch.save(allinfluence, 'influence/influence')


    else:
        """clents"""

        print("{}号服务器的第{}号GPU作为第{}个client".format(args.rank, gpu, newrank))

        # 设置gpu
        args.device = torch.device(
            'cuda:{}'.format(args.gpu) if torch.cuda.is_available() and args.gpu != -1 else 'cpu')
        # 加载训练数据
        data = torch.load("data/distributedData/data_of_client{}".format(newrank))
        bsz = 64
        train_set = torch.utils.data.DataLoader(data, batch_size=bsz)
        model = CNNMnist().to(args.device)
        model.load_state_dict(torch.load('w_wag'))  # 加载模型
        data, target = train_set.dataset[0]
        data = train_set.collate_fn([data])
        target = train_set.collate_fn([target])
        grad_v = grad_z(data, target, model, gpu=gpu,create_graph=False)
        grad_test = copy.deepcopy(grad_v)

        """calculate influence function"""

        """ 和server交互计算s_test,可以循环迭代(采用rka算法)"""

        # 从server接收grad_test
        for i in grad_test:
            dist.broadcast(src=0, tensor=i, group=group[newrank - 1])

        stest = copy.deepcopy(grad_test)
        for k in range(args.num_sample_rka):
            #从server接收采样id,计算二阶导
            id=torch.tensor([0]).to(args.device).to(args.device)
            dist.broadcast(src=0,tensor=id,group=group[newrank - 1])
            idt= id.item()
            second_grad=hessian(model,train_set,idt,gpu=args.gpu)

            #向server发送二阶导
            for i in second_grad:
                temp = i
                dist.broadcast(src=newrank, tensor=temp, group=group[newrank - 1])

            # 从server接收最终的二阶导
            for i in second_grad:
                temp = i
                dist.broadcast(src=0, tensor=temp, group=allgroup)
            # 使用rka算法计算stest
            stest = rka(stest, second_grad, grad_test)

            s_test_fin = stest
            """"s_test计算结束,得到最终的s_test_fin,开始计算influence"""

        print("client:", newrank, "calculate influence")
        n = len(train_set.dataset)
        influence = np.array([i for i in range(n)], dtype='float32')
        for i in utility.create_progressbar(len(train_set.dataset), desc='influence', start=0):
            # 计算grad
            data, target = train_set.dataset[i]
            data = train_set.collate_fn([data])
            target = train_set.collate_fn([target])
            grad_z_vec = grad_z(data, target, model, gpu=gpu)
            # 计算influence
            inf_tmp = -sum(
                [torch.sum(k * j).data.cpu().numpy() for k, j in six.moves.zip(grad_z_vec, s_test_fin)]) / n
            influence[i] = inf_tmp
        influence = torch.tensor(influence).to(args.device)
        # 向服务器发送influence
        print("client:", newrank, "send influence to server")
        dist.broadcast(src=newrank, tensor=influence, group=group[newrank - 1])
        print("client:", newrank, "end send influence to server")
            loss_locals_30.append(copy.deepcopy(loss30))

        # update global weights
        w_glob = FedAvg(w_locals)
        w_glob1 = FedAvg(w_locals_1)
        w_glob5 = FedAvg(w_locals_5)
        w_glob10 = FedAvg(w_locals_10)
        w_glob15 = FedAvg(w_locals_15)
        w_glob20 = FedAvg(w_locals_20)
        w_glob25 = FedAvg(w_locals_25)
        w_glob30 = FedAvg(w_locals_30)


        # copy weight to net_glob
        net_glob.load_state_dict(w_glob)
        net_glob1.load_state_dict(w_glob1)
        net_glob5.load_state_dict(w_glob5)
        net_glob10.load_state_dict(w_glob10)
        net_glob15.load_state_dict(w_glob15)
        net_glob20.load_state_dict(w_glob20)
        net_glob25.load_state_dict(w_glob25)
        net_glob30.load_state_dict(w_glob30)

        # print loss
        loss_avg = sum(loss_locals) / len(loss_locals)
        loss_avg_1 = sum(loss_locals_1) / len(loss_locals_1)
        loss_avg_5 = sum(loss_locals_5) / len(loss_locals_5)
        loss_avg_10 = sum(loss_locals_10) / len(loss_locals_10)
        loss_avg_15 = sum(loss_locals_15) / len(loss_locals_15)
        loss_avg_20 = sum(loss_locals_20) / len(loss_locals_20)
        loss_avg_25 = sum(loss_locals_25) / len(loss_locals_25)
예제 #9
0
class Client():
    def __init__(self,
                 args,
                 dataset=None,
                 idxs=None,
                 w=None,
                 C=0.5,
                 sigma=0.05):
        self.args = args
        self.loss_func = nn.CrossEntropyLoss()
        self.ldr_train = DataLoader(DatasetSplit(dataset, idxs),
                                    batch_size=self.args.local_bs,
                                    shuffle=True)
        self.model = CNNMnist(args=args).to(args.device)
        self.model.load_state_dict(w)
        self.C = C
        self.sigma = sigma
        if self.args.mode == 'Paillier':
            self.pub = pub
            self.priv = priv

    def train(self):
        w_old = copy.deepcopy(self.model.state_dict())
        net = copy.deepcopy(self.model)

        net.train()

        #train and update
        optimizer = torch.optim.SGD(net.parameters(),
                                    lr=self.args.lr,
                                    momentum=self.args.momentum)
        for iter in range(self.args.local_ep):
            batch_loss = []
            for batch_idx, (images, labels) in enumerate(self.ldr_train):
                images, labels = images.to(self.args.device), labels.to(
                    self.args.device)
                net.zero_grad()
                log_probs = net(images)
                loss = self.loss_func(log_probs, labels)
                loss.backward()
                optimizer.step()
                batch_loss.append(loss.item())

        w_new = net.state_dict()

        update_w = {}
        if self.args.mode == 'plain':
            for k in w_new.keys():
                update_w[k] = w_new[k] - w_old[k]
        # 1. part one
        #     DP mechanism
        elif self.args.mode == 'DP':
            for k in w_new.keys():
                # calculate update_w
                update_w[k] = w_new[k] - w_old[k]
                # clip the update
                update_w[k] = update_w[k] / max(
                    1,
                    torch.norm(update_w[k], 2) / self.C)
                # add noise ,cause update_w might reveal user's data also ,we should add noise before send to server
                update_w[k] += np.random.normal(0.0, self.sigma**2 * self.C**2)
        # 2. part two
        #     Paillier enc
        elif self.args.mode == 'Paillier':
            print(len(w_new.keys()))
            for k in w_new.keys():
                print("start  ", k, flush=True)
                update_w[k] = w_new[k] - w_old[k]
                update_w_list = update_w[k].view(-1).cpu().tolist()
                for iter, w in enumerate(update_w_list):
                    update_w_list[iter] = self.pub.encrypt(w)
                update_w[k] = update_w_list
                print("end ", flush=True)
        else:
            exit()
        return update_w, sum(batch_loss) / len(batch_loss)

    def update(self, w_glob):
        if self.args.mode == 'plain':
            self.model.load_state_dict(w_glob)
        elif self.args.mode == 'DP':
            self.model.load_state_dict(w_glob)
        elif self.args.mode == 'Paillier':
            w_glob_ciph = copy.deepcopy(w_glob)
            for k in w_glob_ciph.keys():
                for iter, item in enumerate(w_glob_ciph[k]):
                    w_glob_ciph[k][iter] = self.priv.decrypt(item)
                shape = list(self.model.state_dict()[k].size())
                w_glob_ciph[k] = torch.FloatTensor(w_glob_ciph[k]).to(
                    self.args.device).view(*shape)
                self.model.state_dict()[k] += w_glob_ciph[k]
        else:
            exit()
            #5 MALICIOUS
            w_locals_5.append(copy.deepcopy(w5))
            loss_locals_5.append(copy.deepcopy(loss5))

            #10 MALICIOUS
            w_locals_10.append(copy.deepcopy(w10))
            loss_locals_10.append(copy.deepcopy(loss10))

        # update global weights
        w_glob = FedAvg(w_locals)
        w_glob_5 = FedAvg(w_locals_5)
        w_glob_10 = FedAvg(w_locals_10)

        # copy weight to net_glob
        net_glob.load_state_dict(w_glob)
        net_glob5.load_state_dict(w_glob_5)
        net_glob10.load_state_dict(w_glob_10)

        # print loss
        loss_avg = sum(loss_locals) / len(loss_locals)
        loss_avg_5 = sum(loss_locals_5) / len(loss_locals_5)
        loss_avg_10 = sum(loss_locals_10) / len(loss_locals_10)

        non_malicious_structure[iter][0] = loss_avg
        non_malicious_structure5[iter][0] = loss_avg_5
        non_malicious_structure10[iter][0] = loss_avg_10

        malicious_structure5[iter][0] = loss_avg_5
        malicious_structure10[iter][0] = loss_avg_10

        print('NO ATTACK ---> Round {:3d}, Average loss {:.3f}'.format(
예제 #11
0
class Server():
    def __init__(self, args, w):
        self.args = args
        self.clients_update_w = []
        self.clients_loss = []
        self.model = CNNMnist(args=args).to(args.device)
        self.model.load_state_dict(w)

    def FedAvg(self):
        # 1. part one
        #     DP mechanism
        # cause we choose to add noise at client end,the fedavg should be the same as plain
        if self.args.mode == 'plain' or self.args.mode == 'DP':
            update_w_avg = copy.deepcopy(self.clients_update_w[0])
            for k in update_w_avg.keys():
                for i in range(1, len(self.clients_update_w)):
                    update_w_avg[k] += self.clients_update_w[i][k]
                update_w_avg[k] = torch.div(update_w_avg[k],
                                            len(self.clients_update_w))
                self.model.state_dict()[k] += update_w_avg[k]
            return copy.deepcopy(self.model.state_dict()), sum(
                self.clients_loss) / len(self.clients_loss)

        # 2. part two
        #     Paillier add
        elif self.args.mode == 'Paillier':
            update_w_avg = copy.deepcopy(self.clients_update_w[0])
            for k in update_w_avg.keys():
                client_num = len(self.clients_update_w)
                for i in range(1, client_num):
                    for iter in range(len(update_w_avg[k])):
                        update_w_avg[k][iter] += self.clients_update_w[i][k][
                            iter]
                for iter in range(len(update_w_avg[k])):
                    update_w_avg[k][iter] /= client_num
            return update_w_avg, sum(self.clients_loss) / len(
                self.clients_loss)
        else:
            exit()

    def test(self, datatest):
        self.model.eval()

        # testing
        test_loss = 0
        correct = 0
        data_loader = DataLoader(datatest, batch_size=self.args.bs)
        for idx, (data, target) in enumerate(data_loader):
            if self.args.gpu != -1:
                data, target = data.cuda(), target.cuda()
            log_probs = self.model(data)

            # sum up batch loss
            test_loss += F.cross_entropy(log_probs, target,
                                         reduction='sum').item()

            # get the index of the max log-probability
            y_pred = log_probs.data.max(1, keepdim=True)[1]
            correct += y_pred.eq(
                target.data.view_as(y_pred)).long().cpu().sum()

        test_loss /= len(data_loader.dataset)
        accuracy = 100.00 * correct / len(data_loader.dataset)
        return accuracy, test_loss