Example #1
0
def train_ref(model,
              criterion,
              optimizer,
              input,
              target,
              nb_epochs=200,
              verbose=False):

    mini_batch_size = 100

    #empty recipient
    loss_evolution = []
    precision_evolution = []

    #actual training
    for e in range(nb_epochs):
        loss_e = 0.
        for b in range(0, input.size(0), mini_batch_size):
            output = model(input.narrow(0, b, mini_batch_size))
            loss = criterion(output, target.narrow(0, b, mini_batch_size))
            loss_e += loss
            model.zero_grad()
            loss.backward()
            optimizer.step()

        #record the data
        precision_evolution.append(
            helpers.compute_accuracy(model, input, target) / target.shape[0] *
            100)
        loss_evolution.append(loss_e)

        if verbose:
            message = "epoch {:3}, loss {:10.4}".format(e, loss_e)
            helpers.update_progress((e + 1.) / nb_epochs, message=message)

    return loss_evolution, precision_evolution
Example #2
0
def train_rep(model,
              lr,
              X,
              P,
              n_iter,
              c_iter,
              batch_size,
              alpha=10,
              C_reg=1,
              compute_emd=False,
              adv=True,
              verbose=False):
    """
    Train the fair representation using autoencoder provided by the user.
    Parameters:
        model: the Pytorch model of the autoencoder. The model should have two members, model.encoder, and the model.decoder.

    Parameters:
        lr: learning rate.
        X: the input features.
        P: the protected attribute.
        n_iter: number of iterations.
        c_iter: the number of iteration to trian the critic inside each training iteration.
        batch_size: batch size.
        alpha: the weight of the fairness contraint. Larger means more penalize on the violation of fairness.
        C_reg: the penalization coefficient of the regularization of the encoder.
        compute_emd: whether the EMD distance is calculated for each iteration. It may slow the training process significantly.
        adv: if the model is trained adversarially, i.e. fairly. Setting it false will result in training a normal autoencoder.
        verbose: if the training process is verbosely printed.
    """
    time_s = time.time()
    X_0 = X[P == 0]
    X_1 = X[P == 1]

    optim_encoder = optim.Adam(model.encoder.parameters(), lr=lr)
    optim_decoder = optim.Adam(model.decoder.parameters(), lr=lr)
    optim_crit = optim.Adam(model.critic.parameters(), lr=0.1)

    l1_crit = nn.L1Loss(size_average=False)

    n_of_batch = int(len(X) / (batch_size * 2)) * n_iter

    for i in range(n_of_batch):
        X_n = X_0[np.random.choice(len(X_0), batch_size)]
        X_u = X_1[np.random.choice(len(X_1), batch_size)]
        if adv:
            w_dist_last = 0
            eps = 1
            #while w_dist <= 0:
            while eps >= 1e-3:
                #while True:
                for t in range(c_iter):
                    optim_crit.zero_grad()
                    w_dist = model.wdist(X_n, X_u)
                    loss = -w_dist
                    loss.backward(retain_graph=True)
                    optim_crit.step()
                    eps = np.abs(w_dist.data.item() - w_dist_last)

                    # keep training crit until distance no longer decrease
                    w_dist_last = w_dist.data.item()

                    for p in model.critic.parameters():
                        p.data.clamp_(-0.1, 0.1)

        # for t in range(c_iter):
        optim_encoder.zero_grad()
        optim_decoder.zero_grad()

        # only use the encoder g
        mse, wdist = model.forward(X_n, X_u)

        if adv:
            loss = mse + wdist * alpha
        else:
            loss = mse

        # L1 regularization
        reg_loss = 0
        #for param in model.encoder.parameters():
        #    reg_loss += torch.abs(param).sum()
        for layer in model.encoder:
            if type(layer) is nn.Linear:
                #norm = torch.sum(torch.pow(torch.sum(torch.abs(layer.weight), dim=0), 2))
                norm = 0.0
                for row in layer.weight.transpose(0, 1):
                    norm += torch.sum(torch.pow(row, 2))
                reg_loss += norm

        loss += C_reg * reg_loss
        loss.backward(retain_graph=True)

        # use mse and wdist to update g and f
        optim_encoder.step()
        optim_decoder.step()

        text = 'mse: %.4f, critic: %.4f' % (mse.item(), wdist.item())
        if compute_emd:
            g_0 = model.encoder(X_u).detach().cpu().numpy()
            g_1 = model.encoder(X_n).detach().cpu().numpy()
            real_emd = emd_samples(g_0, g_1)
            text += ", emd: %.4f" % real_emd

        if verbose:
            update_progress(i, n_of_batch, time_s, text=text + ' ')
