Esempio n. 1
0
    def generate_gradient(self, input, target):
        target = TensorBase(np.array(target).astype('float64'))
        input = TensorBase(np.array(input).astype('float64'))
        pred = self.forward(input)

        target_v = target

        if(self.pubkey is not None and self.encrypted):
            target_v = self.pubkey.encrypt(target_v)

        output_grad = (pred - target_v)

        weight_grad = TensorBase(np.zeros_like(self.weights.data))

        if(self.encrypted):
            weight_grad = weight_grad.encrypt(self.pubkey)

        for i in range(len(input)):
            if(input[i] != 1 and input[i] != 0):
                weight_grad[i] += (output_grad[0] * input[i])
            elif(input[i] == 1):
                weight_grad[i] += output_grad[0]
            else:
                "doesn't matter... input == 0"

        return weight_grad
Esempio n. 2
0
 def batch_update(self, minibatch, alpha):
     """Updates a minibatch of input and target prediction. Should be called through
     learn() for default parameters
     """
     weight_update = TensorBase(np.zeros(self.weights.data.shape))
     if (self.encrypted):
         weight_update = weight_update.encrypt(self.pubkey)
     for (x, y) in zip(*minibatch):
         weight_update += self.generate_gradient(x, y)
     self.weights -= weight_update * (alpha / len(minibatch[0]))
Esempio n. 3
0
    def __init__(self, n_inputs=4, n_labels=2, desc=""):

        self.desc = desc

        self.n_inputs = n_inputs
        self.n_labels = n_labels

        self.weights = TensorBase(np.zeros((n_inputs, n_labels)))

        self.pubkey = None
        self.encrypted = False
Esempio n. 4
0
    def __init__(self, n_inputs=4, n_labels=2, desc="", capsule_client=None):
        self.desc = desc

        self.n_inputs = n_inputs
        self.n_labels = n_labels

        self.weights = TensorBase(np.random.rand(n_inputs, n_labels))

        self.pubkey = None
        self.encrypted = False
        self.capsule = capsule_client
Esempio n. 5
0
    def evaluate_gradient_from_avg(self,addr,avg,prikey,pubkey,inputs,targets,alpha=0.5):  
        num_epochs = 50
        if (self.syft_obj.encrypted):
            self.syft_obj.decrypt(prikey)
        candidate = self.syft_obj
        #candidate.weights=candidate.weights.decrypt(prikey)
        avg_grad_values=TensorBase(avg)
        print("type i wanna know",type(avg_grad_values))
        for e in range (num_epochs):
            #alpha = alpha * 0.09
            candidate.weights -= (avg_grad_values * alpha) 
        #candidate.weights -= (avg * alpha)
        #candidate.weights = candidate.weights.decrypt(prikey)
        candidate.encrypted = False
        candidate.weights = TensorBase(candidate.weights)
        candidate.weights = candidate.weights.clamp_(-2,2)
        #candidate.weights=candidate.weights.clamp_(-2,2)
        print("type i wanna know2",type(candidate.weights))

        new_model_error = candidate.evaluate(inputs, targets)
        print("new_model_error_iwannaknow",new_model_error)

        """if (new_model_error < self.best_error and self.target_error < self.best_error):
            totalError = self.initial_error - self.target_error
            solvedError = self.best_error - new_model_error
            self.best_error = new_model_error
            #self.syft_obj = candidate
            print("self.best_error",self.best_error)
        #self.syft_obj = candidate
        #tx = self.repo.get_transaction(from_addr=addr)
        #ipfs_address = self.repo.ipfs.store(candidate.encrypt(pubkey))
        #ip=IPFSAddress().to_ethereum(ipfs_address)
        #tx.evalGradientfromAvg(self.model_id,new_model_error,ip)
        owner = self.owner
        bounty=self.bounty
        init_error=self.initial_error
        target_error=self.target_error
        model_id=self.model_id
        syft_ob=candidate
        best_error=self.best_error
        print("best_error", best_error)
        #updatedModel=Model(owner=owner,syft_obj=syft_ob,bounty=bounty,initial_error=init_error,best_error=best_error,target_error=target_error,model_id=model_id)
        print("updatedmodel.best_error", updatedModel.best_error)"""

        return new_model_error,candidate
