├── README.md ├── 密码学自选题报告.pdf ├── Result ├── test0 │ ├── Figure_1.png │ ├── 扼要总结.txt │ ├── config0.json │ └── 对照组weight&loss&accuracy.txt ├── test1 │ ├── Figure_1.png │ ├── config1.json │ └── result.txt ├── 改变正则化参数lambda对模型accuracy的影响.png └── 改变隐私参数epsilon对模型accuracy的影响.jpg ├── Code ├── config.json ├── main.py ├── utils.py └── model.py └── Tutorials └── src_explain.ipynb /README.md: -------------------------------------------------------------------------------- 1 | # VFL_with_LDP 2 | 联邦学习项目:在breast cancer数据集上实现了纵向联邦学习与标签差分隐私结合 3 | -------------------------------------------------------------------------------- /密码学自选题报告.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unakar/VFL_with_LDP/HEAD/密码学自选题报告.pdf -------------------------------------------------------------------------------- /Result/test0/Figure_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unakar/VFL_with_LDP/HEAD/Result/test0/Figure_1.png -------------------------------------------------------------------------------- /Result/test1/Figure_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unakar/VFL_with_LDP/HEAD/Result/test1/Figure_1.png -------------------------------------------------------------------------------- /Result/test0/扼要总结.txt: -------------------------------------------------------------------------------- 1 | 在隐私参数设置为0时的训练结果: 2 | 最终准确率(30轮): 3 | yA_accuracy:0.916083916083916 4 | yB_accuracy:0.8601398601398601 -------------------------------------------------------------------------------- /Result/改变正则化参数lambda对模型accuracy的影响.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unakar/VFL_with_LDP/HEAD/Result/改变正则化参数lambda对模型accuracy的影响.png -------------------------------------------------------------------------------- /Result/改变隐私参数epsilon对模型accuracy的影响.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unakar/VFL_with_LDP/HEAD/Result/改变隐私参数epsilon对模型accuracy的影响.jpg -------------------------------------------------------------------------------- /Code/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "n_iter": 30, 3 | "lambda": 0.1, 4 | "lr": 0.005, 5 | "A_idx": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], 6 | "B_idx": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 7 | "epsilon": 8.0 8 | } 9 | -------------------------------------------------------------------------------- /Result/test0/config0.json: -------------------------------------------------------------------------------- 1 | { 2 | "n_iter": 30, 3 | "lambda": 0.1, 4 | "lr": 0.005, 5 | "A_idx": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], 6 | "B_idx": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 7 | "epsilon": 0.0 8 | } 9 | -------------------------------------------------------------------------------- /Result/test1/config1.json: -------------------------------------------------------------------------------- 1 | { 2 | "n_iter": 30, 3 | "lambda": 2, 4 | "lr": 0.005, 5 | "A_idx": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], 6 | "B_idx": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 7 | "epsilon": 4.0 8 | } 9 | -------------------------------------------------------------------------------- /Code/main.py: -------------------------------------------------------------------------------- 1 | import json 2 | import numpy as np 3 | from model import * 4 | from utils import * 5 | pred1,pred2=[],[] 6 | 7 | 8 | 9 | def model_training(X, y, X_test, y_test, config): 10 | 11 | XA, XB, XA_test, XB_test = vertically_partition_data(X, X_test, config['A_idx'], config['B_idx']) 12 | print('XA:',XA.shape, ' XB:',XB.shape) 13 | 14 | ## 各参与方的初始化 15 | Guest_A = GuestA(XA, config) 16 | print("Guest_A successfully initialized.") 17 | Host_B = HostB(XB, y, config) 18 | print("Host_B successfully initialized.") 19 | Sever_C = SeverC(XA.shape, XB.shape, config) 20 | print("Sever_C successfully initialized.") 21 | 22 | ## 各参与方之间连接的建立 23 | Guest_A.connect("B", Host_B) 24 | Guest_A.connect("C", Sever_C) 25 | Host_B.connect("A", Guest_A) 26 | Host_B.connect("C", Sever_C) 27 | Sever_C.connect("A", Guest_A) 28 | Sever_C.connect("B", Host_B) 29 | 30 | ## 训练 31 | accuracy_A, accuracy_B = [],[] 32 | Host_B.task_0() 33 | for i in range(1,config['n_iter']+1): 34 | print(f"**********epoch{i}**********") 35 | Sever_C.task_1("A", "B") 36 | Guest_A.task_1("B") 37 | if i%5 == 0: 38 | Host_B.task_flipback("A") 39 | else: 40 | Host_B.task_1("A") 41 | Guest_A.task_2("C") 42 | Host_B.task_2("C") 43 | Sever_C.task_2("A", "B") 44 | Guest_A.task_3() 45 | Host_B.task_3() 46 | 47 | ### A做预测 48 | yA_pred = predict_sigmoid(Guest_A.weights, XA_test, np.zeros_like(XA_test.shape[0])) 49 | yA_accuracy, yA_precision, yA_recall, yA_f1 = calculate_metrics(y_test, yA_pred) 50 | print(f"yA_accuracy:{yA_accuracy}, yA_precision:{yA_precision}, yA_recall:{yA_recall}, yA_f1:{yA_f1}") 51 | accuracy_A.append(yA_accuracy) 52 | 53 | ### B做预测 54 | yB_pred = predict_sigmoid(Host_B.weights, XB_test, np.zeros_like(XB_test.shape[0])) 55 | yB_accuracy, yB_precision, yB_recall, yB_f1 = calculate_metrics(y_test, yB_pred) 56 | print(f"yB_accuracy:{yB_accuracy}, yB_precision:{yB_precision}, yB_recall:{yB_recall}, yB_f1:{yB_f1}") 57 | accuracy_B.append(yB_accuracy) 58 | 59 | print("All process done.") 60 | 61 | loss_acc_fig(Sever_C.loss, accuracy_A, Sever_C.loss, accuracy_B) 62 | 63 | return True 64 | 65 | X, y, X_test, y_test = load_data() 66 | config = json.load(open('.\Code\config.json')) 67 | model_training(X, y, X_test, y_test, config) -------------------------------------------------------------------------------- /Code/utils.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | from sklearn.preprocessing import StandardScaler 4 | from sklearn.datasets import load_breast_cancer 5 | from sklearn.model_selection import train_test_split 6 | from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score 7 | 8 | def load_data(): 9 | breast = load_breast_cancer() 10 | X_train, X_test, y_train, y_test = train_test_split(breast.data, breast.target, random_state=1) 11 | 12 | std = StandardScaler() 13 | X_train = std.fit_transform(X_train) 14 | X_test = std.transform(X_test) 15 | return X_train, y_train, X_test, y_test 16 | 17 | def vertically_partition_data(X, X_test, A_idx, B_idx): 18 | XA = X[:, A_idx] 19 | XB = X[:, B_idx] 20 | XB = np.c_[np.ones(X.shape[0]), XB] 21 | XA_test = X_test[:, A_idx] 22 | XB_test = X_test[:, B_idx] 23 | XB_test = np.c_[np.ones(XB_test.shape[0]), XB_test] 24 | return XA, XB, XA_test, XB_test 25 | 26 | # 计算accuracy... 27 | def calculate_metrics(y_true, y_pred): 28 | """ 29 | Calculate accuracy, precision, recall and F1 score 30 | :param y_true: true labels 31 | :param y_pred: predicted labels 32 | :return: accuracy, precision, recall, F1 score 33 | """ 34 | accuracy = accuracy_score(y_true, y_pred) 35 | precision = precision_score(y_true, y_pred) 36 | recall = recall_score(y_true, y_pred) 37 | f1 = f1_score(y_true, y_pred) 38 | return accuracy, precision, recall, f1 39 | 40 | # sigmoid 41 | def predict_sigmoid(weights, X_test, b): 42 | z = np.dot(weights, X_test.T) + b 43 | y_pred = 1/(1+np.exp(-z)) 44 | y_pred[y_pred > 0.5] = 1 45 | y_pred[y_pred <= 0.5]= 0 46 | return y_pred 47 | 48 | def loss_acc_fig(loss_A, accuracy_A, loss_B, accuracy_B): 49 | fig = plt.figure(figsize=(12, 6)) 50 | x=[i+1 for i in range(len(loss_A))] 51 | plt.subplot(1, 2, 1) 52 | l1=plt.plot(x,loss_A,'r--',label='loss_A') 53 | l2=plt.plot(x,accuracy_A,'g--',label='accuracy_A') 54 | plt.plot(x,loss_A,'ro-',x,accuracy_A,'g+-') 55 | plt.title('Training and validation accuracy') 56 | plt.xlabel('n_iter') 57 | plt.ylabel('loss_A/accuracy_A') 58 | plt.legend() 59 | 60 | plt.subplot(1, 2, 2) 61 | l3=plt.plot(x,loss_B,'r--',label='loss_B') 62 | l4=plt.plot(x,accuracy_B,'g--',label='accuracy_B') 63 | plt.plot(x,loss_B,'ro-',x,accuracy_B,'g+-') 64 | plt.title('Training and validation accuracy') 65 | plt.xlabel('n_iter') 66 | plt.ylabel('loss_B/accuracy_B') 67 | plt.legend() 68 | plt.show() -------------------------------------------------------------------------------- /Code/model.py: -------------------------------------------------------------------------------- 1 | from phe import paillier 2 | from utils import * 3 | import math 4 | import numpy as np 5 | import json 6 | 7 | config = json.load(open('.\Code\config.json')) 8 | 9 | 10 | class Client: 11 | def __init__(self, config): 12 | self.config = config 13 | self.data = {} 14 | self.other_client = {} 15 | 16 | def connect(self, other, target_client): 17 | self.other_client[other] = target_client 18 | 19 | def communicate(self, data, target_client): 20 | target_client.data.update(data) 21 | 22 | class HostB(Client): 23 | def __init__(self, X, y, config): 24 | super().__init__(config) 25 | self.X = X 26 | self.y = y 27 | self.weights = np.random.normal(loc=0,scale=1.0/15,size=X.shape[1]) 28 | self.data = {} 29 | 30 | #flip labels 31 | def flip_labels(self): 32 | flip_prob = 1/(1+math.exp(config['epsilon'])) 33 | num_flips = int(flip_prob * len(self.y)) 34 | flip_indices = np.random.choice(len(self.y), num_flips, replace=False) 35 | self.y[flip_indices] = 1 - self.y[flip_indices] 36 | 37 | 38 | def compute_u_b(self): 39 | WX_b = np.dot(self.X, self.weights) 40 | u_b = 0.25 * WX_b - self.y + 0.5 41 | return WX_b, u_b 42 | 43 | def compute_encrypted_dL_b(self, encrypted_u): 44 | encrypted_dL_b = self.X.T.dot(encrypted_u) + self.config['lambda'] * self.weights 45 | return encrypted_dL_b 46 | 47 | def update_weight(self, dL_b): 48 | self.weights = self.weights - self.config["lr"] * dL_b / len(self.X) 49 | 50 | def task_0(self): 51 | try: 52 | self.flip_labels() 53 | print("Random process of flipping labels is done.") 54 | except Exception as e: 55 | print("Wrong 0 in B: %s" % e) 56 | 57 | ## B: step2 58 | def task_1(self, Guest_A_name): 59 | try: 60 | dt = self.data 61 | assert "public_key" in dt.keys(), "Error: 'public_key' from C in step 1 not successfully received." 62 | public_key = dt['public_key'] 63 | except Exception as e: 64 | print("B step 1 exception: %s" % e) 65 | try: 66 | WX_b, u_b = self.compute_u_b() 67 | encrypted_u_b = np.asarray([public_key.encrypt(x) for x in u_b]) 68 | dt.update({"encrypted_u_b": encrypted_u_b}) 69 | dt.update({"WX_b": WX_b}) 70 | except Exception as e: 71 | print("Wrong 1 in B: %s" % e) 72 | 73 | data_to_A= {"encrypted_u_b": encrypted_u_b} 74 | self.communicate(data_to_A, self.other_client[Guest_A_name]) 75 | 76 | ## B: step3、4 77 | def task_2(self,Sever_C_name): 78 | try: 79 | dt = self.data 80 | assert "encrypted_u_a" in dt.keys(), "Error: 'encrypt_u_a' from A in step 1 not successfully received." 81 | encrypted_u_a = dt['encrypted_u_a'] 82 | encrypted_u = encrypted_u_a + dt['encrypted_u_b'] 83 | encrypted_dL_b = self.compute_encrypted_dL_b(encrypted_u) 84 | mask = np.random.rand(len(encrypted_dL_b)) 85 | encrypted_masked_dL_b = encrypted_dL_b + mask 86 | dt.update({"mask": mask}) 87 | except Exception as e: 88 | print("B step 2 exception: %s" % e) 89 | try: 90 | assert "encrypted_WX_a_square" in dt.keys(), "Error: 'encrypted_WX_a_square' from A in step 1 not successfully received." 91 | encrypted_z = 4*encrypted_u_a + dt['WX_b'] 92 | encrypted_loss = np.sum((0.5-self.y)*encrypted_z + 0.125*dt["encrypted_WX_a_square"] + 0.125*dt["WX_b"] * (encrypted_z+4*encrypted_u_a)) 93 | except Exception as e: 94 | print("B step 2 exception: %s" % e) 95 | data_to_C = {"encrypted_masked_dL_b": encrypted_masked_dL_b, "encrypted_loss": encrypted_loss} 96 | self.communicate(data_to_C, self.other_client[Sever_C_name]) 97 | 98 | ## B: step6 99 | def task_3(self): 100 | try: 101 | dt = self.data 102 | assert "masked_dL_b" in dt.keys(), "Error: 'masked_dL_b' from C in step 2 not successfully received." 103 | masked_dL_b = dt['masked_dL_b'] 104 | dL_b = masked_dL_b - dt['mask'] 105 | self.update_weight(dL_b) 106 | except Exception as e: 107 | print("A step 3 exception: %s" % e) 108 | print(f"B weight: {self.weights}") 109 | return 110 | 111 | 112 | 113 | def task_flipback(self,Guest_A_name): 114 | try: 115 | dt = self.data 116 | assert "public_key" in dt.keys(), "Error: 'public_key' from C in step 1 not successfully received." 117 | public_key = dt['public_key'] 118 | except Exception as e: 119 | print("B step 1 exception: %s" % e) 120 | try: 121 | yB_pred = predict_sigmoid(self.weights, self.X, np.zeros_like(self.X.shape[0])) 122 | #y_dist记为yB_pred和真实的y之间的差距,选出其中差距最大的前2%的样本,将其标签翻转 123 | y_dist = np.abs(yB_pred - self.y) 124 | flip_indices = np.argsort(y_dist)[-int(0.02*len(y_dist)):] 125 | self.y[flip_indices] = 1 - self.y[flip_indices] 126 | 127 | WX_b, u_b = self.compute_u_b() 128 | encrypted_u_b = np.asarray([public_key.encrypt(x) for x in u_b]) 129 | dt.update({"encrypted_u_b": encrypted_u_b}) 130 | dt.update({"WX_b": WX_b}) 131 | except Exception as e: 132 | print("Wrong 1 in B: %s" % e) 133 | 134 | data_to_A= {"encrypted_u_b": encrypted_u_b} 135 | self.communicate(data_to_A, self.other_client[Guest_A_name]) 136 | 137 | 138 | 139 | 140 | class GuestA(Client): 141 | def __init__(self, X, config): 142 | super().__init__(config) 143 | self.X = X 144 | self.weights = np.random.normal(loc=0,scale=1.0/15,size=X.shape[1])# 145 | 146 | def compute_WX_a(self): 147 | WX_a = np.dot(self.X, self.weights) 148 | return WX_a 149 | 150 | ## 加密梯度的计算,对应step4 151 | def compute_encrypted_dL_a(self, encrypted_u): 152 | encrypted_dL_a = self.X.T.dot(encrypted_u) + self.config['lambda'] * self.weights 153 | return encrypted_dL_a 154 | 155 | ##参数的更新 156 | def update_weight(self, dL_a): 157 | self.weights = self.weights - self.config["lr"] * dL_a / len(self.X) 158 | return 159 | 160 | ## A: step2 161 | def task_1(self, Host_B_name): 162 | dt = self.data 163 | assert "public_key" in dt.keys(), "Error: 'public_key' from C in step 1 not successfully received." 164 | public_key = dt['public_key'] 165 | WX_a = self.compute_WX_a() 166 | u_a = 0.25 * WX_a 167 | WX_a_square = WX_a ** 2 168 | encrypted_u_a = np.asarray([public_key.encrypt(x) for x in u_a]) 169 | encrypted_WX_a_square = np.asarray([public_key.encrypt(x) for x in WX_a_square]) 170 | dt.update({"encrypted_u_a": encrypted_u_a}) 171 | data_to_B = {"encrypted_u_a": encrypted_u_a, "encrypted_WX_a_square": encrypted_WX_a_square} 172 | self.communicate(data_to_B, self.other_client[Host_B_name]) 173 | 174 | ## A: step3、4 175 | def task_2(self, Sever_C_name): 176 | dt = self.data 177 | assert "encrypted_u_b" in dt.keys(), "Error: 'encrypted_u_b' from B in step 1 not successfully received." 178 | encrypted_u_b = dt['encrypted_u_b'] 179 | encrypted_u = encrypted_u_b + dt['encrypted_u_a'] 180 | encrypted_dL_a = self.compute_encrypted_dL_a(encrypted_u) 181 | mask = np.random.rand(len(encrypted_dL_a)) 182 | encrypted_masked_dL_a = encrypted_dL_a + mask 183 | dt.update({"mask": mask}) 184 | data_to_C = {'encrypted_masked_dL_a': encrypted_masked_dL_a} 185 | self.communicate(data_to_C, self.other_client[Sever_C_name]) 186 | 187 | ## A: step6 188 | def task_3(self): 189 | dt = self.data 190 | assert "masked_dL_a" in dt.keys(), "Error: 'masked_dL_a' from C in step 2 not successfully received." 191 | masked_dL_a = dt['masked_dL_a'] 192 | dL_a = masked_dL_a - dt['mask'] 193 | self.update_weight(dL_a) 194 | print(f"A weight: {self.weights}") 195 | return 196 | 197 | 198 | 199 | 200 | class SeverC(Client): 201 | 202 | 203 | def __init__(self, A_d_shape, B_d_shape, config): 204 | super().__init__(config) 205 | self.A_data_shape = A_d_shape 206 | self.B_data_shape = B_d_shape 207 | self.public_key = None 208 | self.private_key = None 209 | self.loss = [] 210 | 211 | ## C: step1 212 | def task_1(self, Guest_A_name, Host_B_name): 213 | try: 214 | public_key, private_key = paillier.generate_paillier_keypair() 215 | self.public_key = public_key 216 | self.private_key = private_key 217 | except Exception as e: 218 | print("C step 1 error 1: %s" % e) 219 | 220 | data_to_AB = {"public_key": public_key} 221 | self.communicate(data_to_AB, self.other_client[Guest_A_name]) 222 | self.communicate(data_to_AB, self.other_client[Host_B_name]) 223 | return 224 | 225 | ## C: step5 226 | def task_2(self, Guest_A_name, Host_B_name): 227 | try: 228 | dt = self.data 229 | assert "encrypted_masked_dL_a" in dt.keys() and "encrypted_masked_dL_b" in dt.keys(), "Error: 'masked_dL_a' from A or 'masked_dL_b' from B in step 2 not successfully received." 230 | encrypted_masked_dL_a = dt['encrypted_masked_dL_a'] 231 | encrypted_masked_dL_b = dt['encrypted_masked_dL_b'] 232 | masked_dL_a = np.asarray([self.private_key.decrypt(x) for x in encrypted_masked_dL_a]) 233 | masked_dL_b = np.asarray([self.private_key.decrypt(x) for x in encrypted_masked_dL_b]) 234 | except Exception as e: 235 | print("C step 2 exception: %s" % e) 236 | 237 | try: 238 | assert "encrypted_loss" in dt.keys(), "Error: 'encrypted_loss' from B in step 2 not successfully received." 239 | encrypted_loss = dt['encrypted_loss'] 240 | loss = self.private_key.decrypt(encrypted_loss) / self.A_data_shape[0] + math.log(2) 241 | print("loss: ", loss) 242 | self.loss.append(loss) 243 | except Exception as e: 244 | print("C step 2 exception: %s" % e) 245 | 246 | data_to_A = {"masked_dL_a": masked_dL_a} 247 | data_to_B = {"masked_dL_b": masked_dL_b} 248 | self.communicate(data_to_A, self.other_client[Guest_A_name]) 249 | self.communicate(data_to_B, self.other_client[Host_B_name]) 250 | return -------------------------------------------------------------------------------- /Result/test0/对照组weight&loss&accuracy.txt: -------------------------------------------------------------------------------- 1 | 2 | XA: (426, 20) XB: (426, 11) 3 | Client_A successfully initialized. 4 | Client_B successfully initialized. 5 | Client_C successfully initialized. 6 | ******loss: 0.6037608387777682 ****** 7 | A weight: [-0.06984453 -0.00799791 0.02559916 -0.07659329 0.07793419 0.06904268 8 | -0.04688743 -0.11349752 -0.02453607 0.01437828 -0.07811539 -0.08872718 9 | -0.02905127 0.07172473 0.01050687 -0.00232593 -0.02281954 0.00524317 10 | 0.04201711 0.05393142] 11 | B weight: [ 0.02988837 -0.06218227 0.01894706 0.08519177 0.02366245 0.05364719 12 | -0.03340221 -0.11323235 -0.05946808 0.05295384 -0.06337866] 13 | yA_accuracy:0.7412587412587412, yA_precision:0.8072289156626506, yA_recall:0.7613636363636364, yA_f1:0.783625730994152 14 | yB_accuracy:0.7482517482517482, yB_precision:0.7708333333333334, yB_recall:0.8409090909090909, yB_f1:0.8043478260869567 15 | ******loss: 0.5965714953903103 ****** 16 | A weight: [-0.07086614 -0.00788771 0.02460051 -0.07757676 0.07807285 0.06852534 17 | -0.04729566 -0.11419828 -0.02440516 0.01434817 -0.07968996 -0.08971398 18 | -0.0306348 0.07024703 0.0095348 -0.00359455 -0.02421026 0.00360124 19 | 0.04102573 0.05321209] 20 | B weight: [ 0.03050759 -0.06365401 0.01805757 0.08369825 0.02224893 0.05291593 21 | -0.03460811 -0.11459196 -0.06100529 0.05225896 -0.0632558 ] 22 | yA_accuracy:0.7412587412587412, yA_precision:0.8072289156626506, yA_recall:0.7613636363636364, yA_f1:0.783625730994152 23 | yB_accuracy:0.7622377622377622, yB_precision:0.78125, yB_recall:0.8522727272727273, yB_f1:0.8152173913043479 24 | ******loss: 0.5896094998136769 ****** 25 | A weight: [-0.07186838 -0.00777736 0.02362159 -0.07854082 0.07821059 0.06802178 26 | -0.04769119 -0.11488359 -0.02427377 0.01432438 -0.08124092 -0.09068886 27 | -0.03219405 0.06879249 0.0085748 -0.00484312 -0.02557886 0.00198386 28 | 0.04004603 0.05250418] 29 | B weight: [ 0.03112601 -0.06510279 0.01717992 0.0822283 0.02085839 0.05219694 30 | -0.03579195 -0.11592732 -0.06251731 0.05157579 -0.06313074] 31 | yA_accuracy:0.7412587412587412, yA_precision:0.8072289156626506, yA_recall:0.7613636363636364, yA_f1:0.783625730994152 32 | yB_accuracy:0.7622377622377622, yB_precision:0.78125, yB_recall:0.8522727272727273, yB_f1:0.8152173913043479 33 | ******loss: 0.5828673897927495 ****** 34 | A weight: [-0.07285158 -0.00766689 0.02266207 -0.0794858 0.07834742 0.06753176 35 | -0.04807426 -0.11555372 -0.02414194 0.01430679 -0.08276864 -0.09165201 36 | -0.03372942 0.06736073 0.00762666 -0.00607197 -0.02692569 0.00039062 37 | 0.03907784 0.05180749] 38 | B weight: [ 0.03174365 -0.06652896 0.01631392 0.08078151 0.01949046 0.05149001 39 | -0.03695411 -0.11723886 -0.06400454 0.05090411 -0.06300354] 40 | yA_accuracy:0.7412587412587412, yA_precision:0.8, yA_recall:0.7727272727272727, yA_f1:0.7861271676300577 41 | yB_accuracy:0.7692307692307693, yB_precision:0.7835051546391752, yB_recall:0.8636363636363636, yB_f1:0.8216216216216216 42 | ******loss: 0.5763379498956901 ****** 43 | A weight: [-0.07381606 -0.0075563 0.02172162 -0.08041201 0.07848332 0.06705501 44 | -0.04844511 -0.11620895 -0.02400969 0.01429525 -0.0842735 -0.09260359 45 | -0.0352413 0.06595139 0.0066902 -0.00728143 -0.02825114 -0.00117888 46 | 0.03812097 0.05112183] 47 | B weight: [ 0.03236051 -0.06793291 0.01545938 0.07935753 0.01814477 0.05079493 48 | -0.03809495 -0.11852697 -0.06546741 0.05024373 -0.06287424] 49 | yA_accuracy:0.7552447552447552, yA_precision:0.8192771084337349, yA_recall:0.7727272727272727, yA_f1:0.7953216374269007 50 | yB_accuracy:0.7762237762237763, yB_precision:0.7916666666666666, yB_recall:0.8636363636363636, yB_f1:0.8260869565217391 51 | ******loss: 0.5700142033325121 ****** 52 | A weight: [-0.07476214 -0.00744562 0.02079992 -0.08131978 0.07861831 0.0665913 53 | -0.04880396 -0.11684955 -0.02387706 0.01428964 -0.08575587 -0.0935438 54 | -0.03673008 0.06456409 0.00576522 -0.00847183 -0.02955554 -0.00272503 55 | 0.03717524 0.05044702] 56 | B weight: [ 0.03297657 -0.06931499 0.01461613 0.07795597 0.01682095 0.0501115 57 | -0.03921484 -0.11979205 -0.06690632 0.04959446 -0.06274291] 58 | yA_accuracy:0.7622377622377622, yA_precision:0.8214285714285714, yA_recall:0.7840909090909091, yA_f1:0.8023255813953489 59 | yB_accuracy:0.7832167832167832, yB_precision:0.8, yB_recall:0.8636363636363636, yB_f1:0.8306010928961749 60 | ******loss: 0.5638894040450309 ****** 61 | A weight: [-0.07569014 -0.00733486 0.01989663 -0.08220942 0.07875236 0.06614039 62 | -0.04915103 -0.11747579 -0.02374406 0.01428984 -0.08721611 -0.09447281 63 | -0.03819611 0.06319849 0.00485155 -0.00964347 -0.03083926 -0.00424821 64 | 0.03624049 0.04978285] 65 | B weight: [ 0.03359185 -0.07067555 0.01378397 0.07657646 0.01551864 0.04943953 66 | -0.04031413 -0.12103449 -0.06832166 0.04895611 -0.0626096 ] 67 | yA_accuracy:0.7902097902097902, yA_precision:0.8372093023255814, yA_recall:0.8181818181818182, yA_f1:0.8275862068965518 68 | yB_accuracy:0.7902097902097902, yB_precision:0.8085106382978723, yB_recall:0.8636363636363636, yB_f1:0.8351648351648351 69 | ******loss: 0.5579570290591931 ****** 70 | A weight: [-0.07660037 -0.00722404 0.01901144 -0.08308122 0.07888548 0.06570204 71 | -0.04948654 -0.11808791 -0.02361073 0.01429571 -0.08865458 -0.09539079 72 | -0.03963978 0.06185423 0.00394899 -0.01079667 -0.03210263 -0.00574879 73 | 0.03531652 0.04912916] 74 | B weight: [ 0.03420635 -0.07201495 0.01296275 0.07521866 0.0142375 0.0487788 75 | -0.04139318 -0.12225468 -0.06971384 0.04832848 -0.06247436] 76 | yA_accuracy:0.8111888111888111, yA_precision:0.8588235294117647, yA_recall:0.8295454545454546, yA_f1:0.8439306358381502 77 | yB_accuracy:0.7902097902097902, yB_precision:0.8085106382978723, yB_recall:0.8636363636363636, yB_f1:0.8351648351648351 78 | ******loss: 0.5522107710910759 ****** 79 | A weight: [-0.07749313 -0.00711316 0.01814405 -0.0839355 0.07901767 0.06527602 80 | -0.04981072 -0.11868618 -0.02347709 0.01430714 -0.09007163 -0.09629791 81 | -0.04106145 0.06053096 0.00305737 -0.01193173 -0.033346 -0.00722715 82 | 0.03440318 0.04848576] 83 | B weight: [ 0.03482007 -0.07333353 0.01215228 0.0738822 0.01297718 0.04812914 84 | -0.04245233 -0.12345299 -0.07108324 0.0477114 -0.06233725] 85 | yA_accuracy:0.8111888111888111, yA_precision:0.8588235294117647, yA_recall:0.8295454545454546, yA_f1:0.8439306358381502 86 | yB_accuracy:0.8041958041958042, yB_precision:0.8260869565217391, yB_recall:0.8636363636363636, yB_f1:0.8444444444444444 87 | ******loss: 0.5466445313981423 ****** 88 | A weight: [-0.07836871 -0.00700225 0.01729415 -0.08477255 0.07914891 0.0648621 89 | -0.05012377 -0.11927085 -0.02334316 0.014324 -0.0914676 -0.09719434 90 | -0.04246147 0.05922835 0.00217652 -0.01304896 -0.03456969 -0.00868365 91 | 0.0335003 0.04785247] 92 | B weight: [ 0.035433 -0.07463162 0.0113524 0.07256674 0.01173733 0.04749035 93 | -0.04349192 -0.12462979 -0.07243023 0.04710468 -0.06219831] 94 | yA_accuracy:0.8251748251748252, yA_precision:0.8795180722891566, yA_recall:0.8295454545454546, yA_f1:0.8538011695906433 95 | yB_accuracy:0.8041958041958042, yB_precision:0.8260869565217391, yB_recall:0.8636363636363636, yB_f1:0.8444444444444444 96 | ******loss: 0.5412524128676143 ****** 97 | A weight: [-0.07922742 -0.00689131 0.01646144 -0.08559266 0.07927921 0.06446006 98 | -0.05042589 -0.11984216 -0.02320897 0.01434618 -0.09284285 -0.09808024 99 | -0.0438402 0.05794605 0.00130626 -0.01414864 -0.03577404 -0.01011865 100 | 0.0326077 0.04722913] 101 | B weight: [ 0.03604516 -0.07590957 0.01056293 0.07127193 0.01051763 0.04686224 102 | -0.04451228 -0.12578546 -0.07375519 0.04650814 -0.0620576 ] 103 | yA_accuracy:0.8461538461538461, yA_precision:0.8837209302325582, yA_recall:0.8636363636363636, yA_f1:0.8735632183908046 104 | yB_accuracy:0.8041958041958042, yB_precision:0.8260869565217391, yB_recall:0.8636363636363636, yB_f1:0.8444444444444444 105 | ******loss: 0.5360287133340956 ****** 106 | A weight: [-0.08006954 -0.00678037 0.01564562 -0.08639612 0.07940856 0.06406967 107 | -0.0507173 -0.12040035 -0.02307455 0.01437356 -0.0941977 -0.09895578 108 | -0.04519797 0.05668374 0.00044642 -0.01523108 -0.03695936 -0.0115325 109 | 0.03172524 0.04661555] 110 | B weight: [ 0.03665653 -0.07716769 0.00978371 0.06999745 0.00931775 0.04624464 111 | -0.04551374 -0.12692034 -0.07505849 0.04592161 -0.06191517] 112 | yA_accuracy:0.8531468531468531, yA_precision:0.8850574712643678, yA_recall:0.875, yA_f1:0.8800000000000001 113 | yB_accuracy:0.8041958041958042, yB_precision:0.8260869565217391, yB_recall:0.8636363636363636, yB_f1:0.8444444444444444 114 | ******loss: 0.5309679191188403 ****** 115 | A weight: [-0.08089536 -0.00666943 0.0148464 -0.08718321 0.07953696 0.06369072 116 | -0.0509982 -0.12094567 -0.02293992 0.01440602 -0.09553247 -0.09982111 117 | -0.04653513 0.0554411 -0.00040317 -0.01629655 -0.03812598 -0.01292555 118 | 0.03085275 0.04601157] 119 | B weight: [ 0.03726713 -0.07840631 0.00901458 0.06874295 0.00813736 0.04563737 120 | -0.04649663 -0.12803479 -0.07634049 0.04534492 -0.06177106] 121 | yA_accuracy:0.8671328671328671, yA_precision:0.896551724137931, yA_recall:0.8863636363636364, yA_f1:0.8914285714285715 122 | yB_accuracy:0.8181818181818182, yB_precision:0.8369565217391305, yB_recall:0.875, yB_f1:0.8555555555555556 123 | ******loss: 0.5260646987833112 ****** 124 | A weight: [-0.08170515 -0.0065585 0.01406351 -0.0879542 0.07966441 0.063323 125 | -0.05126878 -0.12147835 -0.0228051 0.01444346 -0.09684751 -0.1006764 126 | -0.04785202 0.0542178 -0.00124267 -0.01734534 -0.03927419 -0.01429814 127 | 0.02999007 0.04541703] 128 | B weight: [ 0.03787695 -0.07962575 0.00825539 0.06750811 0.00697614 0.04504024 129 | -0.04746126 -0.12912916 -0.07760154 0.0447779 -0.06162532] 130 | yA_accuracy:0.8671328671328671, yA_precision:0.896551724137931, yA_recall:0.8863636363636364, yA_f1:0.8914285714285715 131 | yB_accuracy:0.8181818181818182, yB_precision:0.8369565217391305, yB_recall:0.875, yB_f1:0.8555555555555556 132 | ******loss: 0.5213138970899188 ****** 133 | A weight: [-0.08249919 -0.00644761 0.01329665 -0.08870936 0.0797909 0.0629663 134 | -0.05152923 -0.12199861 -0.02267011 0.01448576 -0.09814312 -0.10152179 135 | -0.04914896 0.05301353 -0.00207224 -0.01837772 -0.04040432 -0.0156506 136 | 0.02913705 0.04483176] 137 | B weight: [ 0.03848599 -0.08082632 0.00750597 0.06629262 0.00583379 0.04445308 138 | -0.04840794 -0.13020378 -0.078842 0.04422038 -0.061478 ] 139 | yA_accuracy:0.8671328671328671, yA_precision:0.896551724137931, yA_recall:0.8863636363636364, yA_f1:0.8914285714285715 140 | yB_accuracy:0.8251748251748252, yB_precision:0.8461538461538461, yB_recall:0.875, yB_f1:0.8603351955307262 141 | ******loss: 0.5167105291630689 ****** 142 | A weight: [-0.08327776 -0.00633676 0.01254555 -0.08944898 0.07991643 0.06262041 143 | -0.05177975 -0.12250668 -0.02253498 0.01453281 -0.09941961 -0.10235744 144 | -0.05042627 0.05182799 -0.00289204 -0.01939397 -0.04151665 -0.01698327 145 | 0.02829354 0.0442556 ] 146 | B weight: [ 0.03909425 -0.08200831 0.00676616 0.06509615 0.00470999 0.04387573 147 | -0.04933697 -0.131259 -0.08006219 0.04367219 -0.06132914] 148 | yA_accuracy:0.8811188811188811, yA_precision:0.9176470588235294, yA_recall:0.8863636363636364, yA_f1:0.9017341040462428 149 | yB_accuracy:0.8321678321678322, yB_precision:0.8478260869565217, yB_recall:0.8863636363636364, yB_f1:0.8666666666666666 150 | ******loss: 0.5122497748438692 ****** 151 | A weight: [-0.08404111 -0.00622596 0.01180995 -0.0901733 0.080041 0.06228512 152 | -0.05202053 -0.12300279 -0.02239973 0.01458451 -0.1006773 -0.1031835 153 | -0.05168427 0.05066087 -0.00370222 -0.02039435 -0.04261149 -0.01829646 154 | 0.02745939 0.0436884 ] 155 | B weight: [ 0.03970175 -0.08317204 0.00603583 0.06391841 0.00360444 0.04330801 156 | -0.05024867 -0.13229514 -0.08126247 0.04313318 -0.06117879] 157 | yA_accuracy:0.8881118881118881, yA_precision:0.9285714285714286, yA_recall:0.8863636363636364, yA_f1:0.9069767441860465 158 | yB_accuracy:0.8461538461538461, yB_precision:0.8586956521739131, yB_recall:0.8977272727272727, yB_f1:0.8777777777777778 159 | ******loss: 0.5079269732320739 ****** 160 | A weight: [-0.0847895 -0.00611523 0.01108957 -0.09088259 0.0801646 0.06196025 161 | -0.05225175 -0.12348715 -0.02226438 0.01464076 -0.10191649 -0.1040001 162 | -0.05292328 0.04951188 -0.00450295 -0.02137912 -0.04368912 -0.01959049 163 | 0.02663445 0.04313 ] 164 | B weight: [ 0.04030846 -0.0843178 0.00531481 0.06275907 0.00251684 0.04274976 165 | -0.05114332 -0.13331253 -0.08244317 0.04260319 -0.06102699] 166 | yA_accuracy:0.8951048951048951, yA_precision:0.9294117647058824, yA_recall:0.8977272727272727, yA_f1:0.9132947976878613 167 | yB_accuracy:0.8461538461538461, yB_precision:0.8586956521739131, yB_recall:0.8977272727272727, yB_f1:0.8777777777777778 168 | ******loss: 0.5037376174090512 ****** 169 | A weight: [-0.08552321 -0.00600458 0.01038415 -0.0915771 0.08028724 0.0616456 170 | -0.05247359 -0.12395997 -0.02212895 0.01470145 -0.10313747 -0.10480741 171 | -0.0541436 0.04838071 -0.00529437 -0.02234855 -0.04474983 -0.02086569 172 | 0.02581859 0.04258025] 173 | B weight: [ 0.04091441 -0.08544588 0.00460297 0.06161786 0.00144691 0.04220082 174 | -0.05202121 -0.13431148 -0.0836046 0.04208207 -0.06087378] 175 | yA_accuracy:0.8951048951048951, yA_precision:0.9294117647058824, yA_recall:0.8977272727272727, yA_f1:0.9132947976878613 176 | yB_accuracy:0.8531468531468531, yB_precision:0.8681318681318682, yB_recall:0.8977272727272727, yB_f1:0.8826815642458101 177 | ******loss: 0.49967734933576946 ****** 178 | A weight: [-0.08624246 -0.00589401 0.00969344 -0.09225708 0.0804089 0.06134097 179 | -0.05268623 -0.12442148 -0.02199346 0.01476649 -0.10434054 -0.10560555 180 | -0.05534553 0.04726709 -0.00607663 -0.02330288 -0.04579391 -0.02212235 181 | 0.02501165 0.042039 ] 182 | B weight: [ 0.04151958 -0.08655657 0.00390015 0.06049446 0.00039435 0.04166103 183 | -0.05288264 -0.13529231 -0.0847471 0.04156965 -0.06071921] 184 | yA_accuracy:0.8951048951048951, yA_precision:0.9294117647058824, yA_recall:0.8977272727272727, yA_f1:0.9132947976878613 185 | yB_accuracy:0.8531468531468531, yB_precision:0.8681318681318682, yB_recall:0.8977272727272727, yB_f1:0.8826815642458101 186 | ******loss: 0.49574195491999407 ****** 187 | A weight: [-0.08694753 -0.00578355 0.00901718 -0.09292278 0.0805296 0.06104618 188 | -0.05288984 -0.12487187 -0.02185793 0.01483577 -0.10552599 -0.10639468 189 | -0.05652937 0.04617072 -0.00684987 -0.02424236 -0.04682162 -0.02336078 190 | 0.0242135 0.04150611] 191 | B weight: [ 0.04212398 -0.08765014 0.00320622 0.05938859 -0.00064112 0.04113023 192 | -0.05372788 -0.13625532 -0.08587097 0.04106579 -0.06056332] 193 | yA_accuracy:0.8951048951048951, yA_precision:0.9294117647058824, yA_recall:0.8977272727272727, yA_f1:0.9132947976878613 194 | yB_accuracy:0.8531468531468531, yB_precision:0.8681318681318682, yB_recall:0.8977272727272727, yB_f1:0.8826815642458101 195 | ******loss: 0.49192735924708275 ****** 196 | A weight: [-0.08763864 -0.0056732 0.00835512 -0.09357444 0.08064932 0.06076104 197 | -0.05308459 -0.12531134 -0.02172237 0.01490919 -0.1066941 -0.10717492 198 | -0.05769541 0.04509134 -0.00761425 -0.02516725 -0.04783324 -0.02458128 199 | 0.02342401 0.04098143] 200 | B weight: [ 0.04272762 -0.08872688 0.00252104 0.05829997 -0.00165977 0.04060827 201 | -0.05455722 -0.13720083 -0.08697653 0.04057035 -0.06040614] 202 | yA_accuracy:0.8951048951048951, yA_precision:0.9294117647058824, yA_recall:0.8977272727272727, yA_f1:0.9132947976878613 203 | yB_accuracy:0.8531468531468531, yB_precision:0.8681318681318682, yB_recall:0.8977272727272727, yB_f1:0.8826815642458101 204 | ******loss: 0.48822962196895 ****** 205 | A weight: [-0.08831604 -0.00556296 0.00770702 -0.0942123 0.08076807 0.06048537 206 | -0.05327066 -0.12574011 -0.02158682 0.01498667 -0.10784515 -0.10794641 207 | -0.05884395 0.04402866 -0.00836989 -0.02607778 -0.04882904 -0.02578413 208 | 0.02264303 0.04046481] 209 | B weight: [ 0.04333048 -0.08978705 0.00184446 0.05722831 -0.00266189 0.04009499 210 | -0.05537091 -0.13812912 -0.08806407 0.04008317 -0.06024772] 211 | yA_accuracy:0.9020979020979021, yA_precision:0.9302325581395349, yA_recall:0.9090909090909091, yA_f1:0.9195402298850575 212 | yB_accuracy:0.8531468531468531, yB_precision:0.8681318681318682, yB_recall:0.8977272727272727, yB_f1:0.8826815642458101 213 | ******loss: 0.4846449328459539 ****** 214 | A weight: [-0.08897996 -0.00545286 0.00707264 -0.09483659 0.08088584 0.06021899 215 | -0.05344821 -0.12615836 -0.02145129 0.0150681 -0.10897941 -0.10870928 216 | -0.05997525 0.04298241 -0.00911695 -0.02697419 -0.04980928 -0.02696964 217 | 0.02187043 0.03995613] 218 | B weight: [ 0.04393258 -0.09083094 0.00117636 0.05617334 -0.00364774 0.03959025 219 | -0.05616923 -0.13904049 -0.08913391 0.03960412 -0.0600881 ] 220 | yA_accuracy:0.9020979020979021, yA_precision:0.9302325581395349, yA_recall:0.9090909090909091, yA_f1:0.9195402298850575 221 | yB_accuracy:0.8531468531468531, yB_precision:0.8681318681318682, yB_recall:0.8977272727272727, yB_f1:0.8826815642458101 222 | ******loss: 0.48116960743663195 ****** 223 | A weight: [-0.08963064 -0.0053429 0.00645174 -0.09544754 0.08100264 0.05996173 224 | -0.05361741 -0.12656629 -0.02131579 0.0151534 -0.11009716 -0.10946367 225 | -0.06108961 0.04195233 -0.00985555 -0.02785671 -0.05077422 -0.02813807 226 | 0.02110609 0.03945524] 227 | B weight: [ 0.04453391 -0.09185878 0.00051661 0.0551348 -0.00461758 0.0390939 228 | -0.05695245 -0.13993523 -0.09018634 0.03913306 -0.05992731] 229 | yA_accuracy:0.9020979020979021, yA_precision:0.9302325581395349, yA_recall:0.9090909090909091, yA_f1:0.9195402298850575 230 | yB_accuracy:0.8531468531468531, yB_precision:0.8681318681318682, yB_recall:0.8977272727272727, yB_f1:0.8826815642458101 231 | ******loss: 0.47780008293038045 ****** 232 | A weight: [-0.09026831 -0.0052331 0.00584409 -0.09604538 0.08111845 0.05971341 233 | -0.05377841 -0.12696409 -0.02118034 0.01524248 -0.11119865 -0.1102097 234 | -0.06218729 0.04093817 -0.01058583 -0.02872557 -0.05172411 -0.02928972 235 | 0.02034988 0.03896201] 236 | B weight: [ 4.51344734e-02 -9.28708624e-02 -1.34940794e-04 5.41124034e-02 237 | -5.57167839e-03 3.86058009e-02 -5.77208109e-02 -1.40813616e-01 238 | -9.12216395e-02 3.86698398e-02 -5.97653880e-02] 239 | yA_accuracy:0.916083916083916, yA_precision:0.9523809523809523, yA_recall:0.9090909090909091, yA_f1:0.9302325581395349 240 | yB_accuracy:0.8601398601398601, yB_precision:0.8695652173913043, yB_recall:0.9090909090909091, yB_f1:0.888888888888889 241 | ******loss: 0.47453291411833515 ****** 242 | A weight: [-0.09089318 -0.00512345 0.00524945 -0.09663033 0.08123329 0.05947386 243 | -0.05393136 -0.12735195 -0.02104497 0.01533525 -0.11228416 -0.1109475 244 | -0.06326856 0.03993965 -0.01130793 -0.029581 -0.0526592 -0.03042485 245 | 0.01960167 0.03847631] 246 | B weight: [ 0.04573427 -0.09386742 -0.0007784 0.0531059 -0.00651029 0.03812581 247 | -0.05847458 -0.14167593 -0.0922401 0.03821433 -0.05960238] 248 | yA_accuracy:0.916083916083916, yA_precision:0.9523809523809523, yA_recall:0.9090909090909091, yA_f1:0.9302325581395349 249 | yB_accuracy:0.8601398601398601, yB_precision:0.8695652173913043, yB_recall:0.9090909090909091, yB_f1:0.888888888888889 250 | ******loss: 0.4713647694978681 ****** 251 | A weight: [-0.09150549 -0.00501397 0.00466761 -0.09720261 0.08134714 0.05924293 252 | -0.05407644 -0.12773004 -0.02090968 0.01543162 -0.11335393 -0.11167719 253 | -0.06433369 0.03895654 -0.01202196 -0.03042322 -0.05357973 -0.03154373 254 | 0.01886134 0.037998 ] 255 | B weight: [ 0.04633331 -0.09484872 -0.00141391 0.05211503 -0.00743366 0.03765378 256 | -0.059214 -0.14252245 -0.093242 0.03776641 -0.05943831] 257 | yA_accuracy:0.916083916083916, yA_precision:0.9523809523809523, yA_recall:0.9090909090909091, yA_f1:0.9302325581395349 258 | yB_accuracy:0.8601398601398601, yB_precision:0.8695652173913043, yB_recall:0.9090909090909091, yB_f1:0.888888888888889 259 | ******loss: 0.46829242750626837 ****** 260 | A weight: [-0.09210544 -0.00490468 0.00409834 -0.09776243 0.08146001 0.05902043 261 | -0.05421378 -0.12809855 -0.0207745 0.0155315 -0.11440821 -0.1123989 262 | -0.06538294 0.03798857 -0.01272807 -0.03125245 -0.05448596 -0.03264663 263 | 0.01812876 0.03752697] 264 | B weight: [ 0.04693158 -0.09581499 -0.00204158 0.05113954 -0.00834204 0.03718958 265 | -0.05993932 -0.14335343 -0.09422762 0.03732593 -0.05927322] 266 | yA_accuracy:0.916083916083916, yA_precision:0.9523809523809523, yA_recall:0.9090909090909091, yA_f1:0.9302325581395349 267 | yB_accuracy:0.8601398601398601, yB_precision:0.8695652173913043, yB_recall:0.9090909090909091, yB_f1:0.888888888888889 268 | ******loss: 0.4653127728793204 ****** 269 | A weight: [-0.09269325 -0.00479557 0.00354143 -0.09831001 0.0815719 0.05880622 270 | -0.05434354 -0.12845766 -0.02063943 0.01563482 -0.11544727 -0.11311275 271 | -0.06641656 0.03703552 -0.01342637 -0.03206889 -0.05537811 -0.03373381 272 | 0.01740382 0.03706307] 273 | B weight: [ 0.04752909 -0.09676648 -0.00266155 0.05017918 -0.00923568 0.03673308 274 | -0.06065079 -0.14416916 -0.09519723 0.03689277 -0.05910714] 275 | yA_accuracy:0.916083916083916, yA_precision:0.9523809523809523, yA_recall:0.9090909090909091, yA_f1:0.9302325581395349 276 | yB_accuracy:0.8601398601398601, yB_precision:0.8695652173913043, yB_recall:0.9090909090909091, yB_f1:0.888888888888889 277 | All process done. -------------------------------------------------------------------------------- /Result/test1/result.txt: -------------------------------------------------------------------------------- 1 | XA: (426, 20) XB: (426, 11) 2 | Guest_A successfully initialized. 3 | Host_B successfully initialized. 4 | Sever_C successfully initialized. 5 | Random process of flipping labels is done. 6 | **********epoch1********** 7 | ******loss: 0.8127255347230972 ****** 8 | A weight: [ 0.09109948 0.0367327 0.02902956 0.03587624 0.07895733 0.03179898 9 | 0.15846816 -0.08093672 -0.0403558 0.01114437 0.05795133 -0.07816044 10 | -0.09264781 0.04169087 0.0232079 -0.04060241 0.07102859 0.03679773 11 | -0.01148802 0.07972502] 12 | B weight: [-0.03196765 0.0377887 0.00336731 -0.07151367 0.06463403 0.09595161 13 | -0.02379388 -0.0703596 0.02866873 0.02862403 0.03050141] 14 | yA_accuracy:0.23776223776223776, yA_precision:0.3157894736842105, yA_recall:0.20454545454545456, yA_f1:0.2482758620689655 15 | yB_accuracy:0.32167832167832167, yB_precision:0.4117647058823529, yB_recall:0.23863636363636365, yB_f1:0.302158273381295 16 | **********epoch2********** 17 | ******loss: 0.7982398676633549 ****** 18 | A weight: [ 0.08943851 0.03666469 0.02739174 0.03429239 0.07890541 0.03075028 19 | 0.15746647 -0.08223596 -0.04038425 0.01068762 0.05585471 -0.07936073 20 | -0.09477073 0.03968208 0.02193624 -0.04233655 0.06905482 0.03457158 21 | -0.01262285 0.07866478] 22 | B weight: [-0.03126967 0.03580642 0.00223439 -0.07353542 0.062683 0.09481568 23 | -0.02562278 -0.07243697 0.02646491 0.02761799 0.03036546] 24 | yA_accuracy:0.25874125874125875, yA_precision:0.3448275862068966, yA_recall:0.22727272727272727, yA_f1:0.273972602739726 25 | yB_accuracy:0.34965034965034963, yB_precision:0.4489795918367347, yB_recall:0.25, yB_f1:0.32116788321167883 26 | **********epoch3********** 27 | ******loss: 0.784227873857342 ****** 28 | A weight: [ 0.08780608 0.0365981 0.02578303 0.03273678 0.07885393 0.02972328 29 | 0.15648489 -0.08351134 -0.04041042 0.01024222 0.05379132 -0.08054454 30 | -0.09685938 0.03770597 0.02068195 -0.04404168 0.06711311 0.03238055 31 | -0.01374131 0.07762174] 32 | B weight: [-0.03057257 0.03385654 0.00111811 -0.07552384 0.06076452 0.09369818 33 | -0.02741907 -0.07447875 0.02429754 0.02662947 0.03023447] 34 | yA_accuracy:0.26573426573426573, yA_precision:0.3559322033898305, yA_recall:0.23863636363636365, yA_f1:0.2857142857142857 35 | yB_accuracy:0.38461538461538464, yB_precision:0.5, yB_recall:0.26136363636363635, yB_f1:0.34328358208955223 36 | **********epoch4********** 37 | ******loss: 0.7706738744776062 ****** 38 | A weight: [ 0.08620168 0.0365329 0.02420293 0.03120895 0.07880286 0.02871763 39 | 0.15552309 -0.08476327 -0.04043434 0.00980796 0.0517606 -0.08171214 40 | -0.09891434 0.035762 0.01944475 -0.04571826 0.06520292 0.03022403 41 | -0.01484365 0.0765956 ] 42 | B weight: [-2.98763581e-02 3.19385114e-02 1.82018589e-05 -7.74794769e-02 43 | 5.88780413e-02 9.25987958e-02 -2.91832980e-02 -7.64855231e-02 44 | 2.21660286e-02 2.56581763e-02 3.01083526e-02] 45 | yA_accuracy:0.2727272727272727, yA_precision:0.3620689655172414, yA_recall:0.23863636363636365, yA_f1:0.2876712328767123 46 | yB_accuracy:0.4405594405594406, yB_precision:0.6, yB_recall:0.2727272727272727, yB_f1:0.37499999999999994 47 | **********epoch5********** 48 | ******loss: 0.7521953066738191 ****** 49 | A weight: [ 0.0846683 0.03647772 0.02269365 0.02974327 0.07877161 0.02779966 50 | 0.15463059 -0.08595891 -0.04044002 0.00942681 0.0498064 -0.08280962 51 | -0.10088796 0.03388845 0.01833245 -0.04727365 0.06341972 0.02819287 52 | -0.01582864 0.07565989] 53 | B weight: [-0.02918103 0.03009092 -0.00102766 -0.07935776 0.05705919 0.09163943 54 | -0.03080443 -0.07835038 0.02017011 0.02481984 0.03005621] 55 | yA_accuracy:0.27972027972027974, yA_precision:0.3728813559322034, yA_recall:0.25, yA_f1:0.29931972789115646 56 | yB_accuracy:0.45454545454545453, yB_precision:0.625, yB_recall:0.2840909090909091, yB_f1:0.390625 57 | **********epoch6********** 58 | ******loss: 0.7405386709241325 ****** 59 | A weight: [ 0.08316102 0.03642375 0.02121099 0.0283035 0.07874053 0.02690121 60 | 0.1537562 -0.08713297 -0.04044383 0.00905569 0.0478827 -0.08389205 61 | -0.10283016 0.03204489 0.0172357 -0.04880282 0.06166558 0.02619366 62 | -0.01679895 0.07473947] 63 | B weight: [-0.0284866 0.02827308 -0.00205829 -0.08120546 0.05527023 0.09069653 64 | -0.03239611 -0.08018291 0.0182074 0.02399715 0.03000811] 65 | yA_accuracy:0.27972027972027974, yA_precision:0.3728813559322034, yA_recall:0.25, yA_f1:0.29931972789115646 66 | yB_accuracy:0.48951048951048953, yB_precision:0.6829268292682927, yB_recall:0.3181818181818182, yB_f1:0.43410852713178294 67 | **********epoch7********** 68 | ******loss: 0.7292619988894781 ****** 69 | A weight: [ 0.08167942 0.03637098 0.01975451 0.0268892 0.07870961 0.02602192 70 | 0.15289961 -0.0882858 -0.04044581 0.00869441 0.045989 -0.08495965 71 | -0.10474147 0.03023085 0.01615424 -0.0503062 0.05994 0.02422586 72 | -0.01775482 0.07383409] 73 | B weight: [-0.02779304 0.0264845 -0.00307393 -0.08302307 0.05351068 0.08976981 74 | -0.03395881 -0.08198365 0.01627734 0.02318984 0.02996398] 75 | yA_accuracy:0.3006993006993007, yA_precision:0.4, yA_recall:0.2727272727272727, yA_f1:0.3243243243243243 76 | yB_accuracy:0.5104895104895105, yB_precision:0.7045454545454546, yB_recall:0.3522727272727273, yB_f1:0.4696969696969697 77 | **********epoch8********** 78 | ******loss: 0.7183527239816545 ****** 79 | A weight: [ 0.08022306 0.03631937 0.01832376 0.02549996 0.07867883 0.02516146 80 | 0.1520605 -0.08941779 -0.040446 0.00834278 0.04412481 -0.08601266 81 | -0.10662238 0.02844584 0.01508781 -0.05178422 0.05824252 0.02228896 82 | -0.01869648 0.07294349] 83 | B weight: [-0.02710037 0.02472471 -0.00407482 -0.0848111 0.05178003 0.08885902 84 | -0.03549305 -0.08375315 0.01437939 0.02239765 0.02992372] 85 | yA_accuracy:0.3356643356643357, yA_precision:0.4426229508196721, yA_recall:0.3068181818181818, yA_f1:0.3624161073825503 86 | yB_accuracy:0.5384615384615384, yB_precision:0.7391304347826086, yB_recall:0.38636363636363635, yB_f1:0.5074626865671641 87 | **********epoch9********** 88 | ******loss: 0.7077986962022265 ****** 89 | A weight: [ 0.07879152 0.0362689 0.01691832 0.02413535 0.07864819 0.02431951 90 | 0.15123856 -0.09052928 -0.04044445 0.00800062 0.04228963 -0.08705133 91 | -0.10847341 0.02668937 0.01403617 -0.05323733 0.05657267 0.02038245 92 | -0.01962418 0.07206741] 93 | B weight: [-0.02640858 0.02299323 -0.00506121 -0.08657004 0.05007783 0.08796386 94 | -0.03699929 -0.08549193 0.012513 0.02162032 0.02988727] 95 | yA_accuracy:0.34265734265734266, yA_precision:0.45161290322580644, yA_recall:0.3181818181818182, yA_f1:0.3733333333333333 96 | yB_accuracy:0.5664335664335665, yB_precision:0.76, yB_recall:0.4318181818181818, yB_f1:0.5507246376811594 97 | **********epoch10********** 98 | ******loss: 0.6965880913517603 ****** 99 | A weight: [ 0.07741314 0.03619101 0.01556063 0.02281497 0.07860354 0.02349257 100 | 0.15042372 -0.09160976 -0.04040002 0.00767583 0.04049746 -0.08813872 101 | -0.11028079 0.02497707 0.0129803 -0.0546697 0.05491511 0.01849945 102 | -0.02052019 0.07121004] 103 | B weight: [-0.0257881 0.02130034 -0.00607775 -0.08829021 0.04841718 0.08708772 104 | -0.03847631 -0.08721559 0.01067568 0.02087553 0.02986136] 105 | yA_accuracy:0.3916083916083916, yA_precision:0.5079365079365079, yA_recall:0.36363636363636365, yA_f1:0.423841059602649 106 | yB_accuracy:0.5874125874125874, yB_precision:0.7735849056603774, yB_recall:0.4659090909090909, yB_f1:0.5815602836879433 107 | **********epoch11********** 108 | ******loss: 0.6867575409513061 ****** 109 | A weight: [ 0.07605865 0.03611428 0.01422728 0.02151829 0.078559 0.02268345 110 | 0.14962543 -0.09267051 -0.04035401 0.00736014 0.03873328 -0.08921209 111 | -0.11205935 0.02329231 0.01193874 -0.05607799 0.05328425 0.01664578 112 | -0.02140274 0.07036673] 113 | B weight: [-0.0251684 0.01963474 -0.00708016 -0.08998232 0.04678394 0.08622666 114 | -0.03992633 -0.08890961 0.00886879 0.02014502 0.02983911] 115 | yA_accuracy:0.3986013986013986, yA_precision:0.515625, yA_recall:0.375, yA_f1:0.4342105263157895 116 | yB_accuracy:0.6293706293706294, yB_precision:0.8070175438596491, yB_recall:0.5227272727272727, yB_f1:0.6344827586206896 117 | **********epoch12********** 118 | ******loss: 0.6772467136315699 ****** 119 | A weight: [ 0.07472763 0.03603867 0.01291787 0.02024492 0.07851457 0.02189185 120 | 0.14884339 -0.09371187 -0.04030644 0.00705338 0.03699664 -0.09027169 121 | -0.11380954 0.02163463 0.01091127 -0.05746258 0.05167962 0.01482097 122 | -0.02227203 0.06953721] 123 | B weight: [-0.0245495 0.017996 -0.00806866 -0.09164684 0.04517767 0.08538042 124 | -0.04134981 -0.09057451 0.00709185 0.01942856 0.02982042] 125 | yA_accuracy:0.4195804195804196, yA_precision:0.5409836065573771, yA_recall:0.375, yA_f1:0.4429530201342282 126 | yB_accuracy:0.6363636363636364, yB_precision:0.8103448275862069, yB_recall:0.5340909090909091, yB_f1:0.6438356164383561 127 | **********epoch13********** 128 | ******loss: 0.6680450401712388 ****** 129 | A weight: [ 0.0734197 0.03596415 0.011632 0.01899447 0.07847022 0.02111745 130 | 0.14807733 -0.09473418 -0.04025737 0.00675539 0.03528708 -0.09131772 131 | -0.11553183 0.02000358 0.00989765 -0.0588239 0.0501008 0.01302452 132 | -0.02312829 0.06872127] 133 | B weight: [-0.02393138 0.01638366 -0.00904347 -0.09328421 0.04359792 0.08454875 134 | -0.0427472 -0.09221076 0.00534435 0.01872589 0.02980523] 135 | yA_accuracy:0.4405594405594406, yA_precision:0.5666666666666667, yA_recall:0.38636363636363635, yA_f1:0.4594594594594595 136 | yB_accuracy:0.6503496503496503, yB_precision:0.8166666666666667, yB_recall:0.5568181818181818, yB_f1:0.6621621621621621 137 | **********epoch14********** 138 | ******loss: 0.6591423016815945 ****** 139 | A weight: [ 0.07213445 0.0358907 0.01036927 0.01776655 0.07842595 0.02035995 140 | 0.14732695 -0.09573776 -0.04020682 0.00646599 0.03360417 -0.0923504 141 | -0.11722669 0.01839873 0.00889766 -0.06016231 0.04854735 0.01125597 142 | -0.02397174 0.06791866] 143 | B weight: [-0.02331405 0.01479731 -0.01000482 -0.09489489 0.04204425 0.08373139 144 | -0.04411894 -0.09381884 0.00362579 0.01803678 0.02979347] 145 | yA_accuracy:0.4825174825174825, yA_precision:0.6166666666666667, yA_recall:0.42045454545454547, yA_f1:0.5 146 | yB_accuracy:0.6923076923076923, yB_precision:0.84375, yB_recall:0.6136363636363636, yB_f1:0.7105263157894737 147 | **********epoch15********** 148 | ******loss: 0.6492323036770932 ****** 149 | A weight: [ 0.070902 0.03586041 0.00914683 0.01658228 0.07841654 0.01960057 150 | 0.14658388 -0.09672667 -0.04014845 0.00617018 0.03196466 -0.09330934 151 | -0.11888087 0.01683825 0.00800814 -0.06145786 0.0470399 0.00954147 152 | -0.02475438 0.06715248] 153 | B weight: [-0.02274445 0.01323855 -0.01091106 -0.09647645 0.0405224 0.08300761 154 | -0.0454462 -0.09537995 0.00195751 0.01740672 0.02979652] 155 | yA_accuracy:0.5174825174825175, yA_precision:0.6557377049180327, yA_recall:0.45454545454545453, yA_f1:0.5369127516778524 156 | yB_accuracy:0.6993006993006993, yB_precision:0.8461538461538461, yB_recall:0.625, yB_f1:0.7189542483660131 157 | **********epoch16********** 158 | ******loss: 0.6411839645481907 ****** 159 | A weight: [ 0.06969116 0.03583104 0.00794643 0.01541949 0.07840708 0.01885725 160 | 0.14585574 -0.09769777 -0.04008877 0.00588251 0.03035059 -0.09425565 161 | -0.12050888 0.01530278 0.0071314 -0.06273169 0.04555658 0.00785351 162 | -0.02552493 0.06639887] 163 | B weight: [-0.02217558 0.0117046 -0.01180454 -0.09803251 0.03902547 0.08229727 164 | -0.04674912 -0.09691427 0.00031678 0.01678942 0.02980265] 165 | yA_accuracy:0.5524475524475524, yA_precision:0.7068965517241379, yA_recall:0.4659090909090909, yA_f1:0.5616438356164384 166 | yB_accuracy:0.7062937062937062, yB_precision:0.8484848484848485, yB_recall:0.6363636363636364, yB_f1:0.7272727272727273 167 | **********epoch17********** 168 | ******loss: 0.6333972549803171 ****** 169 | A weight: [ 0.06850157 0.03580256 0.0067677 0.01427782 0.07839755 0.01812969 170 | 0.14514226 -0.09865136 -0.04002781 0.00560281 0.02876152 -0.09518953 171 | -0.12211113 0.01379189 0.00626721 -0.06398414 0.04409696 0.00619165 172 | -0.02628361 0.06565762] 173 | B weight: [-0.02160744 0.01019506 -0.01268545 -0.09956351 0.03755304 0.08160014 174 | -0.04802812 -0.09842227 -0.00129688 0.01618466 0.02981181] 175 | yA_accuracy:0.5804195804195804, yA_precision:0.7413793103448276, yA_recall:0.48863636363636365, yA_f1:0.5890410958904111 176 | yB_accuracy:0.7202797202797203, yB_precision:0.8636363636363636, yB_recall:0.6477272727272727, yB_f1:0.7402597402597403 177 | **********epoch18********** 178 | ******loss: 0.6258635297766963 ****** 179 | A weight: [ 0.06733287 0.03577497 0.00561027 0.01315693 0.07838793 0.01741763 180 | 0.14444319 -0.09958775 -0.03996561 0.00533095 0.02719705 -0.09611118 181 | -0.12368806 0.01230519 0.00541537 -0.06521558 0.04266067 0.00455546 182 | -0.02703061 0.06492851] 183 | B weight: [-0.02104001 0.00870953 -0.01355399 -0.10106985 0.03610471 0.08091599 184 | -0.04928359 -0.09990438 -0.00288391 0.01559223 0.02982393] 185 | yA_accuracy:0.6013986013986014, yA_precision:0.7540983606557377, yA_recall:0.5227272727272727, yA_f1:0.6174496644295302 186 | yB_accuracy:0.7412587412587412, yB_precision:0.8805970149253731, yB_recall:0.6704545454545454, yB_f1:0.7612903225806451 187 | **********epoch19********** 188 | ******loss: 0.6185744302376452 ****** 189 | A weight: [ 0.06618471 0.03574823 0.00447378 0.01205647 0.07837822 0.01672079 190 | 0.14375827 -0.10050723 -0.03990221 0.00506677 0.02565678 -0.09702079 191 | -0.12524008 0.01084227 0.00457568 -0.06642636 0.04124729 0.00294451 192 | -0.02776612 0.06421133] 193 | B weight: [-0.02047331 0.00724762 -0.01441037 -0.10255193 0.03468007 0.08024459 194 | -0.05051596 -0.10136104 -0.00444476 0.0150119 0.02983894] 195 | yA_accuracy:0.6223776223776224, yA_precision:0.7741935483870968, yA_recall:0.5454545454545454, yA_f1:0.64 196 | yB_accuracy:0.7552447552447552, yB_precision:0.8840579710144928, yB_recall:0.6931818181818182, yB_f1:0.7770700636942676 197 | **********epoch20********** 198 | ******loss: 0.6109836207208345 ****** 199 | A weight: [ 0.06507468 0.03575445 0.00337563 0.01098765 0.07842123 0.01604348 200 | 0.14306601 -0.10139217 -0.0398365 0.00480648 0.02415233 -0.09783612 201 | -0.12675196 0.00941621 0.00394075 -0.06752022 0.039917 0.00144054 202 | -0.02838351 0.0636144 ] 203 | B weight: [-0.01993081 0.00579879 -0.01522504 -0.10401754 0.0332728 0.07972131 204 | -0.05166286 -0.10276243 -0.00592798 0.01452911 0.02995427] 205 | yA_accuracy:0.6293706293706294, yA_precision:0.7777777777777778, yA_recall:0.5568181818181818, yA_f1:0.6490066225165563 206 | yB_accuracy:0.7552447552447552, yB_precision:0.8840579710144928, yB_recall:0.6931818181818182, yB_f1:0.7770700636942676 207 | **********epoch21********** 208 | ******loss: 0.6045990991051735 ****** 209 | A weight: [ 6.39840247e-02 3.57613760e-02 2.29721515e-03 9.93815249e-03 210 | 7.84638680e-02 1.53801763e-02 1.42386843e-01 -1.02261383e-01 211 | -3.97698307e-02 4.55311791e-03 2.26707479e-02 -9.86402563e-02 212 | -1.28240334e-01 8.01262632e-03 3.31664640e-03 -6.85950712e-02 213 | 3.86079356e-02 -3.99317974e-05 -2.89905383e-02 6.30281064e-02] 214 | B weight: [-0.019389 0.00437232 -0.01602832 -0.10546021 0.03188798 0.07920946 215 | -0.05278846 -0.10414014 -0.00738675 0.01405724 0.03007171] 216 | yA_accuracy:0.6363636363636364, yA_precision:0.78125, yA_recall:0.5681818181818182, yA_f1:0.6578947368421052 217 | yB_accuracy:0.7692307692307693, yB_precision:0.8873239436619719, yB_recall:0.7159090909090909, yB_f1:0.7924528301886792 218 | **********epoch22********** 219 | ******loss: 0.5984211286082425 ****** 220 | A weight: [ 0.06291242 0.035769 0.00123821 0.00890765 0.07850614 0.01473064 221 | 0.14172055 -0.10311515 -0.03970223 0.00430654 0.02121166 -0.09943339 222 | -0.12970559 0.00663117 0.00270317 -0.06965125 0.03731975 -0.0014973 223 | -0.02958737 0.06245227] 224 | B weight: [-0.01884787 0.00296786 -0.01682039 -0.10688031 0.03052525 0.07870885 225 | -0.05389311 -0.10549455 -0.00882147 0.01359611 0.03019121] 226 | yA_accuracy:0.6573426573426573, yA_precision:0.8, yA_recall:0.5909090909090909, yA_f1:0.6797385620915033 227 | yB_accuracy:0.7832167832167832, yB_precision:0.8904109589041096, yB_recall:0.7386363636363636, yB_f1:0.8074534161490683 228 | **********epoch23********** 229 | ******loss: 0.5924428976318755 ****** 230 | A weight: [ 0.06185955 0.03577731 0.0001983 0.00789584 0.07854803 0.01409461 231 | 0.14106691 -0.10395372 -0.03963373 0.00406662 0.0197747 -0.10021569 232 | -0.13114809 0.00527147 0.00210013 -0.07068905 0.0360521 -0.00293193 233 | -0.03017418 0.06188669] 234 | B weight: [-0.01830744 0.00158506 -0.01760145 -0.10827821 0.02918424 0.07821926 235 | -0.05497717 -0.10682607 -0.01023256 0.01314552 0.03031272] 236 | yA_accuracy:0.6783216783216783, yA_precision:0.8181818181818182, yA_recall:0.6136363636363636, yA_f1:0.7012987012987013 237 | yB_accuracy:0.7902097902097902, yB_precision:0.8918918918918919, yB_recall:0.75, yB_f1:0.8148148148148148 238 | **********epoch24********** 239 | ******loss: 0.5866578201122887 ****** 240 | A weight: [ 0.0608251 0.03578628 -0.00082284 0.0069024 0.07858954 0.01347187 241 | 0.14042568 -0.10477738 -0.03956436 0.00383324 0.0183595 -0.10098733 242 | -0.13256823 0.00393319 0.00150737 -0.07170881 0.03480463 -0.00434423 243 | -0.03075114 0.0613312 ] 244 | B weight: [-0.01776769 0.00022355 -0.01837165 -0.10965427 0.02786461 0.07774051 245 | -0.05604099 -0.10813508 -0.0116204 0.01270529 0.03043619] 246 | yA_accuracy:0.6783216783216783, yA_precision:0.8181818181818182, yA_recall:0.6136363636363636, yA_f1:0.7012987012987013 247 | yB_accuracy:0.7972027972027972, yB_precision:0.8933333333333333, yB_recall:0.7613636363636364, yB_f1:0.8220858895705522 248 | **********epoch25********** 249 | ******loss: 0.5812374392461065 ****** 250 | A weight: [ 0.05982124 0.03579185 -0.00182144 0.00593968 0.07864179 0.01282081 251 | 0.13975982 -0.10562471 -0.03952936 0.00356964 0.01698264 -0.10171782 252 | -0.13395168 0.0026298 0.00098064 -0.0727221 0.03356537 -0.00573391 253 | -0.03131431 0.06076448] 254 | B weight: [-0.01725211 -0.00111004 -0.01911402 -0.11100372 0.02657192 0.07729552 255 | -0.05712015 -0.10943848 -0.01298709 0.01226449 0.03051114] 256 | yA_accuracy:0.6923076923076923, yA_precision:0.8333333333333334, yA_recall:0.625, yA_f1:0.7142857142857143 257 | yB_accuracy:0.8111888111888111, yB_precision:0.8961038961038961, yB_recall:0.7840909090909091, yB_f1:0.8363636363636362 258 | **********epoch26********** 259 | ******loss: 0.5758279865866995 ****** 260 | A weight: [ 0.05883518 0.0357981 -0.00280187 0.00499469 0.07869373 0.01218279 261 | 0.13910615 -0.10645746 -0.03949339 0.00331257 0.01562677 -0.10243806 262 | -0.13531355 0.00134704 0.00046381 -0.07371784 0.03234572 -0.00710196 263 | -0.03186793 0.06020764] 264 | B weight: [-0.01673718 -0.00242308 -0.01984593 -0.1123321 0.02529985 0.07686103 265 | -0.05817962 -0.11072001 -0.01433128 0.01183379 0.03058816] 266 | yA_accuracy:0.7272727272727273, yA_precision:0.855072463768116, yA_recall:0.6704545454545454, yA_f1:0.7515923566878981 267 | yB_accuracy:0.8111888111888111, yB_precision:0.8961038961038961, yB_recall:0.7840909090909091, yB_f1:0.8363636363636362 268 | **********epoch27********** 269 | ******loss: 0.5705936157616422 ****** 270 | A weight: [ 5.78666425e-02 3.58050287e-02 -3.76445611e-03 4.06715335e-03 271 | 7.87453602e-02 1.15575877e-02 1.38464474e-01 -1.07275871e-01 272 | -3.94564808e-02 3.06190723e-03 1.42915501e-02 -1.03148211e-01 273 | -1.36654182e-01 8.45975542e-05 -4.32888067e-05 -7.46963333e-02 274 | 3.11453320e-02 -8.44873197e-03 -3.24121517e-02 5.96604995e-02] 275 | B weight: [-0.01622291 -0.00371591 -0.02056756 -0.11363973 0.02404807 0.07643686 276 | -0.05921975 -0.11198007 -0.01565333 0.01141301 0.03066719] 277 | yA_accuracy:0.7272727272727273, yA_precision:0.855072463768116, yA_recall:0.6704545454545454, yA_f1:0.7515923566878981 278 | yB_accuracy:0.8111888111888111, yB_precision:0.8961038961038961, yB_recall:0.7840909090909091, yB_f1:0.8363636363636362 279 | **********epoch28********** 280 | ******loss: 0.5655285500583285 ****** 281 | A weight: [ 0.05691532 0.03581261 -0.00470948 0.00315677 0.07879667 0.01094497 282 | 0.13783458 -0.1080802 -0.03941866 0.00281752 0.01297664 -0.10384844 283 | -0.13797392 -0.00115788 -0.00054082 -0.07565787 0.02996389 -0.00977458 284 | -0.03294715 0.05912289] 285 | B weight: [-0.01570929 -0.00498885 -0.02127907 -0.11492697 0.02281624 0.07602283 286 | -0.06024086 -0.11321899 -0.01695362 0.01100198 0.03074817] 287 | yA_accuracy:0.7412587412587412, yA_precision:0.8695652173913043, yA_recall:0.6818181818181818, yA_f1:0.7643312101910827 288 | yB_accuracy:0.8251748251748252, yB_precision:0.8987341772151899, yB_recall:0.8068181818181818, yB_f1:0.8502994011976047 289 | **********epoch29********** 290 | ******loss: 0.5606272040760591 ****** 291 | A weight: [ 0.05598092 0.03582082 -0.00563725 0.00226326 0.07884766 0.01034471 292 | 0.13721625 -0.1088707 -0.03937996 0.0025793 0.01168172 -0.1045389 293 | -0.13927311 -0.0023807 -0.00102896 -0.07660273 0.02880108 -0.01107986 294 | -0.03347308 0.05859464] 295 | B weight: [-0.01519633 -0.00624223 -0.02198062 -0.11619415 0.02160405 0.07561876 296 | -0.06124327 -0.11443715 -0.01823251 0.01060051 0.03083105] 297 | yA_accuracy:0.7552447552447552, yA_precision:0.8840579710144928, yA_recall:0.6931818181818182, yA_f1:0.7770700636942676 298 | yB_accuracy:0.8321678321678322, yB_precision:0.9, yB_recall:0.8181818181818182, yB_f1:0.8571428571428572 299 | **********epoch30********** 300 | ******loss: 0.5551033113294392 ****** 301 | A weight: [ 0.05508149 0.03583816 -0.00653328 0.0013865 0.0789058 0.00974729 302 | 0.13660338 -0.10963575 -0.03936158 0.00235669 0.0104082 -0.10519255 303 | -0.14055252 -0.00359025 -0.00141464 -0.07749649 0.02768658 -0.01232251 304 | -0.03393758 0.05816047] 305 | B weight: [-0.01463707 -0.00749827 -0.02266255 -0.11746123 0.02038788 0.07531332 306 | -0.06219823 -0.11561488 -0.01946052 0.01023978 0.03097659] 307 | yA_accuracy:0.7622377622377622, yA_precision:0.8857142857142857, yA_recall:0.7045454545454546, yA_f1:0.7848101265822784 308 | yB_accuracy:0.8321678321678322, yB_precision:0.9, yB_recall:0.8181818181818182, yB_f1:0.8571428571428572 309 | **********epoch31********** 310 | ******loss: 0.5506309209921442 ****** 311 | A weight: [ 0.05419825 0.03585607 -0.0074128 0.00052592 0.07896347 0.00916148 312 | 0.13600142 -0.11038771 -0.03934245 0.00213975 0.00915384 -0.10583693 313 | -0.14181225 -0.00478097 -0.00179172 -0.07837461 0.02658965 -0.01354567 314 | -0.03439367 0.05773485] 315 | B weight: [-0.01407852 -0.00873553 -0.02333499 -0.11870907 0.01919055 0.07501703 316 | -0.06313563 -0.11677295 -0.02066821 0.00988792 0.03112355] 317 | yA_accuracy:0.7692307692307693, yA_precision:0.8873239436619719, yA_recall:0.7159090909090909, yA_f1:0.7924528301886792 318 | yB_accuracy:0.8391608391608392, yB_precision:0.9012345679012346, yB_recall:0.8295454545454546, yB_f1:0.8639053254437871 319 | **********epoch32********** 320 | ******loss: 0.5463016730821075 ****** 321 | A weight: [ 0.05333094 0.03587454 -0.0082761 -0.00031876 0.07902067 0.00858707 322 | 0.13541016 -0.11112681 -0.03932258 0.00192837 0.00791832 -0.10647219 323 | -0.14305263 -0.00595316 -0.00216035 -0.07923735 0.02551001 -0.01474967 324 | -0.0348415 0.05731763] 325 | B weight: [-0.01352069 -0.00995431 -0.02399807 -0.11993797 0.01801177 0.07472972 326 | -0.06405574 -0.11791168 -0.02185591 0.00954476 0.03127189] 327 | yA_accuracy:0.7762237762237763, yA_precision:0.9, yA_recall:0.7159090909090909, yA_f1:0.7974683544303798 328 | yB_accuracy:0.8461538461538461, yB_precision:0.9125, yB_recall:0.8295454545454546, yB_f1:0.869047619047619 329 | **********epoch33********** 330 | ******loss: 0.5421108576046321 ****** 331 | A weight: [ 0.05247929 0.03589356 -0.00912343 -0.00114779 0.07907739 0.00802386 332 | 0.13482942 -0.11185326 -0.039302 0.00172245 0.00670133 -0.10709848 333 | -0.14427397 -0.00710711 -0.00252068 -0.08008496 0.02444735 -0.01593481 334 | -0.0352812 0.05690866] 335 | B weight: [-0.01296356 -0.01115491 -0.02465196 -0.12114825 0.01685124 0.07445123 336 | -0.06495889 -0.1190314 -0.02302396 0.00921015 0.03142157] 337 | yA_accuracy:0.7832167832167832, yA_precision:0.9014084507042254, yA_recall:0.7272727272727273, yA_f1:0.8050314465408807 338 | yB_accuracy:0.8461538461538461, yB_precision:0.9125, yB_recall:0.8295454545454546, yB_f1:0.869047619047619 339 | **********epoch34********** 340 | ******loss: 0.5380539203958539 ****** 341 | A weight: [ 0.05164304 0.03591311 -0.00995508 -0.00196144 0.07913363 0.00747165 342 | 0.13425903 -0.11256728 -0.03928073 0.00152187 0.00550258 -0.10771593 343 | -0.14547658 -0.00824314 -0.00287287 -0.0809177 0.0234014 -0.01710142 344 | -0.03571293 0.05650779] 345 | B weight: [-0.01240715 -0.01233762 -0.0252968 -0.12234021 0.01570865 0.0741814 346 | -0.06584535 -0.12013242 -0.02417269 0.00888393 0.03157254] 347 | yA_accuracy:0.7902097902097902, yA_precision:0.9027777777777778, yA_recall:0.7386363636363636, yA_f1:0.8125 348 | yB_accuracy:0.8461538461538461, yB_precision:0.9125, yB_recall:0.8295454545454546, yB_f1:0.869047619047619 349 | **********epoch35********** 350 | ******loss: 0.5321959164609991 ****** 351 | A weight: [ 0.05083143 0.03599355 -0.01076681 -0.00275641 0.07923366 0.00692745 352 | 0.13371467 -0.11323677 -0.03920036 0.0013301 0.00430393 -0.10832895 353 | -0.14668242 -0.0093717 -0.00321245 -0.08177651 0.0223483 -0.0182607 354 | -0.03613444 0.05608124] 355 | B weight: [-0.01187492 -0.01351176 -0.02593925 -0.12352266 0.01458049 0.07395765 356 | -0.06670303 -0.12119698 -0.02528477 0.00861986 0.03176994] 357 | yA_accuracy:0.8041958041958042, yA_precision:0.9166666666666666, yA_recall:0.75, yA_f1:0.8250000000000001 358 | yB_accuracy:0.8461538461538461, yB_precision:0.9125, yB_recall:0.8295454545454546, yB_f1:0.869047619047619 359 | **********epoch36********** 360 | ******loss: 0.5283706634206641 ****** 361 | A weight: [ 0.05003465 0.0360743 -0.01156343 -0.0035365 0.07933298 0.00639373 362 | 0.13318018 -0.11389438 -0.03911958 0.00114331 0.00312304 -0.10893337 363 | -0.14787005 -0.01048281 -0.00354421 -0.08262093 0.02131137 -0.01940201 364 | -0.03654826 0.05566247] 365 | B weight: [-0.01134336 -0.01466849 -0.02657291 -0.1246873 0.01346978 0.07374211 366 | -0.06754466 -0.12224351 -0.02637818 0.00836373 0.03196837] 367 | yA_accuracy:0.8041958041958042, yA_precision:0.9166666666666666, yA_recall:0.75, yA_f1:0.8250000000000001 368 | yB_accuracy:0.8531468531468531, yB_precision:0.9135802469135802, yB_recall:0.8409090909090909, yB_f1:0.8757396449704142 369 | **********epoch37********** 370 | ******loss: 0.5246666915630323 ****** 371 | A weight: [ 0.04925245 0.03615536 -0.01234519 -0.00430198 0.0794316 0.00587032 372 | 0.13265536 -0.11454033 -0.03903842 0.0009614 0.00195961 -0.10952933 373 | -0.14903974 -0.01157676 -0.00386831 -0.0834512 0.02029035 -0.02052565 374 | -0.03695452 0.05525134] 375 | B weight: [-0.01081249 -0.0158081 -0.02719793 -0.1258344 0.01237624 0.07353461 376 | -0.06837052 -0.12327232 -0.02745324 0.0081154 0.03216779] 377 | yA_accuracy:0.8111888111888111, yA_precision:0.9295774647887324, yA_recall:0.75, yA_f1:0.830188679245283 378 | yB_accuracy:0.8531468531468531, yB_precision:0.9135802469135802, yB_recall:0.8409090909090909, yB_f1:0.8757396449704142 379 | **********epoch38********** 380 | ******loss: 0.521080021130205 ****** 381 | A weight: [ 0.0484846 0.03623671 -0.01311233 -0.00505308 0.0795295 0.00535702 382 | 0.13214006 -0.11517481 -0.03895689 0.00078427 0.00081337 -0.11011696 383 | -0.1501918 -0.01265382 -0.00418486 -0.08426755 0.01928496 -0.02163191 384 | -0.03735336 0.0548477 ] 385 | B weight: [-0.01028228 -0.01693085 -0.02781444 -0.12696426 0.01129958 0.07333502 386 | -0.06918088 -0.12428372 -0.02851025 0.00787471 0.03236817] 387 | yA_accuracy:0.8181818181818182, yA_precision:0.9305555555555556, yA_recall:0.7613636363636364, yA_f1:0.8375 388 | yB_accuracy:0.8531468531468531, yB_precision:0.9135802469135802, yB_recall:0.8409090909090909, yB_f1:0.8757396449704142 389 | **********epoch39********** 390 | ******loss: 0.5176068039058412 ****** 391 | A weight: [ 0.04773084 0.03631833 -0.01386511 -0.00579005 0.07962668 0.00485366 392 | 0.1316341 -0.11579804 -0.03887502 0.00061183 -0.00031596 -0.1106964 393 | -0.1513265 -0.01371426 -0.00449401 -0.08507024 0.01829496 -0.02272108 394 | -0.0377449 0.05445142] 395 | B weight: [-0.00975276 -0.01803702 -0.02842257 -0.12807715 0.01023955 0.07314317 396 | -0.06997602 -0.12527799 -0.02954952 0.00764152 0.03256946] 397 | yA_accuracy:0.8251748251748252, yA_precision:0.9315068493150684, yA_recall:0.7727272727272727, yA_f1:0.84472049689441 398 | yB_accuracy:0.8531468531468531, yB_precision:0.9135802469135802, yB_recall:0.8409090909090909, yB_f1:0.8757396449704142 399 | **********epoch40********** 400 | ******loss: 0.5119513973478543 ****** 401 | A weight: [ 0.04695521 0.03635884 -0.01461782 -0.00653502 0.07970936 0.00425473 402 | 0.13108047 -0.1164789 -0.03885222 0.00034224 -0.00143796 -0.11125769 403 | -0.15245448 -0.01476439 -0.00473868 -0.08586139 0.01731501 -0.02379845 404 | -0.03812171 0.05408315] 405 | B weight: [-0.00924738 -0.01914909 -0.02902992 -0.12919667 0.00917719 0.07298573 406 | -0.07078468 -0.12628347 -0.03060084 0.00737987 0.03277852] 407 | yA_accuracy:0.8251748251748252, yA_precision:0.9315068493150684, yA_recall:0.7727272727272727, yA_f1:0.84472049689441 408 | yB_accuracy:0.8531468531468531, yB_precision:0.9135802469135802, yB_recall:0.8409090909090909, yB_f1:0.8757396449704142 409 | All process done. 410 | -------------------------------------------------------------------------------- /Tutorials/src_explain.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 2, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import math\n", 10 | "import json\n", 11 | "import numpy as np\n", 12 | "import matplotlib.pyplot as plt\n", 13 | "from phe import paillier\n", 14 | "from sklearn.preprocessing import StandardScaler\n", 15 | "from sklearn.datasets import load_breast_cancer\n", 16 | "from sklearn.model_selection import train_test_split\n", 17 | "from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score" 18 | ] 19 | }, 20 | { 21 | "attachments": {}, 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "### load_data()\n", 26 | "1. 加载乳腺癌数据集 \n", 27 | "2. 返回处理好的训练集、训练集标签、测试集、测试集标签\n", 28 | "3. 数据拆分,将数据集随机划分为训练集和测试集,其中random_state为随机数种子,保证每次划分结果一致\n", 29 | "4. 数据标准化,使用StandardScaler进行数据标准化(z-score标准化)" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 3, 35 | "metadata": {}, 36 | "outputs": [], 37 | "source": [ 38 | "def load_data():\n", 39 | " breast = load_breast_cancer()\n", 40 | " X_train, X_test, y_train, y_test = train_test_split(breast.data, breast.target, random_state=1)\n", 41 | " \n", 42 | " std = StandardScaler()\n", 43 | " X_train = std.fit_transform(X_train)\n", 44 | " X_test = std.transform(X_test)\n", 45 | " return X_train, y_train, X_test, y_test" 46 | ] 47 | }, 48 | { 49 | "attachments": {}, 50 | "cell_type": "markdown", 51 | "metadata": {}, 52 | "source": [ 53 | "### vertically_partition_data()\n", 54 | "将样本进一步拆分,分配给guest方A和host方B,A获得部分特征数据,B获得部分特征数据与标签数据。" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": 4, 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [ 63 | "def vertically_partition_data(X, X_test, A_idx, B_idx):\n", 64 | " XA = X[:, A_idx] \n", 65 | " XB = X[:, B_idx] \n", 66 | " XB = np.c_[np.ones(X.shape[0]), XB]\n", 67 | " XA_test = X_test[:, A_idx]\n", 68 | " XB_test = X_test[:, B_idx]\n", 69 | " XB_test = np.c_[np.ones(XB_test.shape[0]), XB_test]\n", 70 | " return XA, XB, XA_test, XB_test" 71 | ] 72 | }, 73 | { 74 | "attachments": {}, 75 | "cell_type": "markdown", 76 | "metadata": {}, 77 | "source": [ 78 | "### 预测函数(sigmoid激活函数)\n", 79 | "$$ y = \\frac{1}{1+e^{-w^{T}x}}$$\n", 80 | "输入测试集与权重矩阵,计算预测值" 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": 5, 86 | "metadata": {}, 87 | "outputs": [], 88 | "source": [ 89 | "pred1,pred2=[],[]\n", 90 | "# sigmoid\n", 91 | "def predict_sigmoid(weights, X_test):\n", 92 | " z = np.dot(weights, X_test.T) \n", 93 | " y_pred = 1/(1+np.exp(-z))\n", 94 | " y_pred[y_pred > 0.5] = 1\n", 95 | " y_pred[y_pred <= 0.5]= 0\n", 96 | " return y_pred" 97 | ] 98 | }, 99 | { 100 | "attachments": {}, 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "### 输入真实标签和预测值,返回值accuracy, precision, recall 和 F1 score" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": 6, 110 | "metadata": {}, 111 | "outputs": [], 112 | "source": [ 113 | "# 计算accuracy...\n", 114 | "def calculate_metrics(y_true, y_pred):\n", 115 | " \"\"\"\n", 116 | " Calculate accuracy, precision, recall and F1 score\n", 117 | " :param y_true: true labels\n", 118 | " :param y_pred: predicted labels\n", 119 | " :return: accuracy, precision, recall, F1 score\n", 120 | " \"\"\"\n", 121 | " accuracy = accuracy_score(y_true, y_pred)\n", 122 | " precision = precision_score(y_true, y_pred)\n", 123 | " recall = recall_score(y_true, y_pred)\n", 124 | " f1 = f1_score(y_true, y_pred)\n", 125 | " return accuracy, precision, recall, f1" 126 | ] 127 | }, 128 | { 129 | "attachments": {}, 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "### 绘制随着eposh轮次增加,每轮loss和accuracy的变化曲线" 134 | ] 135 | }, 136 | { 137 | "cell_type": "code", 138 | "execution_count": 7, 139 | "metadata": {}, 140 | "outputs": [], 141 | "source": [ 142 | "def loss_acc_fig(loss_A, accuracy_A, loss_B, accuracy_B):\n", 143 | " fig = plt.figure(figsize=(12, 6))\n", 144 | " x=[i+1 for i in range(len(loss_A))]\n", 145 | " plt.subplot(1, 2, 1)\n", 146 | " l1=plt.plot(x,loss_A,'r--',label='loss_A')\n", 147 | " l2=plt.plot(x,accuracy_A,'g--',label='accuracy_A')\n", 148 | " plt.plot(x,loss_A,'ro-',x,accuracy_A,'g+-')\n", 149 | " plt.title('Training and validation accuracy')\n", 150 | " plt.xlabel('n_iter')\n", 151 | " plt.ylabel('loss_A/accuracy_A')\n", 152 | " plt.legend()\n", 153 | " \n", 154 | " plt.subplot(1, 2, 2)\n", 155 | " l3=plt.plot(x,loss_B,'r--',label='loss_B')\n", 156 | " l4=plt.plot(x,accuracy_B,'g--',label='accuracy_B')\n", 157 | " plt.plot(x,loss_B,'ro-',x,accuracy_B,'g+-')\n", 158 | " plt.title('Training and validation accuracy')\n", 159 | " plt.xlabel('n_iter')\n", 160 | " plt.ylabel('loss_B/accuracy_B')\n", 161 | " plt.legend()\n", 162 | " plt.show()" 163 | ] 164 | }, 165 | { 166 | "attachments": {}, 167 | "cell_type": "markdown", 168 | "metadata": {}, 169 | "source": [ 170 | "### 设置参与方的父类,各参与方都需要保存模型的参数、一些中间计算结果以及与其他参与方的连接状况。" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": 8, 176 | "metadata": {}, 177 | "outputs": [], 178 | "source": [ 179 | "class Client:\n", 180 | " def __init__(self, config):\n", 181 | " ## 模型参数\n", 182 | " self.config = config\n", 183 | " ## 中间计算结果\n", 184 | " self.data = {}\n", 185 | " ## 与其他节点的连接状况\n", 186 | " self.other_client = {}\n", 187 | " \n", 188 | " ## 与其他参与方建立连接\n", 189 | " def connect(self, client_name, target_client):\n", 190 | " self.other_client[client_name] = target_client\n", 191 | " \n", 192 | " ## 向目标参与方发送数据\n", 193 | " def send_data(self, data, target_client):\n", 194 | " target_client.data.update(data)" 195 | ] 196 | }, 197 | { 198 | "attachments": {}, 199 | "cell_type": "markdown", 200 | "metadata": {}, 201 | "source": [ 202 | "### Host方B在训练过程中既提供特征数据,又提供标签数据。" 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": 9, 208 | "metadata": {}, 209 | "outputs": [], 210 | "source": [ 211 | "class HostB(Client):\n", 212 | " def __init__(self, X, y, config):\n", 213 | " super().__init__(config)\n", 214 | " self.X = X\n", 215 | " self.y = y\n", 216 | " self.weights = np.random.normal(loc=0,scale=1.0/15,size=X.shape[1]) # 权重矩阵初始化\n", 217 | " self.data = {}\n", 218 | " \n", 219 | " def flip_labels(self):\n", 220 | " flip_prob = 1/(1+math.exp(config['epsilon']))\n", 221 | " num_flips = int(flip_prob * len(self.y))\n", 222 | " flip_indices = np.random.choice(len(self.y), num_flips, replace=False)\n", 223 | " self.y[flip_indices] = 1 - self.y[flip_indices]\n", 224 | " \n", 225 | " ## 计算B的梯度\n", 226 | " def compute_u_b(self):\n", 227 | " z_b = np.dot(self.X, self.weights)\n", 228 | " u_b = 0.25 * z_b - self.y + 0.5\n", 229 | " return z_b, u_b\n", 230 | "\n", 231 | " ## 计算加密的梯度\n", 232 | " def compute_encrypted_dJ_b(self, encrypted_u):\n", 233 | " encrypted_dJ_b = self.X.T.dot(encrypted_u) + self.config['lambda'] * self.weights\n", 234 | " return encrypted_dJ_b\n", 235 | "\n", 236 | " ## 参数的更新\n", 237 | " def update_weight(self, dJ_b):\n", 238 | " self.weights = self.weights - self.config[\"lr\"] * dJ_b / len(self.X)\n", 239 | " \n", 240 | " ## B:初始化参数\n", 241 | " def task_0(self):\n", 242 | " try:\n", 243 | " self.flip_labels()\n", 244 | " print(\"Random process of flipping labels is done.\")\n", 245 | " except Exception as e:\n", 246 | " print(\"Wrong 0 in B: %s\" % e)\n", 247 | " \n", 248 | " ## B: step2:计算梯度,使用公钥加密后发送给A\n", 249 | " def task_1(self, Guest_A_name):\n", 250 | " try:\n", 251 | " dt = self.data\n", 252 | " assert \"public_key\" in dt.keys(), \"Error: 'public_key' from C in step 1 not successfully received.\"\n", 253 | " public_key = dt['public_key']\n", 254 | " except Exception as e:\n", 255 | " print(\"B step 1 exception: %s\" % e)\n", 256 | " try:\n", 257 | " z_b, u_b = self.compute_u_b()\n", 258 | " encrypted_u_b = np.asarray([public_key.encrypt(x) for x in u_b])\n", 259 | " dt.update({\"encrypted_u_b\": encrypted_u_b})\n", 260 | " dt.update({\"z_b\": z_b})\n", 261 | " except Exception as e:\n", 262 | " print(\"Wrong 1 in B: %s\" % e)\n", 263 | "\n", 264 | " data_to_A= {\"encrypted_u_b\": encrypted_u_b}\n", 265 | " self.send_data(data_to_A, self.other_client[Guest_A_name])\n", 266 | "\t\n", 267 | " ## B: step3、4:B将加密的梯度加上随机数后发送给C来进行解密\n", 268 | " def task_2(self,Sever_C_name):\n", 269 | " try:\n", 270 | " dt = self.data\n", 271 | " assert \"encrypted_u_a\" in dt.keys(), \"Error: 'encrypt_u_a' from A in step 1 not successfully received.\"\n", 272 | " encrypted_u_a = dt['encrypted_u_a']\n", 273 | " encrypted_u = encrypted_u_a + dt['encrypted_u_b']\n", 274 | " encrypted_dJ_b = self.compute_encrypted_dJ_b(encrypted_u)\n", 275 | " mask = np.random.rand(len(encrypted_dJ_b))\n", 276 | " encrypted_masked_dJ_b = encrypted_dJ_b + mask\n", 277 | " dt.update({\"mask\": mask})\n", 278 | " except Exception as e:\n", 279 | " print(\"B step 2 exception: %s\" % e)\n", 280 | " try:\n", 281 | " assert \"encrypted_z_a_square\" in dt.keys(), \"Error: 'encrypted_z_a_square' from A in step 1 not successfully received.\"\n", 282 | " encrypted_z = 4*encrypted_u_a + dt['z_b']\n", 283 | " encrypted_loss = np.sum((0.5-self.y)*encrypted_z + 0.125*dt[\"encrypted_z_a_square\"] + 0.125*dt[\"z_b\"] * (encrypted_z+4*encrypted_u_a))\n", 284 | " except Exception as e:\n", 285 | " print(\"B step 2 exception: %s\" % e)\n", 286 | " data_to_C = {\"encrypted_masked_dJ_b\": encrypted_masked_dJ_b, \"encrypted_loss\": encrypted_loss}\n", 287 | " self.send_data(data_to_C, self.other_client[Sever_C_name])\n", 288 | "\t\n", 289 | " ## B: step6:根据C发送来的数据减去随机数后更新自己的参数\n", 290 | " def task_3(self):\n", 291 | " try:\n", 292 | " dt = self.data\n", 293 | " assert \"masked_dJ_b\" in dt.keys(), \"Error: 'masked_dJ_b' from C in step 2 not successfully received.\"\n", 294 | " masked_dJ_b = dt['masked_dJ_b']\n", 295 | " dJ_b = masked_dJ_b - dt['mask']\n", 296 | " self.update_weight(dJ_b)\n", 297 | " except Exception as e:\n", 298 | " print(\"A step 3 exception: %s\" % e)\n", 299 | " print(f\"B weight: {self.weights}\")\n", 300 | " return\n", 301 | "\n", 302 | " def task_flipback(self,Guest_A_name):\n", 303 | " try:\n", 304 | " dt = self.data\n", 305 | " assert \"public_key\" in dt.keys(), \"Error: 'public_key' from C in step 1 not successfully received.\"\n", 306 | " public_key = dt['public_key']\n", 307 | " except Exception as e:\n", 308 | " print(\"B step 1 exception: %s\" % e)\n", 309 | " try:\n", 310 | " yB_pred = predict_sigmoid(self.weights, self.X)\n", 311 | " #y_dist记为yB_pred和真实的y之间的差距,选出其中差距最大的前2%的样本,将其标签翻转\n", 312 | " y_dist = np.abs(yB_pred - self.y)\n", 313 | " flip_indices = np.argsort(y_dist)[-int(0.02*len(y_dist)):]\n", 314 | " self.y[flip_indices] = 1 - self.y[flip_indices]\n", 315 | "\n", 316 | " z_b, u_b = self.compute_u_b()\n", 317 | " encrypted_u_b = np.asarray([public_key.encrypt(x) for x in u_b])\n", 318 | " dt.update({\"encrypted_u_b\": encrypted_u_b})\n", 319 | " dt.update({\"z_b\": z_b})\n", 320 | " except Exception as e:\n", 321 | " print(\"Wrong 1 in B: %s\" % e)\n", 322 | "\n", 323 | " data_to_A= {\"encrypted_u_b\": encrypted_u_b}\n", 324 | " self.send_data(data_to_A, self.other_client[Guest_A_name])" 325 | ] 326 | }, 327 | { 328 | "attachments": {}, 329 | "cell_type": "markdown", 330 | "metadata": {}, 331 | "source": [ 332 | "### GuestA在训练过程中仅提供特征数据。" 333 | ] 334 | }, 335 | { 336 | "cell_type": "code", 337 | "execution_count": 10, 338 | "metadata": {}, 339 | "outputs": [], 340 | "source": [ 341 | "class GuestA(Client):\n", 342 | " def __init__(self, X, config):\n", 343 | " super().__init__(config)\n", 344 | " self.X = X\n", 345 | " self.weights = np.random.normal(loc=0,scale=1.0/15,size=X.shape[1]) #参数矩阵的初始化\n", 346 | " \n", 347 | " ## 就散A的梯度\n", 348 | " def compute_z_a(self):\n", 349 | " z_a = np.dot(self.X, self.weights)\n", 350 | " return z_a\n", 351 | " \n", 352 | "\t## 加密梯度的计算,对应step4\n", 353 | " def compute_encrypted_dJ_a(self, encrypted_u):\n", 354 | " encrypted_dJ_a = self.X.T.dot(encrypted_u) + self.config['lambda'] * self.weights\n", 355 | " return encrypted_dJ_a\n", 356 | " \n", 357 | "\t## 参数的更新\n", 358 | " def update_weight(self, dJ_a):\n", 359 | " self.weights = self.weights - self.config[\"lr\"] * dJ_a / len(self.X)\n", 360 | " return\n", 361 | "\n", 362 | " ## A: step2:计算梯度,使用公钥加密后发送给B\n", 363 | " def task_1(self, Host_B_name):\n", 364 | " dt = self.data\n", 365 | " assert \"public_key\" in dt.keys(), \"Error: 'public_key' from C in step 1 not successfully received.\"\n", 366 | " public_key = dt['public_key']\n", 367 | " z_a = self.compute_z_a()\n", 368 | " u_a = 0.25 * z_a\n", 369 | " z_a_square = z_a ** 2\n", 370 | " encrypted_u_a = np.asarray([public_key.encrypt(x) for x in u_a])\n", 371 | " encrypted_z_a_square = np.asarray([public_key.encrypt(x) for x in z_a_square])\n", 372 | " dt.update({\"encrypted_u_a\": encrypted_u_a})\n", 373 | " data_to_B = {\"encrypted_u_a\": encrypted_u_a, \"encrypted_z_a_square\": encrypted_z_a_square}\n", 374 | " self.send_data(data_to_B, self.other_client[Host_B_name])\n", 375 | " \n", 376 | " ## A: step3、4:A将加密的梯度加上随机数后发送给C来进行解密\n", 377 | " def task_2(self, Sever_C_name):\n", 378 | " dt = self.data\n", 379 | " assert \"encrypted_u_b\" in dt.keys(), \"Error: 'encrypted_u_b' from B in step 1 not successfully received.\"\n", 380 | " encrypted_u_b = dt['encrypted_u_b']\n", 381 | " encrypted_u = encrypted_u_b + dt['encrypted_u_a']\n", 382 | " encrypted_dJ_a = self.compute_encrypted_dJ_a(encrypted_u)\n", 383 | " mask = np.random.rand(len(encrypted_dJ_a))\n", 384 | " encrypted_masked_dJ_a = encrypted_dJ_a + mask\n", 385 | " dt.update({\"mask\": mask})\n", 386 | " data_to_C = {'encrypted_masked_dJ_a': encrypted_masked_dJ_a}\n", 387 | " self.send_data(data_to_C, self.other_client[Sever_C_name])\n", 388 | " \n", 389 | " ## A: step6:根据C发送来的数据减去随机数后更新自己的参数\n", 390 | " def task_3(self):\n", 391 | " dt = self.data\n", 392 | " assert \"masked_dJ_a\" in dt.keys(), \"Error: 'masked_dJ_a' from C in step 2 not successfully received.\"\n", 393 | " masked_dJ_a = dt['masked_dJ_a']\n", 394 | " dJ_a = masked_dJ_a - dt['mask']\n", 395 | " self.update_weight(dJ_a)\n", 396 | " print(f\"A weight: {self.weights}\")\n", 397 | " return" 398 | ] 399 | }, 400 | { 401 | "attachments": {}, 402 | "cell_type": "markdown", 403 | "metadata": {}, 404 | "source": [ 405 | "### 参与方C在整个训练过程中主要的作用就是分发秘钥,以及最后的对A和B加密梯度的解密。" 406 | ] 407 | }, 408 | { 409 | "cell_type": "code", 410 | "execution_count": 11, 411 | "metadata": {}, 412 | "outputs": [], 413 | "source": [ 414 | "class SeverC(Client):\n", 415 | " \"\"\"\n", 416 | " Client C as trusted dealer.\n", 417 | " \"\"\"\n", 418 | " def __init__(self, A_d_shape, B_d_shape, config):\n", 419 | " super().__init__(config)\n", 420 | " self.A_data_shape = A_d_shape\n", 421 | " self.B_data_shape = B_d_shape\n", 422 | " self.public_key = None\n", 423 | " self.private_key = None\n", 424 | " ## 保存训练中的损失值(泰展开近似)\n", 425 | " self.loss = []\n", 426 | "\t\n", 427 | " ## C: step1:生成密钥对,并分发密钥\n", 428 | " def task_1(self, Guest_A_name, Host_B_name):\n", 429 | " try:\n", 430 | " public_key, private_key = paillier.generate_paillier_keypair()\n", 431 | " self.public_key = public_key\n", 432 | " self.private_key = private_key\n", 433 | " except Exception as e:\n", 434 | " print(\"C step 1 error 1: %s\" % e)\n", 435 | "\n", 436 | " data_to_AB = {\"public_key\": public_key}\n", 437 | " self.send_data(data_to_AB, self.other_client[Guest_A_name])\n", 438 | " self.send_data(data_to_AB, self.other_client[Host_B_name])\n", 439 | " return\n", 440 | "\t\n", 441 | " ## C: step5:C获得加密梯度进行后进行解密再返还A和B。\n", 442 | " def task_2(self, Guest_A_name, Host_B_name):\n", 443 | " try:\n", 444 | " dt = self.data\n", 445 | " assert \"encrypted_masked_dJ_a\" in dt.keys() and \"encrypted_masked_dJ_b\" in dt.keys(), \"Error: 'masked_dJ_a' from A or 'masked_dJ_b' from B in step 2 not successfully received.\"\n", 446 | " encrypted_masked_dJ_a = dt['encrypted_masked_dJ_a']\n", 447 | " encrypted_masked_dJ_b = dt['encrypted_masked_dJ_b']\n", 448 | " masked_dJ_a = np.asarray([self.private_key.decrypt(x) for x in encrypted_masked_dJ_a])\n", 449 | " masked_dJ_b = np.asarray([self.private_key.decrypt(x) for x in encrypted_masked_dJ_b])\n", 450 | " except Exception as e:\n", 451 | " print(\"C step 2 exception: %s\" % e)\n", 452 | "\n", 453 | " try:\n", 454 | " assert \"encrypted_loss\" in dt.keys(), \"Error: 'encrypted_loss' from B in step 2 not successfully received.\"\n", 455 | " encrypted_loss = dt['encrypted_loss']\n", 456 | " loss = self.private_key.decrypt(encrypted_loss) / self.A_data_shape[0] + math.log(2)\n", 457 | " print(\"******loss: \", loss, \"******\")\n", 458 | " self.loss.append(loss)\n", 459 | " except Exception as e:\n", 460 | " print(\"C step 2 exception: %s\" % e)\n", 461 | "\n", 462 | " data_to_A = {\"masked_dJ_a\": masked_dJ_a}\n", 463 | " data_to_B = {\"masked_dJ_b\": masked_dJ_b}\n", 464 | " self.send_data(data_to_A, self.other_client[Guest_A_name])\n", 465 | " self.send_data(data_to_B, self.other_client[Host_B_name])\n", 466 | " return" 467 | ] 468 | }, 469 | { 470 | "attachments": {}, 471 | "cell_type": "markdown", 472 | "metadata": {}, 473 | "source": [ 474 | "### 主运行函数:垂直逻辑回归做预测" 475 | ] 476 | }, 477 | { 478 | "cell_type": "code", 479 | "execution_count": 12, 480 | "metadata": {}, 481 | "outputs": [], 482 | "source": [ 483 | "def vertical_logistic_regression(X, y, X_test, y_test, config):\n", 484 | " \n", 485 | " ## 获取数据\n", 486 | " XA, XB, XA_test, XB_test = vertically_partition_data(X, X_test, config['A_idx'], config['B_idx'])\n", 487 | " print('XA:',XA.shape, ' XB:',XB.shape)\n", 488 | " \n", 489 | " ## 各参与方的初始化\n", 490 | " Guest_A = GuestA(XA, config)\n", 491 | " print(\"Guest_A successfully initialized.\")\n", 492 | " Host_B = HostB(XB, y, config)\n", 493 | " print(\"Host_B successfully initialized.\")\n", 494 | " Sever_C = SeverC(XA.shape, XB.shape, config)\n", 495 | " print(\"Sever_C successfully initialized.\")\n", 496 | " \n", 497 | " ## 各参与方之间连接的建立\n", 498 | " Guest_A.connect(\"B\", Host_B)\n", 499 | " Guest_A.connect(\"C\", Sever_C)\n", 500 | " Host_B.connect(\"A\", Guest_A)\n", 501 | " Host_B.connect(\"C\", Sever_C)\n", 502 | " Sever_C.connect(\"A\", Guest_A)\n", 503 | " Sever_C.connect(\"B\", Host_B)\n", 504 | " \n", 505 | " ## 训练\n", 506 | " accuracy_A, accuracy_B = [],[]\n", 507 | " Host_B.task_0()\n", 508 | " for i in range(1,config['n_iter']+1):\n", 509 | " print(f\"**********epoch{i}**********\")\n", 510 | " Sever_C.task_1(\"A\", \"B\")\n", 511 | " Guest_A.task_1(\"B\")\n", 512 | " if i%5 == 0:\n", 513 | " Host_B.task_flipback(\"A\")\n", 514 | " else:\n", 515 | " Host_B.task_1(\"A\") \n", 516 | " Guest_A.task_2(\"C\")\n", 517 | " Host_B.task_2(\"C\")\n", 518 | " Sever_C.task_2(\"A\", \"B\")\n", 519 | " Guest_A.task_3()\n", 520 | " Host_B.task_3()\n", 521 | " \n", 522 | " ### A做预测\n", 523 | " yA_pred = predict_sigmoid(Guest_A.weights, XA_test)\n", 524 | " yA_accuracy, yA_precision, yA_recall, yA_f1 = calculate_metrics(y_test, yA_pred)\n", 525 | " print(f\"yA_accuracy:{yA_accuracy}, yA_precision:{yA_precision}, yA_recall:{yA_recall}, yA_f1:{yA_f1}\")\n", 526 | " accuracy_A.append(yA_accuracy)\n", 527 | " \n", 528 | " ### B做预测\n", 529 | " yB_pred = predict_sigmoid(Host_B.weights, XB_test)\n", 530 | " yB_accuracy, yB_precision, yB_recall, yB_f1 = calculate_metrics(y_test, yB_pred)\n", 531 | " print(f\"yB_accuracy:{yB_accuracy}, yB_precision:{yB_precision}, yB_recall:{yB_recall}, yB_f1:{yB_f1}\")\n", 532 | " accuracy_B.append(yB_accuracy)\n", 533 | " \n", 534 | " print(\"All process done.\")\n", 535 | " \n", 536 | " loss_acc_fig(Sever_C.loss, accuracy_A, Sever_C.loss, accuracy_B)\n", 537 | " \n", 538 | " return True" 539 | ] 540 | }, 541 | { 542 | "attachments": {}, 543 | "cell_type": "markdown", 544 | "metadata": {}, 545 | "source": [ 546 | "这里仅以10轮作为演示" 547 | ] 548 | }, 549 | { 550 | "cell_type": "code", 551 | "execution_count": 14, 552 | "metadata": {}, 553 | "outputs": [ 554 | { 555 | "name": "stdout", 556 | "output_type": "stream", 557 | "text": [ 558 | "XA: (426, 20) XB: (426, 11)\n", 559 | "Guest_A successfully initialized.\n", 560 | "Host_B successfully initialized.\n", 561 | "Sever_C successfully initialized.\n", 562 | "Random process of flipping labels is done.\n", 563 | "**********epoch1**********\n", 564 | "******loss: 0.686823026878258 ******\n", 565 | "A weight: [ 0.01482629 -0.01698578 -0.04517383 -0.07305028 -0.00398198 0.04963296\n", 566 | " 0.08551975 -0.06423003 0.02535085 -0.05523504 0.09215472 -0.09176684\n", 567 | " -0.06796933 -0.06867426 -0.04499598 -0.08254297 0.01033735 0.19052262\n", 568 | " -0.03285242 -0.17642941]\n", 569 | "B weight: [-0.01426642 -0.00930729 -0.00899131 0.07220739 0.083992 -0.10868632\n", 570 | " 0.07701995 0.02237228 -0.07349146 -0.10731313 0.00860214]\n", 571 | "yA_accuracy:0.6853146853146853, yA_precision:0.7590361445783133, yA_recall:0.7159090909090909, yA_f1:0.736842105263158\n", 572 | "yB_accuracy:0.5034965034965035, yB_precision:0.6268656716417911, yB_recall:0.4772727272727273, yB_f1:0.5419354838709678\n", 573 | "**********epoch2**********\n", 574 | "******loss: 0.6772040828223505 ******\n", 575 | "A weight: [ 0.01353075 -0.01685961 -0.0464497 -0.07432274 -0.00367063 0.04904396\n", 576 | " 0.08492225 -0.06515835 0.02554385 -0.05522016 0.09023151 -0.09279522\n", 577 | " -0.06989221 -0.07048097 -0.04571254 -0.08381662 0.00879998 0.18866611\n", 578 | " -0.03366575 -0.17691452]\n", 579 | "B weight: [-0.01359097 -0.01116988 -0.00997825 0.07033239 0.08219399 -0.10920928\n", 580 | " 0.0757475 0.02077178 -0.07528311 -0.10781565 0.00903104]\n", 581 | "yA_accuracy:0.6853146853146853, yA_precision:0.7590361445783133, yA_recall:0.7159090909090909, yA_f1:0.736842105263158\n", 582 | "yB_accuracy:0.5034965034965035, yB_precision:0.6268656716417911, yB_recall:0.4772727272727273, yB_f1:0.5419354838709678\n", 583 | "**********epoch3**********\n", 584 | "******loss: 0.6678883981308328 ******\n", 585 | "A weight: [ 0.01225828 -0.01673337 -0.04770213 -0.07557193 -0.00336106 0.04847013\n", 586 | " 0.08433898 -0.06606902 0.0257369 -0.05519883 0.08833635 -0.09381004\n", 587 | " -0.07178638 -0.07226013 -0.04641682 -0.08506824 0.00728742 0.18683758\n", 588 | " -0.03446694 -0.17738821]\n", 589 | "B weight: [-0.01291639 -0.01300501 -0.01095147 0.06848543 0.08042348 -0.10971953\n", 590 | " 0.07449953 0.01919893 -0.07704573 -0.10830598 0.00946061]\n", 591 | "yA_accuracy:0.6993006993006993, yA_precision:0.7710843373493976, yA_recall:0.7272727272727273, yA_f1:0.7485380116959065\n", 592 | "yB_accuracy:0.5174825174825175, yB_precision:0.6376811594202898, yB_recall:0.5, yB_f1:0.5605095541401274\n", 593 | "**********epoch4**********\n", 594 | "******loss: 0.658866073196239 ******\n", 595 | "A weight: [ 0.01100849 -0.01660707 -0.04893149 -0.07679824 -0.00305327 0.04791119\n", 596 | " 0.08376968 -0.06696236 0.02592997 -0.0551712 0.0864688 -0.09481152\n", 597 | " -0.07365229 -0.07401218 -0.04710904 -0.0862982 0.00579928 0.18503658\n", 598 | " -0.03525619 -0.1778507 ]\n", 599 | "B weight: [-0.01224266 -0.01481312 -0.0119112 0.06666608 0.07868002 -0.11021732\n", 600 | " 0.07327561 0.01765326 -0.07877981 -0.10878433 0.00989078]\n", 601 | "yA_accuracy:0.7062937062937062, yA_precision:0.7804878048780488, yA_recall:0.7272727272727273, yA_f1:0.7529411764705882\n", 602 | "yB_accuracy:0.5244755244755245, yB_precision:0.6470588235294118, yB_recall:0.5, yB_f1:0.5641025641025642\n", 603 | "**********epoch5**********\n", 604 | "******loss: 0.6495194674203588 ******\n", 605 | "A weight: [ 0.00980668 -0.01652834 -0.05011509 -0.07797639 -0.00283061 0.04736732\n", 606 | " 0.08324222 -0.06783077 0.02603753 -0.05514732 0.0847001 -0.09574019\n", 607 | " -0.07542288 -0.07567662 -0.04777956 -0.08746147 0.00440451 0.18331658\n", 608 | " -0.03600569 -0.17825972]\n", 609 | "B weight: [-0.01159327 -0.01652641 -0.0127991 0.06494071 0.07702373 -0.1107565\n", 610 | " 0.07209712 0.0161756 -0.08045188 -0.10927807 0.01030146]\n", 611 | "yA_accuracy:0.7202797202797203, yA_precision:0.7857142857142857, yA_recall:0.75, yA_f1:0.7674418604651163\n", 612 | "yB_accuracy:0.5384615384615384, yB_precision:0.6617647058823529, yB_recall:0.5113636363636364, yB_f1:0.5769230769230769\n", 613 | "**********epoch6**********\n", 614 | "******loss: 0.6416026046583554 ******\n", 615 | "A weight: [ 0.00862622 -0.01644943 -0.051277 -0.07913304 -0.00260942 0.04683748\n", 616 | " 0.08272792 -0.06868284 0.0261453 -0.05511745 0.08295724 -0.09665642\n", 617 | " -0.07716701 -0.07731566 -0.04843872 -0.08860448 0.00303258 0.18162237\n", 618 | " -0.03674397 -0.17865825]\n", 619 | "B weight: [-0.0109447 -0.0182144 -0.01367439 0.06324119 0.07539279 -0.11128384\n", 620 | " 0.07094124 0.01472346 -0.08209714 -0.10976046 0.01071282]\n", 621 | "yA_accuracy:0.7412587412587412, yA_precision:0.8, yA_recall:0.7727272727272727, yA_f1:0.7861271676300577\n", 622 | "yB_accuracy:0.5454545454545454, yB_precision:0.6666666666666666, yB_recall:0.5227272727272727, yB_f1:0.5859872611464967\n", 623 | "**********epoch7**********\n", 624 | "******loss: 0.6339352347440883 ******\n", 625 | "A weight: [ 0.00746675 -0.01637036 -0.05241757 -0.08026854 -0.00238969 0.04632141\n", 626 | " 0.08222654 -0.06951886 0.02625328 -0.05508171 0.0812398 -0.0975604\n", 627 | " -0.07888512 -0.07892973 -0.04908671 -0.08972756 0.00168311 0.17995351\n", 628 | " -0.03747124 -0.17904649]\n", 629 | "B weight: [-0.01029696 -0.01987749 -0.01453728 0.0615671 0.07378679 -0.11179956\n", 630 | " 0.06980755 0.01329642 -0.08371605 -0.11023171 0.0111248 ]\n", 631 | "yA_accuracy:0.7482517482517482, yA_precision:0.8023255813953488, yA_recall:0.7840909090909091, yA_f1:0.7931034482758621\n", 632 | "yB_accuracy:0.5664335664335665, yB_precision:0.6911764705882353, yB_recall:0.5340909090909091, yB_f1:0.6025641025641026\n", 633 | "**********epoch8**********\n", 634 | "******loss: 0.6265092102280626 ******\n", 635 | "A weight: [ 0.00632792 -0.01629113 -0.05353716 -0.08138324 -0.00217144 0.04581886\n", 636 | " 0.08173782 -0.0703391 0.02636142 -0.05504024 0.07954738 -0.09845232\n", 637 | " -0.08057762 -0.08051921 -0.04972374 -0.09083105 0.00035572 0.1783096\n", 638 | " -0.03818767 -0.17942464]\n", 639 | "B weight: [-0.00965004 -0.02151609 -0.01538796 0.05991803 0.07220533 -0.11230388\n", 640 | " 0.06869569 0.01189403 -0.08530905 -0.11069203 0.01153736]\n", 641 | "yA_accuracy:0.7622377622377622, yA_precision:0.8068181818181818, yA_recall:0.8068181818181818, yA_f1:0.8068181818181818\n", 642 | "yB_accuracy:0.5734265734265734, yB_precision:0.6956521739130435, yB_recall:0.5454545454545454, yB_f1:0.6114649681528662\n", 643 | "**********epoch9**********\n", 644 | "******loss: 0.6193166523695676 ******\n", 645 | "A weight: [ 0.0052094 -0.01621177 -0.05463611 -0.08247747 -0.00195467 0.04532957\n", 646 | " 0.08126154 -0.07114386 0.0264697 -0.05499317 0.07787958 -0.09933237\n", 647 | " -0.08224492 -0.0820845 -0.05034999 -0.0919153 -0.00094997 0.17669021\n", 648 | " -0.03889346 -0.17979288]\n", 649 | "B weight: [-0.00900395 -0.02313057 -0.01622662 0.05829359 0.07064803 -0.112797\n", 650 | " 0.06760528 0.01051589 -0.08687655 -0.1111416 0.01195045]\n", 651 | "yA_accuracy:0.7622377622377622, yA_precision:0.8068181818181818, yA_recall:0.8068181818181818, yA_f1:0.8068181818181818\n", 652 | "yB_accuracy:0.5874125874125874, yB_precision:0.7101449275362319, yB_recall:0.5568181818181818, yB_f1:0.6242038216560509\n", 653 | "**********epoch10**********\n", 654 | "******loss: 0.6085179646835622 ******\n", 655 | "A weight: [ 0.00416799 -0.01615523 -0.05566854 -0.08348075 -0.00183429 0.04481698\n", 656 | " 0.08078028 -0.07194932 0.02655625 -0.05499354 0.07633646 -0.10017789\n", 657 | " -0.08379591 -0.08352248 -0.05103117 -0.09299054 -0.0022195 0.17512725\n", 658 | " -0.03959044 -0.18022185]\n", 659 | "B weight: [-0.00838216 -0.0246282 -0.01704493 0.05678108 0.06920357 -0.11333819\n", 660 | " 0.06650494 0.00918392 -0.08838219 -0.11162425 0.01222255]\n", 661 | "yA_accuracy:0.7762237762237763, yA_precision:0.8181818181818182, yA_recall:0.8181818181818182, yA_f1:0.8181818181818182\n", 662 | "yB_accuracy:0.6083916083916084, yB_precision:0.7285714285714285, yB_recall:0.5795454545454546, yB_f1:0.6455696202531646\n", 663 | "All process done.\n" 664 | ] 665 | }, 666 | { 667 | "data": { 668 | "image/png": "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xqstj4nx1kUkqEKR20yZMoV58+YxatQo7r777my5ZrCnjM9Vmn7Q9LBt19e+nh71e5C0P4krR1x52P7OdTvTuW5nNiVtot2n7Q7ZN7Xz1GN+5rXXXsuqVavYs2cPvXr1olu3bkyYMIFHH32UlJQUSpUqxXfffcfOnTu56667mDNnDmZG7969adu2LYULF2bnzp0AjBo1iq+++ooPPviAzp07U7JkSX777TfOPfdcbrjhBu655x52795NoUKFGDJkCKeddhopKSk89NBDTJw4ETPjtttuo1atWgwYMIDPP/8cgEmTJvHWW28xZkz64dQ9zjlGjRrFpEmTuOiii9izZw8FCxY85r2L5AZvz3mb7l93x+F49KJH6du8r98hiR+iouDll70k/NFH4csv4brroEQJLyk/kAQkJHjT18Ohk/iI+MCPvAbyRm6TVmJiIiVKlMjUvR+LEm+fvf/++5QsWZLdu3dTv359WrVqxW233cb06dOpVq0aW7ZsAeDpp5+mWLFi/PHHHwBs3br1mNf++++/mTx5MpGRkSQmJjJ9+nSioqKYPHkyjz76KKNHj2bw4MEsX76c3377jaioKLZs2UKJEiW488472bhxI6VLl2bIkCF06dLliJ8zc+ZMqlWrRvXq1WnatCnjx4+nTZs22fMFifjEOcdbc96i14ReFIwqyKjrR3FljcP/SEmYiYqCF1+E556DkSOhY8fDj0lK8qavV+ItYSov5DYAzZo1wznHsmXL+PTTT0/8i0GJ9yGO9j+56HzRR91fKrpUpv8nmNbrr79+8H9fq1atYvDgwTRu3Jhq1aoBULJkSQAmT57Mxx9/fPC8zPzP67rrriMyMhKA7du306lTJ/755x/MjP379x+87h133EFUVNQhn9exY0eGDx9Oly5dmDVrFsOGDTvi54wcOZL27dsD0L59ez788EMl3pKrJe5JpMWIFsxaPYuralzFiDYjKFawmN9hhYSZtQBeAyKBd51zz2dwTFPgVSAfsMk518TMTgM+SXPYKcCTzrlXzSweuA3YGNj3qHNufLDuISQiI71xwG++GTKaiG7lytDHJJKOH3kN5I3cBrymJqVKlWLp0qVcfPHFNG3alMInOMGWEm8fTZ06lcmTJzNr1iyio6Np2rQpderU4a+//jrsWOccZnbY9rTb9qQb7uqkk046uPzEE0/QrFkzPv/8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", 669 | "text/plain": [ 670 | "
" 671 | ] 672 | }, 673 | "metadata": { 674 | "needs_background": "light" 675 | }, 676 | "output_type": "display_data" 677 | }, 678 | { 679 | "data": { 680 | "text/plain": [ 681 | "True" 682 | ] 683 | }, 684 | "execution_count": 14, 685 | "metadata": {}, 686 | "output_type": "execute_result" 687 | } 688 | ], 689 | "source": [ 690 | "X, y, X_test, y_test = load_data()\n", 691 | "config = {\n", 692 | " \"n_iter\": 10,\n", 693 | " \"lambda\": 2,\n", 694 | " \"lr\": 0.005,\n", 695 | " \"A_idx\": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29],\n", 696 | " \"B_idx\": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n", 697 | " \"epsilon\": 8.0\n", 698 | " }\n", 699 | "vertical_logistic_regression(X, y, X_test, y_test, config)" 700 | ] 701 | }, 702 | { 703 | "attachments": {}, 704 | "cell_type": "markdown", 705 | "metadata": {}, 706 | "source": [] 707 | } 708 | ], 709 | "metadata": { 710 | "kernelspec": { 711 | "display_name": "base", 712 | "language": "python", 713 | "name": "python3" 714 | }, 715 | "language_info": { 716 | "codemirror_mode": { 717 | "name": "ipython", 718 | "version": 3 719 | }, 720 | "file_extension": ".py", 721 | "mimetype": "text/x-python", 722 | "name": "python", 723 | "nbconvert_exporter": "python", 724 | "pygments_lexer": "ipython3", 725 | "version": "3.9.7" 726 | }, 727 | "orig_nbformat": 4 728 | }, 729 | "nbformat": 4, 730 | "nbformat_minor": 2 731 | } 732 | --------------------------------------------------------------------------------