Example #3
0
def input():
    # session['userid'] = 1

    if request.method == "GET":

        if logged() is False:
            return render_template('welcome.html')

        userid = session.get('userid')

        # load info from db and save it in session
        load_savings(userid, savings_db)
        load_expenses(userid, expenses_db)
        load_goals(userid, goals_db)

        if load_user_info(userid, user_db) is False:
            return redirect('/error')

        return render_template('input.html',
                               savings=session.get('savings'),
                               expenses=session.get('expenses'),
                               goals=session.get('goals'),
                               user_info=session.get('user_info'))

    if request.method == "POST":
        # DEF: saving all info from input page to session
        # save salary
        session['salary'] = float(request.form.get('salary'))

        # preload accounts from session
        savings = session.get('savings')
        expenses = session.get('expenses')
        goals = session.get('goals')

        #for all saving types load current value from input page
        for key in savings:
            savings[key]['value'] = float(request.form.get(key))

            #change progress info
            savings = update_progress(savings, key)

        # for all expenses load value from input page
        for key in expenses:
            expenses[key]['value'] = float(request.form.get(key))

        # for all goal load current value
        for key in goals:
            goals[key]['value'] = float(request.form.get(key))

            # change progress info
            goals = update_progress(goals, key)

        #save updated info in session
        session['expenses'] = expenses
        session['savings'] = savings
        session['goals'] = goals

        print(
            f'\n\n-----USER INPUT processed and saved in session\n\nexpenses: {expenses} \n\nsavings:{savings}\n\ngoals: {goals} \n\nsalary:{session.get("salary")}'
        )
        return redirect('/output')