Esempio n. 6
0
    def learn(self, inputs, targets, i):
        """Updates weights based on input and target prediction. Note, updating
        weights increases the noise in the encrypted weights and will
        eventually require the weights to be re-encrypted.

        TODO: minibatching
        TODO: instead of storing weights, store aggregated weight updates (and
        optionally use them in "forward").
        """
        inputs = inputs[50 * i:]
        targets = targets[50 * i:]
        weight_update = TensorBase(np.zeros_like(self.weights.data))
        s_weight_update = time.time()
        for i, row in enumerate(inputs):
            weight_update += self.generate_gradient(row, targets[i])
            #elf.weights -= weight_update * alpha
        e_weight_update = time.time()
        print("client update time", e_weight_update - s_weight_update)
        weight_update = weight_update / len(inputs)
        length = int(len(inputs))

        return weight_update, length
Esempio n. 7
0
class LinearClassifier():
    """This class is a basic linear classifier with functionality to
    encrypt/decrypt weights according to any of the homomorphic encryption
    schemes in syft.he. It also contains the logic to make predictions when
    in an encrypted state.

    TODO: create a generic interface for ML models that this class implements.

    TODO: minibatching in the "learn" API. The greater the batch size, the more
    iterations should be doable before the homomorphic encryption noise grows
    too much to be decrypted.
    """

    def __init__(self, n_inputs=4, n_labels=2, desc=""):

        self.desc = desc

        self.n_inputs = n_inputs
        self.n_labels = n_labels

        self.weights = TensorBase(np.zeros((n_inputs, n_labels)))

        self.pubkey = None
        self.encrypted = False

    def encrypt(self, pubkey):
        """iterates through each weight and encrypts it

        TODO: check that weights are actually decrypted

        """

        self.encrypted = True
        self.pubkey = pubkey
        self.weights = self.weights.encrypt(pubkey)
        return self

    def decrypt(self, seckey):
        """iterates through each weight and decrypts it

        TODO: check that weights are actually encrypted

        """
        self.encrypted = False
        self.weights = self.weights.decrypt(seckey)
        return self

    def forward(self, input):

        """Makes a prediction based on input. If the network is encrypted, the
        prediction is also encrypted and vise versa."""

        pred = self.weights[0] * input[0]
        for j, each_inp in enumerate(input[1:]):
            if(each_inp == 1):
                pred = pred + self.weights[j + 1]
            elif(each_inp != 0):
                pred = pred + (self.weights[j + 1] * input[j + 1])

        return pred

    def learn(self, input, target, alpha=0.5):
        """Updates weights based on input and target prediction. Note, updating
        weights increases the noise in the encrypted weights and will
        eventually require the weights to be re-encrypted.

        TODO: minibatching
        TODO: instead of storing weights, store aggregated weight updates (and
        optionally use them in "forward").
        """

        weight_update = self.generate_gradient(input, target)
        self.weights -= weight_update * alpha

        return weight_update

    def evaluate(self, inputs, targets):
        """accepts a list of inputs and a list of targets - returns the mean
        squared error scaled by a fixed amount and converted to an integer."""

        scale = 1000

        if(self.encrypted):
            return "not yet supported... but will in the future"
        else:

            loss = 0
            for i, row in enumerate(inputs):
                pred = self.forward(row)
                true = targets[i]
                diff = (pred - true)
                loss += (diff * diff).to_numpy()
            return int((loss[0] * scale) / float(len(inputs)))

    def __str__(self):
        left = "Linear Model (" + str(self.n_inputs) + ","
        return left + str(self.n_labels) + "): " + str(self.desc)

    def __repr__(self):
        return self.__str__()

    def generate_gradient(self, input, target):
        target = TensorBase(np.array(target).astype('float64'))
        input = TensorBase(np.array(input).astype('float64'))
        pred = self.forward(input)

        target_v = target

        if(self.pubkey is not None and self.encrypted):
            target_v = self.pubkey.encrypt(target_v)

        output_grad = (pred - target_v)

        weight_grad = TensorBase(np.zeros_like(self.weights.data))

        if(self.encrypted):
            weight_grad = weight_grad.encrypt(self.pubkey)

        for i in range(len(input)):
            if(input[i] != 1 and input[i] != 0):
                weight_grad[i] += (output_grad[0] * input[i])
            elif(input[i] == 1):
                weight_grad[i] += output_grad[0]
            else:
                "doesn't matter... input == 0"

        return weight_grad
