(self, host_components, data_loader: FTLDataLoader, epoch_idx, local_round=-1)
compute backward gradients using host components
compute backward gradients using host components
compute backward gradients using host components
def compute_backward_gradients(self, host_components, data_loader: FTLDataLoader, epoch_idx, local_round=-1):

        """
        compute backward gradients using host components
        """

        # they are Paillier tensors or np array
        overlap_ub, overlap_ub_2, mapping_comp_b = host_components[0], host_components[1], host_components[2]

        y_overlap_2_phi = np.expand_dims(self.overlap_y_2 * self.phi, axis=1)

        if self.mode == 'plain':

            loss_grads_const_part1 = 0.25 * np.squeeze(np.matmul(y_overlap_2_phi, overlap_ub_2), axis=1)
            loss_grads_const_part2 = self.overlap_y * overlap_ub

            const = np.sum(loss_grads_const_part1, axis=0) - 0.5 * np.sum(loss_grads_const_part2, axis=0)

            grad_a_nonoverlap = self.alpha * const * data_loader.y[data_loader.get_non_overlap_indexes()] / self.data_num
            grad_a_overlap = self.alpha * const * self.overlap_y / self.data_num + mapping_comp_b

            return np.concatenate([grad_a_overlap, grad_a_nonoverlap], axis=0)

        elif self.mode == 'encrypted':

            loss_grads_const_part1 = overlap_ub_2.matmul_3d(0.25 * y_overlap_2_phi, multiply='right')
            loss_grads_const_part1 = loss_grads_const_part1.squeeze(axis=1)

            if self.overlap_y_pt is None:
                self.overlap_y_pt = PaillierTensor(self.overlap_y, partitions=self.partitions)

            loss_grads_const_part2 = overlap_ub * self.overlap_y_pt

            encrypted_const = loss_grads_const_part1.reduce_sum() - 0.5 * loss_grads_const_part2.reduce_sum()

            grad_a_overlap = self.overlap_y_pt.map_ndarray_product((self.alpha/self.data_num * encrypted_const)) + mapping_comp_b

            const, grad_a_overlap = self.decrypt_inter_result(encrypted_const, grad_a_overlap, epoch_idx=epoch_idx
                                                              , local_round=local_round)

            self.decrypt_host_data(epoch_idx, local_round=local_round)

            grad_a_nonoverlap = self.alpha * const * data_loader.y[data_loader.get_non_overlap_indexes()]/self.data_num

            return np.concatenate([grad_a_overlap.numpy(), grad_a_nonoverlap], axis=0)
def compute_backward_gradients ( self , host_components , data_loader : FTLDataLoader , epoch_idx , local_round = - 1 ) : # they are Paillier tensors or np array overlap_ub , overlap_ub_2 , mapping_comp_b = host_components [ 0 ] , host_components [ 1 ] , host_components [ 2 ] y_overlap_2_phi = np . expand_dims ( self . overlap_y_2 * self . phi , axis = 1 ) if self . mode == 'plain' : loss_grads_const_part1 = 0.25 * np . squeeze ( np . matmul ( y_overlap_2_phi , overlap_ub_2 ) , axis = 1 ) loss_grads_const_part2 = self . overlap_y * overlap_ub const = np . sum ( loss_grads_const_part1 , axis = 0 ) - 0.5 * np . sum ( loss_grads_const_part2 , axis = 0 ) grad_a_nonoverlap = self . alpha * const * data_loader . y [ data_loader . get_non_overlap_indexes ( ) ] / self . data_num grad_a_overlap = self . alpha * const * self . overlap_y / self . data_num + mapping_comp_b return np . concatenate ( [ grad_a_overlap , grad_a_nonoverlap ] , axis = 0 ) elif self . mode == 'encrypted' : loss_grads_const_part1 = overlap_ub_2 . matmul_3d ( 0.25 * y_overlap_2_phi , multiply = 'right' ) loss_grads_const_part1 = loss_grads_const_part1 . squeeze ( axis = 1 ) if self . overlap_y_pt is None : self . overlap_y_pt = PaillierTensor ( self . overlap_y , partitions = self . partitions ) loss_grads_const_part2 = overlap_ub * self . overlap_y_pt encrypted_const = loss_grads_const_part1 . reduce_sum ( ) - 0.5 * loss_grads_const_part2 . reduce_sum ( ) grad_a_overlap = self . overlap_y_pt . map_ndarray_product ( ( self . alpha / self . data_num * encrypted_const ) ) + mapping_comp_b const , grad_a_overlap = self . decrypt_inter_result ( encrypted_const , grad_a_overlap , epoch_idx = epoch_idx , local_round = local_round ) self . decrypt_host_data ( epoch_idx , local_round = local_round ) grad_a_nonoverlap = self . alpha * const * data_loader . y [ data_loader . get_non_overlap_indexes ( ) ] / self . data_num return np . concatenate ( [ grad_a_overlap . numpy ( ) , grad_a_nonoverlap ] , axis = 0 )