Example #4
0
    def run(self):
        """
        Codice eseguito nel thread.
        Riceve dal peer l'md5 del file che desidera scaricare e lo invia diviso in parti
        """

        try:
            cmd = self.conn.recv(4)                                                 # Ricezione del comando di download dal peer, deve contenere RETR
        except socket.error as e:
            print 'Socket Error: ' + e.message
        except Exception as e:
            print 'Error: ' + e.message
        else:
            if cmd == "RETR":
                try:
                    self.md5 = self.conn.recv(32)                                   # Ricezione dell'md5 del file da inviare
                    print 'Received md5: ' + self.md5
                except socket.error as e:
                    print 'Socket Error: ' + e.message
                except Exception as e:
                    print 'Error: ' + e.message
                else:
                    found_name = None

                    for idx, file in enumerate(self.file_list):                     # Ricerca del file da inviare tra quelli disponibili
                        if file.md5 == self.md5:
                            found_name = file.name

                    if found_name is None:
                        print 'Found no file with md5: ' + self.md5
                    else:

                        chunk_size = 1024                                           # Dimensione di una parte di file

                        try:
                            file = open("shareable/" + found_name, "rb")
                        except Exception as e:
                            print 'Error: ' + e.message + "\n"
                        else:
                            tot_dim = self.filesize("shareable/" + found_name)      # Calcolo delle dimesioni del file
                            n_chunks = int(tot_dim // chunk_size)              # Calcolo del numero di parti
                            resto = tot_dim % chunk_size                            # Eventuale resto
                            if resto != 0.0:
                                n_chunks += 1

                            file.seek(0, 0)                                         # Spostamento all'inizio del file

                            try:
                                buff = file.read(chunk_size)                        # Lettura del primo chunk
                                chunks_sent = 0

                                msg = 'ARET' + str(n_chunks).zfill(6)               # Risposta alla richiesta di download, deve contenere ARET ed il numero di chunks che saranno inviati
                                print 'Upload Message: ' + msg
                                self.conn.sendall(msg)
                                print 'Sending chunks...'

                                while len(buff) == chunk_size:                      # Invio dei chunks
                                    try:
                                        msg = str(len(buff)).zfill(5) + buff
                                        self.conn.sendall(msg)                      # Invio di
                                        chunks_sent += 1

                                        helpers.update_progress(chunks_sent, n_chunks, 'Uploading ' + file.name)      # Stampa a video del progresso dell'upload

                                        buff = file.read(chunk_size)                # Lettura chunk successivo
                                    except IOError:
                                        print "Connection error due to the death of the peer!!!\n"
                                if len(buff) != 0:                                  # Invio dell'eventuale resto, se più piccolo di chunk_size
                                    msg = str(len(buff)).zfill(5) + buff
                                    self.conn.sendall(msg)
                                print "\nUpload Completed"
                                file.close()                                        # Chiusura del file
                            except EOFError:
                                print "You have read a EOF char"
            else:
                print "Error: unknown directory response.\n"

        self.conn.shutdown(1)                                                       # Segnalazione di fine comunicazione
        self.conn.close()                                                           # Chiusura comunicazione
Example #5
0
def get_file(session_id, host_ipv4, host_ipv6, host_port, file, directory):
    """
    Effettua il download di un file da un altro peer

    :param session_id: id sessione corrente assegnato dalla directory
    :type session_id: str
    :param host_ipv4: indirizzo ipv4 del peer da cui scaricare il file
    :type host_ipv4: str
    :param host_ipv6: indirizzo ipv6 del peer da cui scaricare il file
    :type host_ipv6: str
    :param host_port: porta del peer da cui scaricare il file
    :type host_port: str
    :param file: file da scaricare
    :type file: file
    :param directory: socket verso la directory (per la segnalazione del download)
    :type directory: object
    """

    c = Connection.Connection(host_ipv4, host_ipv6, host_port)                      # Inizializzazione della connessione verso il peer
    c.connect()
    download = c.socket

    msg = 'RETR' + file.md5
    print 'Download Message: ' + msg
    try:
        download.send(msg)                                                          # Richiesta di download al peer
        print 'Message sent, waiting for response...'
        response_message = download.recv(10)                                        # Risposta del peer, deve contenere il codice ARET seguito dalle parti del file
    except socket.error as e:
        print 'Error: ' + e.message
    except Exception as e:
        print 'Error: ' + e.message
    else:
        if response_message[:4] == 'ARET':
            n_chunks = response_message[4:10]                                       # Numero di parti del file da scaricare
            #tmp = 0

            filename = file.name
            fout = open('received/' + filename, "wb")                               # Apertura di un nuovo file in write byte mode (sovrascrive se già esistente)

            n_chunks = int(str(n_chunks).lstrip('0'))                               # Rimozione gli 0 dal numero di parti e converte in intero

            for i in range(0, n_chunks):
                if i == 0:
                    print 'Download started...'

                helpers.update_progress(i, n_chunks, 'Downloading ' + fout.name)    # Stampa a video del progresso del download

                try:
                    chunk_length = recvall(download, 5)                             # Ricezione dal peer la lunghezza della parte di file
                    data = recvall(download, int(chunk_length))                     # Ricezione dal peer la parte del file
                    fout.write(data)                                                # Scrittura della parte su file
                except socket.error as e:
                    print 'Socket Error: ' + e.message
                    break
                except IOError as e:
                    print 'IOError: ' + e.message
                    break
                except Exception as e:
                    print 'Error: ' + e.message
                    break
            fout.close()                                                            # Chiusura file a scrittura ultimata
            print '\nDownload completed'

            warns_directory(session_id, file.md5, directory)                        # Invocazione del metododo che segnala il download alla directory
            print 'Checking file integrity...'
            downloaded_md5 = helpers.hashfile(open(fout.name, 'rb'), hashlib.md5()) # Controllo dell'integrità del file appena scarcato tramite md5
            if file.md5 == downloaded_md5:
                print 'The downloaded file is intact'
            else:
                print 'Something is wrong. Check the downloaded file'
        else:
            print 'Error: unknown response from directory.\n'
Example #6
0
    def Train(self, train_input, train_target, train_classes = None, auxiliary = False, verbose = True, nb_epochs = 50, batch_size=250, device='cpu', evolution = False, test_input = None, test_target = None):
        """ Training of the siamese module.
            if not auxiliary:
                usual training
            if auxiliary:
                first split the sample into the two images and use the branch to try to classify the numbers, compute the
                loss wrt to the classes of digits and update the parameters  of the branch.
                Then run the entire sample trough the sample and compute the loss against the train_target and update

        Parameters
        ----------
        train_input : [n,2,14,14]
            two images [14,14] representing two numbers
        train_target : [n,2]
            is the first digit bigger than the second
        train_classes : [n,2]
            values of the two digits
        auxiliary : bool
            use of the auxiliary loss (the default is False).
        verbose : bool
            if True print the training  `verbose` (the default is True).
        nb_epochs : int
            epochs to train (the default is 50).
        device : torch.device
            Torch device (the default is 'cpu').
        """

        if auxiliary:
            if verbose:
                print("training with auxiliary loss with {} epochs".format(nb_epochs))
            if train_classes is None: print("Error: if auxiliary loss, the model needs the classes of the training set")
        elif verbose:
            print("training with no auxiliary losses with {} epochs".format(nb_epochs))

        criterion = nn.CrossEntropyLoss()
        criterion = criterion.to(device)

        optimizer = optim.Adam(self.parameters(),lr = 0.005)

        if evolution:
            acc_train = []
            acc_test = []

        for e in range(nb_epochs):
            for input, targets in zip(train_input.split(batch_size), train_target.split(batch_size)):

                if auxiliary:
                    #first pass
                    #separating the data so that we train on the two images separatly, and learn to classify them properly
                    train_input1,train_classes1,train_input2,train_classes2 = split_channels(train_input, train_classes)

                    #use the branch to perform handwritten digits classification
                    out1 = self.branch(train_input1)
                    out2 = self.branch(train_input2)

                    #auxiliary loss: learn to detect the handwritten digits directly
                    loss_aux = criterion(out1,train_classes1) + criterion(out2,train_classes2)

                    #optimize based on this
                    self.zero_grad()
                    loss_aux.backward(retain_graph=True)
                    optimizer.step()

                    #second pass
                    #loss and optimization of the whole model
                    response = self.forward(train_input)
                    loss = criterion(response,train_target)
                    self.zero_grad()
                    loss.backward()
                    optimizer.step()

                else:
                    response = self.forward(train_input)
                    loss = criterion(response,train_target)
                    self.zero_grad()
                    loss.backward()
                    optimizer.step()

            if verbose:
                acc = accuracy(self, train_input, train_target)
                print("epoch {:3}, loss {:7.4}, accuracy {:.2%}".format(e,loss,acc))
            else:
                update_progress((e+1)/nb_epochs, message="")

            if evolution:
                acc_train.append(accuracy(self, train_input, train_target))
                acc_test.append( accuracy(self, test_input, test_target))
        if evolution:
            return acc_train,acc_test