Esempio n. 8
0
class LinearClassifier(AbstractModel):
    """
        This class is a basic linear classifier with functionality to
        encrypt/decrypt weights according to any of the homomorphic encryption
        schemes in syft.he. It also contains the logic to make predictions when
        in an encrypted state.
    """
    def __init__(self, n_inputs=4, n_labels=2, desc="", capsule_client=None):
        self.desc = desc

        self.n_inputs = n_inputs
        self.n_labels = n_labels

        self.weights = TensorBase(np.random.rand(n_inputs, n_labels))

        self.pubkey = None
        self.encrypted = False
        self.capsule = capsule_client

    def encrypt(self):
        """iterates through each weight and encrypts it
        """

        if self.encrypted:
            return self

        self.pubkey = self.capsule.keygen()
        self.weights = self.weights.encrypt(self.pubkey)
        self.encrypted = self.weights.encrypted

        return self

    def decrypt(self):
        """iterates through each weight and decrypts it
        """
        if not self.pubkey:
            raise KeyException("Public key was not generated.")

        if not self.encrypted:
            return self

        self.weights = self.capsule.decrypt(self.weights, self.pubkey.id)
        self.encrypted = self.weights.encrypted
        return self

    def forward(self, input):
        """Makes a prediction based on input. If the network is encrypted, the
        prediction is also encrypted and vise versa.
        """
        pred = self.weights[0] * input[0]
        for j, each_inp in enumerate(input[1:]):
            if (each_inp == 1):
                pred = pred + self.weights[j + 1]
            elif (each_inp != 0):
                pred = pred + (self.weights[j + 1] * input[j + 1])

        return pred

    def learn(self,
              input,
              target,
              alpha=0.5,
              batchsize=32,
              encrypt_interval=16):
        """Updates weights based on input and target prediction. Note, updating
        weights increases the noise in the encrypted weights and will
        eventually require the weights to be re-encrypted.

        TODO: instead of storing weights, store aggregated weight updates (and
        optionally use them in "forward").
        """
        input_batches = [
            input[i:i + batchsize] for i in range(0, len(input), batchsize)
        ]
        target_batches = [
            target[i:i + batchsize] for i in range(0, len(target), batchsize)
        ]
        for epoch_count, minibatch in enumerate(
                zip(input_batches, target_batches)):
            self.batch_update(minibatch, alpha)
            if self.encrypted and (epoch_count > encrypt_interval) and (
                    epoch_count % encrypt_interval == 0):
                self.weights = self.capsule.bootstrap(self.weights,
                                                      self.pubkey.id)

    def batch_update(self, minibatch, alpha):
        """Updates a minibatch of input and target prediction. Should be called through
        learn() for default parameters
        """
        weight_update = TensorBase(np.zeros(self.weights.data.shape))
        if (self.encrypted):
            weight_update = weight_update.encrypt(self.pubkey)
        for (x, y) in zip(*minibatch):
            weight_update += self.generate_gradient(x, y)
        self.weights -= weight_update * (alpha / len(minibatch[0]))

    def evaluate(self, inputs, targets):
        """accepts a list of inputs and a list of targets - returns the mean
        squared error scaled by a fixed amount and converted to an integer.
        """
        scale = 1000

        if (self.encrypted):
            return "not yet supported... but will in the future"
        else:

            loss = 0
            for i, row in enumerate(inputs):
                pred = self.forward(row)
                true = targets[i]
                diff = (pred - true)
                loss += (diff * diff).to_numpy()
            return int((loss[0] * scale) / float(len(inputs)))

    def __str__(self):
        left = "Linear Model (" + str(self.n_inputs) + ","
        return left + str(self.n_labels) + "): " + str(self.desc)

    def generate_gradient(self, input, target):
        target = TensorBase(np.array(target).astype('float64'))
        input = TensorBase(np.array(input).astype('float64'))
        pred = self.forward(input)

        target_v = target

        if (self.pubkey is not None and self.encrypted):
            target_v = self.pubkey.encrypt(target_v)

        output_grad = (pred - target_v)

        weight_grad = TensorBase(np.zeros_like(self.weights.data))

        if (self.encrypted):
            weight_grad = weight_grad.encrypt(self.pubkey)

        for i in range(len(input)):
            if (input[i] != 1 and input[i] != 0):
                weight_grad[i] += (output_grad[0] * input[i])
            elif (input[i] == 1):
                weight_grad[i] += output_grad[0]
            else:
                "doesn't matter... input == 0"

        return weight_grad