コード例 #1
0
def pretrain(source_data_loader,
             test_data_loader,
             no_classes,
             embeddings,
             epochs=20,
             batch_size=128,
             cuda=False):

    classifier = Classifier()
    encoder = Encoder(embeddings)

    if cuda:
        classifier.cuda()
        encoder.cuda()
    ''' Jointly optimize both encoder and classifier '''
    encoder_params = filter(lambda p: p.requires_grad, encoder.parameters())
    optimizer = optim.Adam(
        list(encoder_params) + list(classifier.parameters()))

    # Use weights to normalize imbalanced in data
    c = [1] * len(no_classes)
    weights = torch.FloatTensor(len(no_classes))
    for i, (a, b) in enumerate(zip(c, no_classes)):
        weights[i] = 0 if b == 0 else a / b

    loss_fn = nn.CrossEntropyLoss(weight=Variable(weights))

    print('Training encoder and classifier')
    for e in range(epochs):

        # pretrain with whole source data -- use groups with DCD
        for sample in source_data_loader:
            x, y = Variable(sample[0]), Variable(sample[1])
            optimizer.zero_grad()

            if cuda:
                x, y = x.cuda(), y.cuda()

            output = model_fn(encoder, classifier)(x)

            loss = loss_fn(output, y)

            loss.backward()

            optimizer.step()

        print("Epoch", e, "Loss", loss.data[0], "Accuracy",
              eval_on_test(test_data_loader, model_fn(encoder, classifier)))

    return encoder, classifier
コード例 #2
0
ファイル: solver.py プロジェクト: as468579/ml2021spring
class Solver(object):
    def __init__(self, config):

        # Configurations
        self.config = config

        # Build the models
        self.build_models()

    def build_models(self):

        # Models
        self.net = Classifier().to(self.config['device'])

        # Optimizers
        self.optimizer = getattr(torch.optim, self.config['optimizer'])(
            self.net.parameters(),
            lr=self.config['lr'],
        )

        # Citerion
        self.criterion = nn.CrossEntropyLoss(reduce=False)

        # Record
        logging.info(self.net)

    def save_model(self, filename):
        save_path = os.path.join(self.config['save_path'], f'{filename}')
        try:
            logging.info(
                f'Saved best Neural network ckeckpoints into {save_path}')
            torch.save(self.net.state_dict(),
                       save_path,
                       _use_new_zipfile_serialization=False)
        except:
            logging.error(f'Error saving weights to {save_path}')

    def restore_model(self, filename):
        weight_path = os.path.join(self.config['save_path'], f'{filename}')
        try:
            logging.info(f'Loading the trained Extractor from {weight_path}')
            self.net.load_state_dict(
                torch.load(weight_path,
                           map_location=lambda storage, loc: storage))

        except:
            logging.error(f'Error loading weights from {weight_path}')
コード例 #3
0
ファイル: train.py プロジェクト: mingming97/iMet-FGVC6
def main():
    args = parse_args()

    cfg = cfg_from_file(args.config)
    print('using config: {}'.format(args.config))

    data_cfg = cfg['data']
    datalist = datalist_from_file(data_cfg['datalist_path'])
    num_train_files = len(datalist) // 5 * 4
    train_dataset = IMetDataset(data_cfg['dataset_path'],
                                datalist[:num_train_files],
                                transform=data_cfg['train_transform'])
    test_dataset = IMetDataset(data_cfg['dataset_path'],
                               datalist[num_train_files:],
                               transform=data_cfg['test_transform'])
    train_dataloader = data.DataLoader(train_dataset,
                                       batch_size=data_cfg['batch_size'],
                                       shuffle=True)
    test_dataloader = data.DataLoader(test_dataset,
                                      batch_size=data_cfg['batch_size'])

    backbone_cfg = cfg['backbone'].copy()
    backbone_type = backbone_cfg.pop('type')
    if backbone_type == 'ResNet':
        backbone = ResNet(**backbone_cfg)
    elif backbone_type == 'ResNeXt':
        backbone = ResNeXt(**backbone_cfg)
    elif backbone_type == 'DenseNet':
        backbone = DenseNet(**backbone_cfg)
    classifier = Classifier(backbone, backbone.out_feat_dim).cuda()

    train_cfg, log_cfg = cfg['train'], cfg['log']
    criterion = FocalLoss()
    optimizer = torch.optim.SGD(classifier.parameters(),
                                lr=train_cfg['lr'],
                                weight_decay=train_cfg['weight_decay'],
                                momentum=train_cfg['momentum'])
    trainer = Trainer(model=classifier,
                      train_dataloader=train_dataloader,
                      val_dataloader=test_dataloader,
                      criterion=criterion,
                      optimizer=optimizer,
                      train_cfg=train_cfg,
                      log_cfg=log_cfg)
    trainer.train()
コード例 #4
0
def main(batch_size=64, epochs=10):
    if torch.cuda.is_available():
        device = 'cuda'
        print('GPU MODE')
    else:
        device = 'cpu'
        print('CPU MODE')
    device = torch.device(device)

    dataloader = DataLoader(
        datasets.MNIST('./data/mnist',
                       train=True,
                       download=True,
                       transform=transforms.Compose([
                           transforms.Resize(28),
                           transforms.ToTensor(),
                       ])),
        batch_size=batch_size,
        shuffle=True,
    )

    model = Classifier()
    summary(model, (1, 28, 28))

    criterion = nn.CrossEntropyLoss()

    optimizer = torch.optim.Adam(model.parameters())

    for epoch in range(epochs):
        for i, (imgs, labels) in enumerate(dataloader):
            imgs = imgs.to(device, dtype=torch.float32)
            labels = labels.to(device, dtype=torch.long)

            optimizer.zero_grad()
            preds = model(imgs)
            loss = criterion(preds, labels)
            loss.backward()
            optimizer.step()

            if i % 100 == 0:
                print(loss.item())
コード例 #5
0
def pretrain(data, epochs=5, batch_size=128, cuda=False):

    X_s, y_s, _, _ = data

    test_dataloader = mnist_dataloader(train=False, cuda=cuda)

    classifier = Classifier()
    encoder = Encoder()

    if cuda:
        classifier.cuda()
        encoder.cuda()

    ''' Jointly optimize both encoder and classifier ''' 
    optimizer = optim.Adam(list(encoder.parameters()) + list(classifier.parameters()))
    loss_fn = nn.CrossEntropyLoss()
    
    for e in range(epochs):
        
        for _ in range(len(X_s) // batch_size):
            inds = torch.randperm(len(X_s))[:batch_size]

            x, y = Variable(X_s[inds]), Variable(y_s[inds])
            optimizer.zero_grad()

            if cuda:
                x, y = x.cuda(), y.cuda()

            y_pred = model_fn(encoder, classifier)(x)

            loss = loss_fn(y_pred, y)

            loss.backward()

            optimizer.step()

        print("Epoch", e, "Loss", loss.data[0], "Accuracy", eval_on_test(test_dataloader, model_fn(encoder, classifier)))
    
    return encoder, classifier
コード例 #6
0
    'n_classes': FLAGS.n_classes,
}

#append every sentence with <s> in the start and </s> in the end. Also, ignore the words in sentences for which no embedding
print("\nAppending every sentence with <s> in the start and </s> in the end.")
for sent_type in ['s1', 's2']:
    for dset in ['train', 'dev', 'test']:
        eval(dset)[sent_type] = np.array(
            [['<s>'] + [word for word in sent.split() if word in embeddings] +
             ['</s>'] for sent in eval(dset)[sent_type]])
print("Example sentence after processing: \n", train['s1'][0])

if FLAGS.model_name == 'base':
    classif = Classifier(config).to(device)
    loss_fn = torch.nn.CrossEntropyLoss()
    optimizer = torch.optim.SGD(classif.parameters(),
                                lr=FLAGS.lr,
                                weight_decay=1e-4)
elif FLAGS.model_name == 'lstm':

    model = LSTM_main(config).to(device)
    loss_fn = torch.nn.CrossEntropyLoss().to(device)

    #     mod_params = list(model.parameters()) + list(classif.parameters())
    optimizer = torch.optim.SGD(model.parameters(),
                                lr=FLAGS.lr,
                                weight_decay=0)
    print("\n------Training uni-LSTM network---------")
    print(model)

elif FLAGS.model_name == 'bilstm':
コード例 #7
0
class Agent():
    def __init__(self, state_size, action_size, config):
        self.seed = config["seed"]
        torch.manual_seed(self.seed)
        np.random.seed(seed=self.seed)
        random.seed(self.seed)
        self.env = gym.make(config["env_name"])
        self.env.seed(self.seed)
        self.state_size = state_size
        self.action_size = action_size
        self.clip = config["clip"]
        self.device = 'cuda'
        print("Clip ", self.clip)
        print("cuda ", torch.cuda.is_available())
        self.double_dqn = config["DDQN"]
        print("Use double dqn", self.double_dqn)
        self.lr_pre = config["lr_pre"]
        self.batch_size = config["batch_size"]
        self.lr = config["lr"]
        self.tau = config["tau"]
        print("self tau", self.tau)
        self.gamma = 0.99
        self.target_entropy = -torch.prod(torch.Tensor(action_size).to(self.device)).item()
        self.fc1 = config["fc1_units"]
        self.fc2 = config["fc2_units"]
        self.log_alpha = torch.zeros(1, requires_grad=True, device=self.device)
        self.alpha = self.log_alpha.exp()
        self.alpha_optim = optim.Adam([self.log_alpha], lr=config["lr_alpha"])
        self.policy = SACActor(state_size, action_size, self.seed).to(self.device)
        self.policy_optim = optim.Adam(self.policy.parameters(), lr=config["lr_policy"])
        
        self.qnetwork_local = QNetwork(state_size, action_size, self.seed, self.fc1, self.fc2).to(self.device)
        self.qnetwork_target = QNetwork(state_size, action_size, self.seed, self.fc1, self.fc2).to(self.device)
        self.optimizer = optim.Adam(self.qnetwork_local.parameters(), lr=self.lr)
        self.soft_update(self.qnetwork_local, self.qnetwork_target, 1)
        
        self.q_shift_local = SQNetwork(state_size, action_size, self.seed, self.fc1, self.fc2).to(self.device)
        self.q_shift_target = SQNetwork(state_size, action_size,self.seed, self.fc1, self.fc2).to(self.device)
        self.optimizer_shift = optim.Adam(self.q_shift_local.parameters(), lr=self.lr)
        self.soft_update(self.q_shift_local, self.q_shift_target, 1)
         
        self.R_local = SQNetwork(state_size, action_size, self.seed,  self.fc1, self.fc2).to(self.device)
        self.R_target = SQNetwork(state_size, action_size, self.seed, self.fc1, self.fc2).to(self.device)
        self.optimizer_r = optim.Adam(self.R_local.parameters(), lr=self.lr)
        self.soft_update(self.R_local, self.R_target, 1) 

        self.steps = 0
        self.predicter = Classifier(state_size, action_size, self.seed, 256, 256).to(self.device)
        self.optimizer_pre = optim.Adam(self.predicter.parameters(), lr=self.lr_pre)
        pathname = "lr_{}_batch_size_{}_fc1_{}_fc2_{}_seed_{}".format(self.lr, self.batch_size, self.fc1, self.fc2, self.seed)
        pathname += "_clip_{}".format(config["clip"])
        pathname += "_tau_{}".format(config["tau"])
        now = datetime.now()    
        dt_string = now.strftime("%d_%m_%Y_%H:%M:%S")
        pathname += dt_string
        tensorboard_name = str(config["locexp"]) + '/runs/' + pathname
        self.vid_path = str(config["locexp"]) + '/vid'
        self.writer = SummaryWriter(tensorboard_name)
        print("summery writer ", tensorboard_name)
        self.average_prediction = deque(maxlen=100)
        self.average_same_action = deque(maxlen=100)
        self.all_actions = []
        for a in range(self.action_size):
            action = torch.Tensor(1) * 0 +  a
            self.all_actions.append(action.to(self.device))
    
    def learn(self, memory_ex, memory_all):
        self.steps += 1
        logging.debug("--------------------------New update-----------------------------------------------")
        states, next_states, actions, dones = memory_ex.expert_policy(self.batch_size)
        self.state_action_frq(states, actions)
        states, next_states, actions, dones = memory_all.expert_policy(self.batch_size)
        self.compute_shift_function(states, next_states, actions, dones)
        self.compute_r_function(states, actions)
        self.compute_q_function(states, next_states, actions, dones)
        self.soft_update(self.R_local, self.R_target, self.tau)
        self.soft_update(self.q_shift_local, self.q_shift_target, self.tau)
        self.soft_update(self.qnetwork_local, self.qnetwork_target, self.tau)         
        return
        
        
    
    def compute_q_function(self, states, next_states, actions, dones):
        """Update value parameters using given batch of experience tuples.
        Params
        ======
            experiences (Tuple[torch.Tensor]): tuple of (s, a, r, s', done) tuples
            gamma (float): discount factor
        """
        qf1, qf2 = self.qnetwork_local(states)
        q_value1 = qf1.gather(1, actions)
        q_value2 = qf2.gather(1, actions)
        
        with torch.no_grad():
            q1_target, q2_target = self.qnetwork_target(next_states)
            min_q_target = torch.min(q1_target, q2_target)
            next_action_prob, next_action_log_prob = self.policy(next_states)
            next_q_target = (next_action_prob * (min_q_target - self.alpha * next_action_log_prob)).sum(dim=1, keepdim=True)
            rewards = self.R_target(states).detach().gather(1, actions.detach()).squeeze(0)
            Q_targets = rewards + ((1 - dones) * self.gamma * next_q_target)
        
        loss = F.mse_loss(q_value2, Q_targets.detach()) + F.mse_loss(q_value1, Q_targets.detach())
        
        # Get max predicted Q values (for next states) from target model
        
        self.writer.add_scalar('losss/q_loss', loss, self.steps)
        # Minimize the loss
        self.optimizer.zero_grad()
        loss.backward()
        # torch.nn.utils.clip_grad_norm_(self.qnetwork_local.parameters(), 1)
        self.optimizer.step()

        # --------------------------update-policy--------------------------------------------------------
        action_prob, log_action_prob = self.policy(states)
        with torch.no_grad():
            q_pi1, q_pi2 = self.qnetwork_local(states)
            min_q_values = torch.min(q_pi1, q_pi2)
        #policy_loss = (action_prob *  ((self.alpha * log_action_prob) - min_q_values).detach()).sum(dim=1).mean()
        policy_loss = (action_prob *  ((self.alpha * log_action_prob) - min_q_values)).sum(dim=1).mean()
        self.policy_optim.zero_grad()
        policy_loss.backward()
        self.policy_optim.step()
        self.writer.add_scalar('loss/policy', policy_loss, self.steps)

        # --------------------------update-alpha--------------------------------------------------------
        alpha_loss =(action_prob.detach() *  (-self.log_alpha * (log_action_prob + self.target_entropy).detach())).sum(dim=1).mean()
        self.alpha_optim.zero_grad()
        alpha_loss.backward()
        self.alpha_optim.step()
        self.writer.add_scalar('loss/alpha', alpha_loss, self.steps)
        self.alpha = self.log_alpha.exp()
        

    def compute_shift_function(self, states, next_states, actions, dones):
        """Update value parameters using given batch of experience tuples.
        Params
        ======
            experiences (Tuple[torch.Tensor]): tuple of (s, a, r, s', done) tuples
            gamma (float): discount factor
        """
        actions = actions.type(torch.int64)
        with torch.no_grad():
            # Get max predicted Q values (for next states) from target model
            #if self.double_dqn:
            qt1, qt2 = self.qnetwork_local(next_states)
            q_min = torch.min(qt1, qt2)
            max_q, max_actions = q_min.max(1)
            Q_targets_next1, Q_targets_next2 = self.qnetwork_target(next_states)
            Q_targets_next = torch.min(Q_targets_next1, Q_targets_next2)
            Q_targets_next = Q_targets_next.gather(1, max_actions.type(torch.int64).unsqueeze(1))
            #else:
            #Q_targets_next = self.qnetwork_target(next_states).detach().max(1)[0].unsqueeze(1)
            # Compute Q targets for current states
            Q_targets = self.gamma * Q_targets_next * (dones)

        # Get expected Q values from local model
        Q_expected = self.q_shift_local(states).gather(1, actions)
        # Compute loss
        loss = F.mse_loss(Q_expected, Q_targets.detach())
        # Minimize the loss
        self.optimizer_shift.zero_grad()
        loss.backward()
        self.writer.add_scalar('Shift_loss', loss, self.steps)
        self.optimizer_shift.step()
    
    
    def compute_r_function(self, states, actions, debug=False, log=False):
        actions = actions.type(torch.int64)
        # sum all other actions
        # print("state shape ", states.shape)
        size = states.shape[0]
        idx = 0
        all_zeros = [1 for i in range(actions.shape[0])]
        zeros = False
        y_shift = self.q_shift_target(states).gather(1, actions).detach()
        log_a = self.get_action_prob(states, actions).detach()
        y_r_part1 = log_a - y_shift
        y_r_part2 = torch.empty((size, 1), dtype=torch.float32).to(self.device)
        for a, s in zip(actions, states):
            y_h = 0
            taken_actions = 0
            for b in self.all_actions:
                b = b.type(torch.int64).unsqueeze(1)
                n_b = self.get_action_prob(s.unsqueeze(0), b)
                if torch.eq(a, b) or n_b is None:
                    continue
                taken_actions += 1
                y_s = self.q_shift_target(s.unsqueeze(0)).detach().gather(1, b).item()
                n_b = n_b.data.item() - y_s
                r_hat = self.R_target(s.unsqueeze(0)).gather(1, b).item()
                y_h += (r_hat - n_b)
                if log:
                    text = "a {} r _hat {:.2f} - n_b  {:.2f} | sh {:.2f} ".format(b.item(), r_hat, n_b, y_s)
                    logging.debug(text)
            if taken_actions == 0:
                all_zeros[idx] = 0
                zeros = True
                y_r_part2[idx] = 0.0
            else:
                y_r_part2[idx] = (1. / taken_actions) * y_h
            idx += 1
            y_r = y_r_part1 + y_r_part2
        # check if there are zeros (no update for this tuble) remove them from states and
        if zeros:
            #print(all_zeros)
            #print(states)
            #print(actions)
            mask = torch.BoolTensor(all_zeros)
            states = states[mask]
            actions = actions[mask]
            y_r = y_r[mask]

        y = self.R_local(states).gather(1, actions)
        if log:
            text = "Action {:.2f} r target {:.2f} =  n_a {:.2f} + n_b {:.2f}  y {:.2f}".format(actions[0].item(), y_r[0].item(), y_r_part1[0].item(), y_r_part2[0].item(), y[0].item()) 
            logging.debug(text)


        r_loss = F.mse_loss(y, y_r.detach())

        # sys.exit()
        # Minimize the loss
        self.optimizer_r.zero_grad()
        r_loss.backward()
        # torch.nn.utils.clip_grad_norm_(self.R_local.parameters(), 5)
        self.optimizer_r.step()
        self.writer.add_scalar('Reward_loss', r_loss, self.steps)

    
    
    
    def get_action_prob(self, states, actions):
        """
        """
        actions = actions.type(torch.long)
        # check if action prob is zero
        output = self.predicter(states)
        output = F.softmax(output, dim=1)
        action_prob = output.gather(1, actions)
        action_prob = action_prob + torch.finfo(torch.float32).eps
        # check if one action if its to small
        if action_prob.shape[0] == 1:
            if action_prob.cpu().detach().numpy()[0][0] < 1e-4:
                return None
        action_prob = torch.log(action_prob)
        action_prob = torch.clamp(action_prob, min= self.clip, max=0)
        return action_prob


    def state_action_frq(self, states, action):
        """ Train classifer to compute state action freq
        """
        self.predicter.train()
        output = self.predicter(states, train=True)
        output = output.squeeze(0)
        # logging.debug("out predicter {})".format(output))

        y = action.type(torch.long).squeeze(1)
        #print("y shape", y.shape)
        loss = nn.CrossEntropyLoss()(output, y)
        self.optimizer_pre.zero_grad()
        loss.backward()
        #torch.nn.utils.clip_grad_norm_(self.predicter.parameters(), 1)
        self.optimizer_pre.step()
        self.writer.add_scalar('Predict_loss', loss, self.steps)
        self.predicter.eval()


    def test_predicter(self, memory):
        """

        """
        self.predicter.eval()
        same_state_predition = 0
        for i in range(memory.idx):
            states = memory.obses[i]
            actions = memory.actions[i]
        
            states = torch.as_tensor(states, device=self.device).unsqueeze(0)
            actions = torch.as_tensor(actions, device=self.device)
            output = self.predicter(states)   
            output = F.softmax(output, dim=1)
            #print("state 0", output.data)
            # create one hot encode y from actions
            y = actions.type(torch.long).item()
            p = torch.argmax(output.data).item()
            #print("a {}  p {}".format(y, p))
            text = "r  {}".format(self.R_local(states.detach()).detach()) 
            #print(text)
            if y==p:
                same_state_predition += 1
        text = "Same prediction {} of {} ".format(same_state_predition, memory.idx)
        print(text)
        logging.debug(text)




    def soft_update(self, local_model, target_model, tau=4):
        """Soft update model parameters.
        θ_target = τ*θ_local + (1 - τ)*θ_target
        Params
        ======
            local_model (PyTorch model): weights will be copied from
            target_model (PyTorch model): weights will be copied to
            tau (float): interpolation parameter
        """
        # print("use tau", tau)
        for target_param, local_param in zip(target_model.parameters(), local_model.parameters()):
            target_param.data.copy_(tau * local_param.data + (1.0 - tau) * target_param.data)
    
    def load(self, filename):
        self.predicter.load_state_dict(torch.load(filename + "_predicter.pth"))
        self.optimizer_pre.load_state_dict(torch.load(filename + "_predicter_optimizer.pth"))
        self.R_local.load_state_dict(torch.load(filename + "_r_net.pth"))
        self.qnetwork_local.load_state_dict(torch.load(filename + "_q_net.pth"))
        
        print("Load models to {}".format(filename))


    def save(self, filename):
        """
        """
        mkdir("", filename)
        torch.save(self.predicter.state_dict(), filename + "_predicter.pth")
        torch.save(self.optimizer_pre.state_dict(), filename + "_predicter_optimizer.pth")
        torch.save(self.qnetwork_local.state_dict(), filename + "_q_net.pth")
        torch.save(self.optimizer.state_dict(), filename + "_q_net_optimizer.pth")
        torch.save(self.R_local.state_dict(), filename + "_r_net.pth")
        torch.save(self.q_shift_local.state_dict(), filename + "_q_shift_net.pth")

        print("save models to {}".format(filename))

    def test_q_value(self, memory):
        test_elements = memory.idx
        all_diff = 0
        error = True
        used_elements_r = 0
        used_elements_q = 0
        r_error = 0
        q_error = 0
        for i in range(test_elements):
            states = memory.obses[i]
            actions = memory.actions[i]
            states = torch.as_tensor(states, device=self.device).unsqueeze(0)
            actions = torch.as_tensor(actions, device=self.device)
            one_hot = torch.Tensor([0 for i in range(self.action_size)], device="cpu")
            one_hot[actions.item()] = 1
            with torch.no_grad():
                r_values = self.R_local(states)
                q_values1, q_values2 = self.qnetwork_local(states)
                q_values = torch.min(q_values1, q_values2)
                soft_r = F.softmax(r_values, dim=1).to("cpu")
                soft_q = F.softmax(q_values, dim=1).to("cpu")
                actions = actions.type(torch.int64)
                kl_q =  F.kl_div(soft_q.log(), one_hot, None, None, 'sum')
                kl_r =  F.kl_div(soft_r.log(), one_hot, None, None, 'sum')
                if kl_r == float("inf"):
                    pass
                else:
                    r_error += kl_r
                    used_elements_r += 1
                if kl_q == float("inf"):
                    pass
                else:
                    q_error += kl_q
                    used_elements_q += 1
                    
        average_q_kl = q_error / used_elements_q
        average_r_kl = r_error / used_elements_r
        text = "Kl div of Reward {} of {} elements".format(average_q_kl, used_elements_r)
        print(text)
        text = "Kl div of Q_values {} of {} elements".format(average_r_kl, used_elements_q)
        print(text)
        self.writer.add_scalar('KL_reward', average_r_kl, self.steps)
        self.writer.add_scalar('KL_q_values', average_q_kl, self.steps)


    def act(self, state):
        with torch.no_grad():
            state = torch.FloatTensor(state).to(self.device).unsqueeze(0)
            action_prob, _ = self.policy(state)
            action = torch.argmax(action_prob)
            action = action.cpu().numpy()
        return action 


    def eval_policy(self, record=False, eval_episodes=4):
        if record:
            env = wrappers.Monitor(self.env, str(self.vid_path) + "/{}".format(self.steps), video_callable=lambda episode_id: True, force=True)
        else:
            env = self.env

        average_reward = 0
        scores_window = deque(maxlen=100)
        s = 0
        for i_epiosde in range(eval_episodes):
            episode_reward = 0
            state = env.reset()
            while True:
                s += 1
                action = self.act(state)
                state, reward, done, _ = env.step(action)
                episode_reward += reward
                if done:
                    break
            scores_window.append(episode_reward)
        if record:
            return 
        average_reward = np.mean(scores_window)
        print("Eval Episode {}  average Reward {} ".format(eval_episodes, average_reward))
        self.writer.add_scalar('Eval_reward', average_reward, self.steps)
コード例 #8
0
classifier.cuda()

adversarial_loss = torch.nn.MSELoss().cuda()
task_loss = torch.nn.CrossEntropyLoss().cuda()

generator.apply(weights_init_normal)
discriminator.apply(weights_init_normal)
classifier.apply(weights_init_normal)

os.makedirs("data", exist_ok=True)

train_source = get_cifar10(train=True)
train_target = get_stl10(split='train')

optimizer_G = torch.optim.Adam(itertools.chain(generator.parameters(),
                                               classifier.parameters()),
                               lr=opt.lr,
                               betas=(opt.b1, opt.b2))
optimizer_D = torch.optim.Adam(discriminator.parameters(),
                               lr=opt.lr,
                               betas=(opt.b1, opt.b2))

FloatTensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor
LongTensor = torch.cuda.LongTensor if cuda else torch.LongTensor

# ----------
#  Training
# ----------

# Keeps 100 accuracy measurements
task_performance = []
コード例 #9
0
def main():
  args = parser.parse_args()

  # model
  model = Classifier(args.channels)
  optimizer = optim.SGD(
    model.parameters(), lr=0.05, momentum=0.9, weight_decay=0.0001, nesterov=True)
  scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, args.epoch)

  if args.gpu is not None:
    model.cuda(args.gpu)

  # dataset
  raw_loader = torch.utils.data.DataLoader(
    Dataset(os.path.join(DATA_DIR, 'raw')),
    args.batch // 2, shuffle=True, drop_last=True)
  noised_loader = torch.utils.data.DataLoader(
    Dataset(os.path.join(DATA_DIR, 'noised_tgt')),
    args.batch // 2, shuffle=True, drop_last=True)

  # train
  for epoch in range(args.epoch):
    loss = 0
    accuracy = 0
    count = 0

    for x0, x1 in zip(noised_loader, raw_loader):
      if args.gpu is not None:
        x0 = x0.cuda(args.gpu)
        x1 = x1.cuda(args.gpu)

      # train
      model.train()

      x = torch.cat((x0, x1), dim=0)  # @UndefinedVariable
      t = torch.zeros((x.shape[0], 2), device=x.device).float()  # @UndefinedVariable

      t[:x0.shape[0], 0] = 1
      t[x0.shape[0]:, 1] = 1

      x, t = mixup(x, t)
      y = model(x)
      e = (-1 * nn.functional.log_softmax(y, dim=1) * t).sum(dim=1).mean()

      optimizer.zero_grad()
      e.backward()
      optimizer.step()

      # validate
      model.eval()

      with torch.no_grad():
        y0 = (model(x0).max(dim=1)[1] == 0).float()
        y1 = (model(x1).max(dim=1)[1] == 1).float()

      a = torch.cat((y0, y1), dim=0).mean()  # @UndefinedVariable

      loss += float(e) * len(x)
      accuracy += float(a) * len(x)
      count += len(x)

    print('[{}] lr={:.7f}, loss={:.4f}, accuracy={:.4f}'.format(
      epoch, float(optimizer.param_groups[0]['lr']), loss / count, accuracy / count),
      flush=True)

    scheduler.step()

    snapshot = {'channels': args.channels, 'model': model.state_dict()}
    torch.save(snapshot, '{}.tmp'.format(args.file))
    os.rename('{}.tmp'.format(args.file), args.file)
コード例 #10
0
class Agent():
    def __init__(self, state_size, action_size, action_dim, config):
        self.state_size = state_size
        self.action_size = action_size
        self.action_dim = action_dim
        self.seed = 0
        self.device = 'cuda'
        self.batch_size = config["batch_size"]
        self.lr = 0.005
        self.gamma = 0.99
        self.q_shift_local = QNetwork(state_size, action_size,
                                      self.seed).to(self.device)
        self.q_shift_target = QNetwork(state_size, action_size,
                                       self.seed).to(self.device)
        self.Q_local = QNetwork(state_size, action_size,
                                self.seed).to(self.device)
        self.Q_target = QNetwork(state_size, action_size,
                                 self.seed).to(self.device)
        self.R_local = RNetwork(state_size, action_size,
                                self.seed).to(self.device)
        self.R_target = RNetwork(state_size, action_size,
                                 self.seed).to(self.device)
        self.policy = PolicyNetwork(state_size, action_size,
                                    self.seed).to(self.device)
        self.predicter = Classifier(state_size, action_dim,
                                    self.seed).to(self.device)
        #self.criterion = nn.CrossEntropyLoss()
        # optimizer
        self.optimizer_q_shift = optim.Adam(self.q_shift_local.parameters(),
                                            lr=self.lr)
        self.optimizer_q = optim.Adam(self.Q_local.parameters(), lr=self.lr)
        self.optimizer_r = optim.Adam(self.R_local.parameters(), lr=self.lr)
        self.optimizer_p = optim.Adam(self.policy.parameters(), lr=self.lr)
        self.optimizer_pre = optim.Adam(self.predicter.parameters(),
                                        lr=self.lr)
        pathname = "lr {} batch_size {} seed {}".format(
            self.lr, self.batch_size, self.seed)
        tensorboard_name = str(config["locexp"]) + '/runs/' + pathname
        self.writer = SummaryWriter(tensorboard_name)
        self.steps = 0
        self.ratio = 1. / action_dim
        self.all_actions = []
        for a in range(self.action_dim):
            action = torch.Tensor(1) * 0 + a
            self.all_actions.append(action.to(self.device))

    def act(self, state):
        dis, action, log_probs, ent = self.policy.sample_action(
            torch.Tensor(state).unsqueeze(0))
        return dis, action, log_probs, ent

    def learn(self, memory):
        states, next_states, actions = memory.expert_policy(self.batch_size)
        # actions = actions[0]
        # print("states ",  states)
        self.state_action_frq(states, actions)
        self.get_action_prob(states, actions)
        self.compute_r_function(states, actions)
        return
        # compute difference between Q_shift and y_sh
        q_sh_value = self.q_shift_local(next_states, actions)
        y_sh = np.empty((self.batch_size, 1), dtype=np.float32)
        for idx, s in enumerate(next_states):
            q = []
            for action in self.all_actions:
                q.append(Q_target(s.unsqueeze(0), action.unsqueeze(0)))
            q_max = max(q)
            np.copyto(y_sh[idx], q_max.detach().numpy())

        y_sh = torch.Tensor(y_sh)
        y_sh *= self.gamma
        q_shift_loss = F.mse_loss(y_sh, q_shift_values)
        # Minimize the loss
        self.optimizer.zero_grad()
        q_shift_loss.backward()
        self.optimizer.step()

        #minimize MSE between pred Q and y = r'(s,a) + gama * max Q'(s',a)
        q_current = self.Q_local(states, actions)
        r_hat = self.R_target(states, actions)
        # use y_sh as target
        y_q = r_hat + y_sh

        q_loss = F.mse_loss(q_current, y_q)
        # Minimize the loss
        self.optimizer.zero_grad()
        q_loss.backward()
        self.optimizer.step()

        #  get predicted reward
        r = self.R_local(states, actions)

    def state_action_frq(self, states, action):
        """ Train classifer to compute state action freq
        """
        self.steps += 1
        output = self.predicter(states)
        # create one hot encode y from actions
        y = action.type(torch.long)
        y = y.squeeze(1)
        loss = nn.CrossEntropyLoss()(output, y)
        self.optimizer_pre.zero_grad()
        loss.backward()
        self.optimizer_pre.step()
        self.writer.add_scalar('Predict_loss', loss, self.steps)

    def get_action_prob(self, states, actions, dim=False):
        """

        """
        if dim:
            output = self.predicter(states)
            action_prob = output.gather(1, actions.type(torch.long))
            action_prob = torch.log(action_prob)
            return action_prob
        output = self.predicter(states)
        print("Output prob ", output)
        action_prob = output.gather(1, actions.type(torch.long))
        print("action prob ", action_prob)
        action_prob = torch.log(action_prob)
        print("action prob ", action_prob)
        return action_prob

    def compute_r_function(self, states, actions):
        """
        
        """
        actions = actions.type(torch.float)
        y = self.R_local(states, actions)
        y_shift = self.q_shift_target(states, actions)
        y_r_part1 = self.get_action_prob(states, actions) - y_shift
        print("ratio ", self.ratio)
        # sum all other actions
        y_r_part2 = torch.empty((self.batch_size, 1), dtype=torch.float32)
        idx = 0
        for a, s in zip(actions, states):
            y_h = 0
            for b in self.all_actions:
                if torch.eq(a, b):
                    continue
                print("diff ac ", b)
                r_hat = self.R_target(s.unsqueeze(0), b.unsqueeze(0))
                n_b = self.get_action_prob(s.unsqueeze(0), b.unsqueeze(0),
                                           True) - self.q_shift_target(
                                               s.unsqueeze(0), b.unsqueeze(0))
                y_h += (r_hat - n_b)
            y_h = self.ratio * y_h
            y_r_part2[idx] = y_h
            idx += 1
        print("shape of r y ", y.shape)
        print("y r part 1 ", y_r_part1.shape)
        print("y r part 2 ", y_r_part2.shape)
コード例 #11
0
class Agent():
    def __init__(self, state_size, action_size, config):
        self.env_name = config["env_name"]
        self.state_size = state_size
        self.action_size = action_size
        self.seed = config["seed"]
        self.clip = config["clip"]
        self.device = 'cuda'
        print("Clip ", self.clip)
        print("cuda ", torch.cuda.is_available())
        self.double_dqn = config["DDQN"]
        print("Use double dqn", self.double_dqn)
        self.lr_pre = config["lr_pre"]
        self.batch_size = config["batch_size"]
        self.lr = config["lr"]
        self.tau = config["tau"]
        print("self tau", self.tau)
        self.gamma = 0.99
        self.fc1 = config["fc1_units"]
        self.fc2 = config["fc2_units"]
        self.fc3 = config["fc3_units"]
        self.qnetwork_local = QNetwork(state_size, action_size, self.fc1, self.fc2, self.fc3, self.seed).to(self.device)
        self.qnetwork_target = QNetwork(state_size, action_size, self.fc1, self.fc2,self.fc3,  self.seed).to(self.device)
        self.optimizer = optim.Adam(self.qnetwork_local.parameters(), lr=self.lr)
        self.soft_update(self.qnetwork_local, self.qnetwork_target, 1)
        
        self.q_shift_local = QNetwork(state_size, action_size, self.fc1, self.fc2, self.fc3, self.seed).to(self.device)
        self.q_shift_target = QNetwork(state_size, action_size, self.fc1, self.fc2, self.fc3, self.seed).to(self.device)
        self.optimizer_shift = optim.Adam(self.q_shift_local.parameters(), lr=self.lr)
        self.soft_update(self.q_shift_local, self.q_shift_target, 1)
         
        self.R_local = QNetwork(state_size, action_size, self.fc1, self.fc2, self.fc3,  self.seed).to(self.device)
        self.R_target = QNetwork(state_size, action_size, self.fc1, self.fc2, self.fc3, self.seed).to(self.device)
        self.optimizer_r = optim.Adam(self.R_local.parameters(), lr=self.lr)
        self.soft_update(self.R_local, self.R_target, 1) 

        self.expert_q = DQNetwork(state_size, action_size, seed=self.seed).to(self.device)
        self.expert_q.load_state_dict(torch.load('checkpoint.pth'))
        self.memory = Memory(action_size, config["buffer_size"], self.batch_size, self.seed, self.device)
        self.t_step = 0
        self.steps = 0
        self.predicter = Classifier(state_size, action_size, self.seed).to(self.device)
        self.optimizer_pre = optim.Adam(self.predicter.parameters(), lr=self.lr_pre)
        pathname = "lr_{}_batch_size_{}_fc1_{}_fc2_{}_fc3_{}_seed_{}".format(self.lr, self.batch_size, self.fc1, self.fc2, self.fc3, self.seed)
        pathname += "_clip_{}".format(config["clip"])
        pathname += "_tau_{}".format(config["tau"])
        now = datetime.now()    
        dt_string = now.strftime("%d_%m_%Y_%H:%M:%S")
        pathname += dt_string
        tensorboard_name = str(config["locexp"]) + '/runs/' + pathname
        self.writer = SummaryWriter(tensorboard_name)
        print("summery writer ", tensorboard_name)
        self.average_prediction = deque(maxlen=100)
        self.average_same_action = deque(maxlen=100)
        self.all_actions = []
        for a in range(self.action_size):
            action = torch.Tensor(1) * 0 +  a
            self.all_actions.append(action.to(self.device))
    
    
    def learn(self, memory):
        logging.debug("--------------------------New episode-----------------------------------------------")
        states, next_states, actions, dones = memory.expert_policy(self.batch_size)
        self.steps += 1
        self.state_action_frq(states, actions)
        self.compute_shift_function(states, next_states, actions, dones)
        for i in range(1):
            for a in range(self.action_size):
                action =  torch.ones([self.batch_size, 1], device= self.device) * a
                self.compute_r_function(states, action)

        self.compute_q_function(states, next_states, actions, dones)
        self.soft_update(self.q_shift_local, self.q_shift_target, self.tau)
        self.soft_update(self.R_local, self.R_target, self.tau)
        self.soft_update(self.qnetwork_local, self.qnetwork_target, self.tau)
        return
    
    def learn_predicter(self, memory):
        """

        """
        states, next_states, actions, dones = memory.expert_policy(self.batch_size)
        self.state_action_frq(states, actions)
    
    def state_action_frq(self, states, action):
        """ Train classifer to compute state action freq
        """ 
        self.predicter.train()
        output = self.predicter(states, train=True)
        output = output.squeeze(0)
        # logging.debug("out predicter {})".format(output))

        y = action.type(torch.long).squeeze(1)
        #print("y shape", y.shape)
        loss = nn.CrossEntropyLoss()(output, y)
        self.optimizer_pre.zero_grad()
        loss.backward()
        #torch.nn.utils.clip_grad_norm_(self.predicter.parameters(), 1)
        self.optimizer_pre.step()
        self.writer.add_scalar('Predict_loss', loss, self.steps)
        self.predicter.eval()

    def test_predicter(self, memory):
        """

        """
        self.predicter.eval()
        same_state_predition = 0
        for i in range(memory.idx):
            states = memory.obses[i]
            actions = memory.actions[i]
        
            states = torch.as_tensor(states, device=self.device).unsqueeze(0)
            actions = torch.as_tensor(actions, device=self.device)
            output = self.predicter(states)   
            output = F.softmax(output, dim=1)
            # create one hot encode y from actions
            y = actions.type(torch.long).item()
            p =torch.argmax(output.data).item()
            if y==p:
                same_state_predition += 1

        
        #self.average_prediction.append(same_state_predition)
        #average_pred = np.mean(self.average_prediction)
        #self.writer.add_scalar('Average prediction acc', average_pred, self.steps)
        #logging.debug("Same prediction {} of 100".format(same_state_predition))
        text = "Same prediction {} of {} ".format(same_state_predition, memory.idx)
        print(text)
        # self.writer.add_scalar('Action prediction acc', same_state_predition, self.steps)
        self.predicter.train()


    def get_action_prob(self, states, actions):
        """
        """
        actions = actions.type(torch.long)
        # check if action prob is zero
        output = self.predicter(states)
        output = F.softmax(output, dim=1)
        # print("get action_prob ", output) 
        # output = output.squeeze(0)
        action_prob = output.gather(1, actions)
        action_prob = action_prob + torch.finfo(torch.float32).eps
        # check if one action if its to small
        if action_prob.shape[0] == 1:
            if action_prob.cpu().detach().numpy()[0][0] < 1e-4:
                return None
        # logging.debug("action_prob {})".format(action_prob))
        action_prob = torch.log(action_prob)
        action_prob = torch.clamp(action_prob, min= self.clip, max=0)
        return action_prob

    def compute_shift_function(self, states, next_states, actions, dones):
        """Update value parameters using given batch of experience tuples.
        Params
        ======
            experiences (Tuple[torch.Tensor]): tuple of (s, a, r, s', done) tuples
            gamma (float): discount factor
        """
        actions = actions.type(torch.int64)
        with torch.no_grad():
            # Get max predicted Q values (for next states) from target model
            if self.double_dqn:
                qt = self.q_shift_local(next_states)
                max_q, max_actions = qt.max(1)
                Q_targets_next = self.qnetwork_target(next_states).gather(1, max_actions.unsqueeze(1))
            else:
                Q_targets_next = self.qnetwork_target(next_states).max(1)[0].unsqueeze(1)
            # Compute Q targets for current states
            Q_targets = (self.gamma * Q_targets_next * (dones))

        # Get expected Q values from local model
        Q_expected = self.q_shift_local(states).gather(1, actions)

        # Compute loss
        loss = F.mse_loss(Q_expected, Q_targets)
        # Minimize the loss
        self.optimizer_shift.zero_grad()
        loss.backward()
        self.writer.add_scalar('Shift_loss', loss, self.steps)
        self.optimizer_shift.step()


    def compute_r_function(self, states, actions, debug=False, log=False):
        """

        """
        actions = actions.type(torch.int64)
        
        # sum all other actions
        # print("state shape ", states.shape)
        size = states.shape[0]
        idx = 0
        all_zeros = []
        with torch.no_grad():
            y_shift = self.q_shift_target(states).gather(1, actions)
            log_a = self.get_action_prob(states, actions)
            index_list = index_None_value(log_a)
            # print("is none", index_list)
            if index_list is None:
                return


            y_r_part1 = log_a - y_shift
            y_r_part2 =  torch.empty((size, 1), dtype=torch.float32).to(self.device)
            for a, s in zip(actions, states):
                y_h = 0
                taken_actions = 0
                for b in self.all_actions:
                    b = b.type(torch.int64).unsqueeze(1)
                    n_b = self.get_action_prob(s.unsqueeze(0), b)
                    if torch.eq(a, b) or n_b is None:
                        logging.debug("best action {} ".format(a))
                        logging.debug("n_b action {} ".format(b))
                        logging.debug("n_b {} ".format(n_b))
                        continue
                    taken_actions += 1
                    r_hat = self.R_target(s.unsqueeze(0)).gather(1, b)

                    y_s = self.q_shift_target(s.unsqueeze(0)).gather(1, b)
                    n_b = n_b - y_s

                    y_h += (r_hat - n_b)
                    if debug:
                        print("action", b.item())
                        print("r_pre {:.3f}".format(r_hat.item()))
                        print("n_b {:.3f}".format(n_b.item()))
                if taken_actions == 0:
                    all_zeros.append(idx)
                else:
                    y_r_part2[idx] = (1. / taken_actions)  * y_h
                idx += 1
            #print(y_r_part2, y_r_part1)
            y_r = y_r_part1 + y_r_part2
            #print("_________________")
            #print("r update zeros ", len(all_zeros))
        if len(index_list) > 0:
            print("none list", index_list)
        y = self.R_local(states).gather(1, actions)
        if log:
            text = "Action {:.2f}  y target {:.2f} =  n_a {:.2f} + {:.2f} and pre{:.2f}".format(actions.item(), y_r.item(), y_r_part1.item(), y_r_part2.item(), y.item())
            logging.debug(text)

        if debug:
            print("expet action ", actions.item())
            # print("y r {:.3f}".format(y.item()))
            # print("log a prob {:.3f}".format(log_a.item()))
            # print("n_a {:.3f}".format(y_r_part1.item()))
            print("Correct action p {:.3f} ".format(y.item()))
            print("Correct action target {:.3f} ".format(y_r.item()))
            print("part1 corret action {:.2f} ".format(y_r_part1.item()))
            print("part2 incorret action {:.2f} ".format(y_r_part2.item()))
        
        #print("y", y.shape)
        #print("y_r", y_r.shape)
        
        r_loss = F.mse_loss(y, y_r)
        
        #con = input()
        #sys.exit()
        # Minimize the loss
        self.optimizer_r.zero_grad()
        r_loss.backward()
        #torch.nn.utils.clip_grad_norm_(self.R_local.parameters(), 5)
        self.optimizer_r.step()
        self.writer.add_scalar('Reward_loss', r_loss, self.steps)
        if debug:
            print("after update r pre ", self.R_local(states).gather(1, actions).item())
            print("after update r target ", self.R_target(states).gather(1, actions).item())
        # ------------------- update target network ------------------- #
        #self.soft_update(self.R_local, self.R_target, 5e-3)
        if debug:
            print("after soft upda r target ", self.R_target(states).gather(1, actions).item())
    
    def compute_q_function(self, states, next_states, actions, dones, debug=False, log= False):
        """Update value parameters using given batch of experience tuples.
        Params
        ======
            experiences (Tuple[torch.Tensor]): tuple of (s, a, r, s', done) tuples
            gamma (float): discount factor
        """
        actions = actions.type(torch.int64)
        if debug:
            print("---------------q_update------------------")
            print("expet action ", actions.item())
            print("state ", states)
        with torch.no_grad():
            # Get max predicted Q values (for next states) from target model
            if self.double_dqn:
                qt = self.qnetwork_local(next_states)
                max_q, max_actions = qt.max(1)
                Q_targets_next = self.qnetwork_target(next_states).gather(1, max_actions.unsqueeze(1))
            else:
                Q_targets_next = self.qnetwork_target(next_states).max(1)[0].unsqueeze(1)
            # Compute Q targets for current states
            rewards = self.R_target(states).gather(1, actions)
            Q_targets = rewards + (self.gamma * Q_targets_next * (dones))
            if debug:
                print("reward  {}".format(rewards.item()))
                print("Q target next {}".format(Q_targets_next.item()))
                print("Q_target {}".format(Q_targets.item()))



        # Get expected Q values from local model
        Q_expected = self.qnetwork_local(states).gather(1, actions)
        if log:
            text = "Action {:.2f}  q target {:.2f} =  r_a {:.2f} + target {:.2f} and pre{:.2f}".format(actions.item(), Q_targets.item(), rewards.item(), Q_targets_next.item(), Q_expected.item())
            logging.debug(text)
        if debug:
            print("q for a {}".format(Q_expected))
        # Compute loss
        loss = F.mse_loss(Q_expected, Q_targets)
        self.writer.add_scalar('Q_loss', loss, self.steps)
        # Minimize the loss
        self.optimizer.zero_grad()
        loss.backward()
        self.optimizer.step()
        if debug:
            print("q after update {}".format(self.qnetwork_local(states)))
            print("q loss {}".format(loss.item()))


        # ------------------- update target network ------------------- #



    def dqn_train(self, n_episodes=2000, max_t=1000, eps_start=1.0, eps_end=0.01, eps_decay=0.995):
        env =  gym.make('LunarLander-v2')
        scores = []                        # list containing scores from each episode
        scores_window = deque(maxlen=100)  # last 100 scores
        eps = eps_start
        for i_episode in range(1, n_episodes+1):
            state = env.reset()
            score = 0
            for t in range(max_t):
                self.t_step += 1
                action = self.dqn_act(state, eps)
                next_state, reward, done, _ = env.step(action)
                self.step(state, action, reward, next_state, done)
                state = next_state
                score += reward
                if done:
                    self.test_q()
                    break
            scores_window.append(score)       # save most recent score
            scores.append(score)              # save most recent score
            eps = max(eps_end, eps_decay*eps) # decrease epsilon
            print('\rEpisode {}\tAverage Score: {:.2f}'.format(i_episode, np.mean(scores_window)), end="")
            if i_episode % 100 == 0:
                print('\rEpisode {}\tAverage Score: {:.2f}'.format(i_episode, np.mean(scores_window)))
            if np.mean(scores_window)>=200.0:
                print('\nEnvironment solved in {:d} episodes!\tAverage Score: {:.2f}'.format(i_episode-100, np.mean(scores_window)))
                break



    def test_policy(self):
        env =  gym.make('LunarLander-v2')
        logging.debug("new episode")
        average_score = [] 
        average_steps = []
        average_action = []
        for i in range(5):
            state = env.reset()
            score = 0
            same_action = 0
            logging.debug("new episode")
            for t in range(200):
                state = torch.from_numpy(state).float().unsqueeze(0).to(self.device)
                q_expert = self.expert_q(state)
                q_values = self.qnetwork_local(state)
                logging.debug("q expert a0: {:.2f} a1: {:.2f} a2: {:.2f} a3: {:.2f}".format(q_expert.data[0][0], q_expert.data[0][1], q_expert.data[0][2], q_expert.data[0][3]))
                logging.debug("q values a0: {:.2f} a1: {:.2f} a2: {:.2f} a3: {:.2f}  )".format(q_values.data[0][0], q_values.data[0][1], q_values.data[0][2], q_values.data[0][3]))
                action = torch.argmax(q_values).item()
                action_e = torch.argmax(q_expert).item()
                if action == action_e:
                    same_action += 1
                next_state, reward, done, _ = env.step(action)
                state = next_state
                score += reward
                if done:
                    average_score.append(score)
                    average_steps.append(t)
                    average_action.append(same_action)
                    break
        mean_steps = np.mean(average_steps)
        mean_score = np.mean(average_score)
        mean_action= np.mean(average_action)
        self.writer.add_scalar('Ave_epsiode_length', mean_steps , self.steps)
        self.writer.add_scalar('Ave_same_action', mean_action, self.steps)
        self.writer.add_scalar('Ave_score', mean_score, self.steps)


    def step(self, state, action, reward, next_state, done):
        # Save experience in replay memory
        self.memory.add(state, action, reward, next_state, done)

        # Learn every UPDATE_EVERY time steps.
        self.t_step = (self.t_step + 1) % 4
        if self.t_step == 0:
            # If enough samples are available in memory, get random subset and learn
            if len(self.memory) > self.batch_size:
                experiences = self.memory.sample()
                self.update_q(experiences)


    def dqn_act(self, state, eps=0.):
        """Returns actions for given state as per current policy.

        Params
        ======
            state (array_like): current state
            eps (float): epsilon, for epsilon-greedy action selection
        """
        state = torch.from_numpy(state).float().unsqueeze(0).to(device)
        self.qnetwork_local.eval()
        with torch.no_grad():
            action_values = self.qnetwork_local(state)
        self.qnetwork_local.train()

        # Epsilon-greedy action selection
        if random.random() > eps:
            return np.argmax(action_values.cpu().data.numpy())
        else:
            return random.choice(np.arange(self.action_size))

    def update_q(self, experiences, debug=False):
        """Update value parameters using given batch of experience tuples.
        Params
        ======
            experiences (Tuple[torch.Tensor]): tuple of (s, a, r, s', done) tuples
            gamma (float): discount factor
        """
        states, actions, rewards, next_states, dones = experiences
        # Get max predicted Q values (for next states) from target model
        with torch.no_grad():
            Q_targets_next = self.qnetwork_target(next_states).max(1)[0].unsqueeze(1)
            # Compute Q targets for current states
            Q_targets = rewards + (self.gamma * Q_targets_next * (1 - dones))

        # Get expected Q values from local model
        Q_expected = self.qnetwork_local(states).gather(1, actions)
        if debug:
            print("----------------------")
            print("----------------------")
            print("Q target", Q_targets)
            print("pre", Q_expected)
            print("all local",self.qnetwork_local(states))

        # Compute loss
        loss = F.mse_loss(Q_expected, Q_targets)
        # Minimize the loss
        self.optimizer.zero_grad()
        loss.backward()
        self.optimizer.step()

        # ------------------- update target network ------------------- #
        self.soft_update(self.qnetwork_local, self.qnetwork_target)



    def test_q(self):
        experiences = self.memory.test_sample()
        self.update_q(experiences, True)

    def test_q_value(self, memory):
        same_action = 0
        test_elements = memory.idx
        all_diff = 0
        error = True
        self.predicter.eval()
        for i in range(test_elements):
            # print("lop", i)
            states = memory.obses[i]
            next_states = memory.next_obses[i]
            actions = memory.actions[i]
            dones = memory.not_dones[i]
            states = torch.as_tensor(states, device=self.device).unsqueeze(0)
            next_states = torch.as_tensor(next_states, device=self.device)
            actions = torch.as_tensor(actions, device=self.device)
            dones = torch.as_tensor(dones, device=self.device)
            with torch.no_grad():
                output = self.predicter(states)
                output = F.softmax(output, dim=1)
                q_values = self.qnetwork_local(states)
                expert_values = self.expert_q(states)
                print("q values ", q_values)
                print("ex values  ", expert_values)
                best_action = torch.argmax(q_values).item()
                actions = actions.type(torch.int64)
                q_max = q_values.max(1)
                
                #print("q values", q_values)
                q = q_values[0][actions.item()].item()
                #print("q action", q)
                max_q =  q_max[0].data.item()
                diff = max_q - q
                all_diff += diff
                #print("q best", max_q)
                #print("difference ", diff)
            if  actions.item() != best_action:
                r = self.R_local(states)
                rt = self.R_target(states)
                qt = self.qnetwork_target(states)
                logging.debug("------------------false action --------------------------------")
                logging.debug("expert action  {})".format(actions.item()))
                logging.debug("out predicter a0: {:.2f} a1: {:.2f} a2: {:.2f} a3: {:.2f}  )".format(output.data[0][0], output.data[0][1], output.data[0][2], output.data[0][3]))
                logging.debug("q values a0: {:.2f} a1: {:.2f} a2: {:.2f} a3: {:.2f}  )".format(q_values.data[0][0], q_values.data[0][1], q_values.data[0][2], q_values.data[0][3]))
                logging.debug("q target a0: {:.2f} a1: {:.2f} a2: {:.2f} a3: {:.2f}  )".format(qt.data[0][0], qt.data[0][1], qt.data[0][2], qt.data[0][3]))
                logging.debug("rewards a0: {:.2f} a1: {:.2f} a2: {:.2f} a3: {:.2f}  )".format(r.data[0][0], r.data[0][1], r.data[0][2], r.data[0][3]))
                logging.debug("re target a0: {:.2f} a1: {:.2f} a2: {:.2f} a3: {:.2f}  )".format(rt.data[0][0], rt.data[0][1], rt.data[0][2], rt.data[0][3]))
                """ 
                logging.debug("---------Reward Function------------")
                action = torch.Tensor(1) * 0 +  0
                self.compute_r_function(states, action.unsqueeze(0).to(self.device), log= True)
                action = torch.Tensor(1) * 0 +  1
                self.compute_r_function(states, action.unsqueeze(0).to(self.device), log= True)
                action = torch.Tensor(1) * 0 +  2
                self.compute_r_function(states, action.unsqueeze(0).to(self.device), log= True)
                action = torch.Tensor(1) * 0 +  3
                self.compute_r_function(states, action.unsqueeze(0).to(self.device), log= True)
                logging.debug("------------------Q Function --------------------------------")
                action = torch.Tensor(1) * 0 +  0
                self.compute_q_function(states, next_states.unsqueeze(0), action.unsqueeze(0).to(self.device), dones, log= True)
                action = torch.Tensor(1) * 0 +  1
                self.compute_q_function(states, next_states.unsqueeze(0), action.unsqueeze(0).to(self.device), dones, log= True)
                action = torch.Tensor(1) * 0 +  2
                self.compute_q_function(states, next_states.unsqueeze(0), action.unsqueeze(0).to(self.device), dones, log= True)
                action = torch.Tensor(1) * 0 +  3
                self.compute_q_function(states, next_states.unsqueeze(0), action.unsqueeze(0).to(self.device), dones, log= True)
                """
                

            if  actions.item() == best_action:
                same_action += 1
                continue
                print("-------------------------------------------------------------------------------")
                print("state ", i)
                print("expert ", actions)
                print("q values", q_values.data)
                print("action prob predicter  ", output.data)
                self.compute_r_function(states, actions.unsqueeze(0), True)
                self.compute_q_function(states, next_states.unsqueeze(0), actions.unsqueeze(0), dones, True)
            else:
                if error:
                    continue
                    print("-------------------------------------------------------------------------------")
                    print("expert action ", actions.item())
                    print("best action q ", best_action)
                    print(i)
                    error = False
                continue
                # logging.debug("experte action  {} q fun {}".format(actions.item(), q_values))
                print("-------------------------------------------------------------------------------")
                print("state ", i)
                print("expert ", actions)
                print("q values", q_values.data)
                print("action prob predicter  ", output.data)
                self.compute_r_function(states, actions.unsqueeze(0), True)
                self.compute_q_function(states, next_states.unsqueeze(0), actions.unsqueeze(0), dones, True)


        self.writer.add_scalar('diff', all_diff, self.steps)
        self.average_same_action.append(same_action)
        av_action = np.mean(self.average_same_action)
        self.writer.add_scalar('Same_action', same_action, self.steps)
        print("Same actions {}  of {}".format(same_action, test_elements))
        self.predicter.train()


    def soft_update(self, local_model, target_model, tau=4):
        """Soft update model parameters.
        θ_target = τ*θ_local + (1 - τ)*θ_target
        Params
        ======
            local_model (PyTorch model): weights will be copied from
            target_model (PyTorch model): weights will be copied to
            tau (float): interpolation parameter
        """
        # print("use tau", tau)
        for target_param, local_param in zip(target_model.parameters(), local_model.parameters()):
            target_param.data.copy_(tau * local_param.data + (1.0 - tau) * target_param.data)
    
    def save(self, filename):
        """

        """
        mkdir("", filename)
        torch.save(self.predicter.state_dict(), filename + "_predicter.pth")
        torch.save(self.optimizer_pre.state_dict(), filename + "_predicter_optimizer.pth")
        torch.save(self.qnetwork_local.state_dict(), filename + "_q_net.pth")
        """
        torch.save(self.optimizer_q.state_dict(), filename + "_q_net_optimizer.pth")
        torch.save(self.q_shift_local.state_dict(), filename + "_q_shift_net.pth")
        torch.save(self.optimizer_q_shift.state_dict(), filename + "_q_shift_net_optimizer.pth")
        """
        print("save models to {}".format(filename))
    
    def load(self, filename):
        self.predicter.load_state_dict(torch.load(filename + "_predicter.pth"))
        self.optimizer_pre.load_state_dict(torch.load(filename + "_predicter_optimizer.pth"))
        print("Load models to {}".format(filename))
コード例 #12
0
                        help='number of nonterminals')
    args = parser.parse_args()

    # Create dataset, model, and optimizer
    train_set = NonterminalFeaturesDataset(os.path.join(
        args.data_dir, 'train'))
    train_loader = DataLoader(train_set, batch_size=None)
    val_set = NonterminalFeaturesDataset(os.path.join(args.data_dir, 'val'))
    val_loader = DataLoader(train_set, batch_size=None)
    gen_set = NonterminalFeaturesDataset(os.path.join(args.data_dir, 'gen'))
    gen_loader = DataLoader(train_set, batch_size=None)

    classifier = Classifier(args.features, args.nonterminals)
    classifier = classifier.to(device)

    optimizer = torch.optim.SGD(classifier.parameters(), lr=args.lr)

    # Trainer and metrics
    save_dict = {'classifier': classifier}
    trainer = Engine(step_train(classifier, optimizer))
    metric_names = ['loss', 'accuracy']
    RunningAverage(Loss(F.cross_entropy, lambda x:
                        (x['y_pred'], x['y_true']))).attach(trainer, 'loss')
    RunningAverage(Accuracy(lambda x: (x['y_pred'], x['y_true']))).attach(
        trainer, 'accuracy')

    # Evaluator and metrics
    evaluator = Engine(step_train(classifier, None, train=False))
    Accuracy(lambda x: (x['y_pred'], x['y_true'])).attach(
        evaluator, 'accuracy')
コード例 #13
0
class Trainer:
    def __init__(self, device, dset, x_dim, c_dim, z_dim, n_train, n_test, lr,
                 layer_sizes, **kwargs):
        '''
        Trainer class
        Args:
            device (torch.device) : Use GPU or CPU
            x_dim (int)           : Feature dimension
            c_dim (int)           : Attribute dimension
            z_dim (int)           : Latent dimension
            n_train (int)         : Number of training classes
            n_test (int)          : Number of testing classes
            lr (float)            : Learning rate for VAE
            layer_sizes(dict)     : List containing the hidden layer sizes
            **kwargs              : Flags for using various regularizations
        '''
        self.device = device
        self.dset = dset
        self.lr = lr
        self.z_dim = z_dim

        self.n_train = n_train
        self.n_test = n_test
        self.gzsl = kwargs.get('gzsl', False)
        if self.gzsl:
            self.n_test = n_train + n_test

        # flags for various regularizers
        self.use_da = kwargs.get('use_da', False)
        self.use_ca = kwargs.get('use_ca', False)
        self.use_support = kwargs.get('use_support', False)

        self.x_encoder = Encoder(x_dim, layer_sizes['x_enc'],
                                 z_dim).to(self.device)
        self.x_decoder = Decoder(z_dim, layer_sizes['x_dec'],
                                 x_dim).to(self.device)

        self.c_encoder = Encoder(c_dim, layer_sizes['c_enc'],
                                 z_dim).to(self.device)
        self.c_decoder = Decoder(z_dim, layer_sizes['c_dec'],
                                 c_dim).to(self.device)

        self.support_classifier = Classifier(z_dim,
                                             self.n_train).to(self.device)

        params = list(self.x_encoder.parameters()) + \
                 list(self.x_decoder.parameters()) + \
                 list(self.c_encoder.parameters()) + \
                 list(self.c_decoder.parameters())

        if self.use_support:
            params += list(self.support_classifier.parameters())

        self.optimizer = optim.Adam(params, lr=lr)

        self.final_classifier = Classifier(z_dim, self.n_test).to(self.device)
        self.final_cls_optim = optim.RMSprop(
            self.final_classifier.parameters(), lr=2e-4)
        self.criterion = nn.CrossEntropyLoss()

        self.vae_save_path = './saved_models'
        self.disc_save_path = './saved_models/disc_model_%s.pth' % self.dset

    def fit_VAE(self, x, c, y, ep):
        '''
        Train on 1 minibatch of data
        Args:
            x (torch.Tensor) : Features of size (batch_size, 2048)
            c (torch.Tensor) : Attributes of size (batch_size, attr_dim)
            y (torch.Tensor) : Target labels of size (batch_size,)
            ep (int)         : Epoch number
        Returns:
            Loss for the minibatch -
            3-tuple with (vae_loss, distributn loss, cross_recon loss)
        '''
        self.anneal_parameters(ep)

        x = Variable(x.float()).to(self.device)
        c = Variable(c.float()).to(self.device)
        y = Variable(y.long()).to(self.device)

        # VAE for image embeddings
        mu_x, logvar_x = self.x_encoder(x)
        z_x = self.reparameterize(mu_x, logvar_x)
        x_recon = self.x_decoder(z_x)

        # VAE for class embeddings
        mu_c, logvar_c = self.c_encoder(c)
        z_c = self.reparameterize(mu_c, logvar_c)
        c_recon = self.c_decoder(z_c)

        # reconstruction loss
        L_recon_x = self.compute_recon_loss(x, x_recon)
        L_recon_c = self.compute_recon_loss(c, c_recon)

        # KL divergence loss
        D_kl_x = self.compute_kl_div(mu_x, logvar_x)
        D_kl_c = self.compute_kl_div(mu_c, logvar_c)

        # VAE Loss = recon_loss - KL_Divergence_loss
        L_vae_x = L_recon_x - self.beta * D_kl_x
        L_vae_c = L_recon_c - self.beta * D_kl_c
        L_vae = L_vae_x + L_vae_c

        # calculate cross alignment loss
        L_ca = torch.zeros(1).to(self.device)
        if self.use_ca:
            x_recon_from_c = self.x_decoder(z_c)
            L_ca_x = self.compute_recon_loss(x, x_recon_from_c)

            c_recon_from_x = self.c_decoder(z_x)
            L_ca_c = self.compute_recon_loss(c, c_recon_from_x)

            L_ca = L_ca_x + L_ca_c

        # calculate distribution alignment loss
        L_da = torch.zeros(1).to(self.device)
        if self.use_da:
            L_da = 2 * self.compute_da_loss(mu_x, logvar_x, mu_c, logvar_c)

        # calculate loss from support classifier
        L_sup = torch.zeros(1).to(self.device)
        if self.use_support:
            y_prob = F.softmax(self.support_classifier(z_x), dim=0)
            log_prob = torch.log(torch.gather(y_prob, 1, y.unsqueeze(1)))
            L_sup = -1 * torch.mean(log_prob)

        total_loss = L_vae + self.gamma * L_ca + self.delta * L_da + self.alpha * L_sup

        self.optimizer.zero_grad()
        total_loss.backward()
        self.optimizer.step()

        return L_vae.item(), L_da.item(), L_ca.item()

    def reparameterize(self, mu, log_var):
        '''
        Reparameterization trick using unimodal gaussian
        '''
        # eps = Variable(torch.randn(mu.size())).to(self.device)
        eps = Variable(torch.randn(mu.size()[0],
                                   1).expand(mu.size())).to(self.device)
        z = mu + torch.exp(log_var / 2.0) * eps
        return z

    def anneal_parameters(self, epoch):
        '''
        Change weight factors of various losses based on epoch number
        '''
        # weight of kl divergence loss
        if epoch <= 90:
            self.beta = 0.0026 * epoch

        # weight of Cross Alignment loss
        if epoch < 20:
            self.gamma = 0
        if epoch >= 20 and epoch <= 75:
            self.gamma = 0.044 * (epoch - 20)

        # weight of distribution alignment loss
        if epoch < 5:
            self.delta = 0
        if epoch >= 5 and epoch <= 22:
            self.delta = 0.54 * (epoch - 5)

        # weight of support loss
        if epoch < 5:
            self.alpha = 0
        else:
            self.alpha = 0.01

    def compute_recon_loss(self, x, x_recon):
        '''
        Compute the reconstruction error.
        '''
        l1_loss = torch.abs(x - x_recon).sum()
        # l1_loss = torch.abs(x - x_recon).sum(dim=1).mean()
        return l1_loss

    def compute_kl_div(self, mu, log_var):
        '''
        Compute KL Divergence between N(mu, var) & N(0, 1).
        '''
        kld = 0.5 * (1 + log_var - mu.pow(2) - log_var.exp()).sum()
        # kld = 0.5 * (1 + log_var - mu.pow(2) - log_var.exp()).sum(dim=1).mean()
        return kld

    def compute_da_loss(self, mu1, log_var1, mu2, log_var2):
        '''
        Computes Distribution Alignment loss between 2 normal distributions.
        Uses Wasserstein distance as distance measure.
        '''
        l1 = (mu1 - mu2).pow(2).sum(dim=1)

        std1 = (log_var1 / 2.0).exp()
        std2 = (log_var2 / 2.0).exp()
        l2 = (std1 - std2).pow(2).sum(dim=1)

        l_da = torch.sqrt(l1 + l2).sum()
        return l_da

    def fit_final_classifier(self, x, y):
        '''
        Train the final classifier on synthetically generated data
        '''
        x = Variable(x.float()).to(self.device)
        y = Variable(y.long()).to(self.device)

        logits = self.final_classifier(x)
        loss = self.criterion(logits, y)

        self.final_cls_optim.zero_grad()
        loss.backward()
        self.final_cls_optim.step()

        return loss.item()

    def fit_MOE(self, x, y):
        '''
        Trains the synthetic dataset on a MoE model
        '''

    def get_vae_savename(self):
        '''
        Returns a string indicative of various flags used during training and
        dataset used. Works as a unique name for saving models
        '''
        flags = ''
        if self.use_da:
            flags += '-da'
        if self.use_ca:
            flags += '-ca'
        if self.use_support:
            flags += '-support'
        model_name = 'vae_model__dset-%s__lr-%f__z-%d__%s.pth' % (
            self.dset, self.lr, self.z_dim, flags)
        return model_name

    def save_VAE(self, ep):
        state = {
            'epoch': ep,
            'x_encoder': self.x_encoder.state_dict(),
            'x_decoder': self.x_decoder.state_dict(),
            'c_encoder': self.c_encoder.state_dict(),
            'c_decoder': self.c_decoder.state_dict(),
            'optimizer': self.optimizer.state_dict(),
        }
        model_name = self.get_vae_savename()
        torch.save(state, os.path.join(self.vae_save_path, model_name))

    def load_models(self, model_path=''):
        if model_path is '':
            model_path = os.path.join(self.vae_save_path,
                                      self.get_vae_savename())

        ep = 0
        if os.path.exists(model_path):
            checkpoint = torch.load(model_path)
            self.x_encoder.load_state_dict(checkpoint['x_encoder'])
            self.x_decoder.load_state_dict(checkpoint['x_decoder'])
            self.c_encoder.load_state_dict(checkpoint['c_encoder'])
            self.c_decoder.load_state_dict(checkpoint['c_decoder'])
            self.optimizer.load_state_dict(checkpoint['optimizer'])
            ep = checkpoint['epoch']

        return ep

    def create_syn_dataset(self,
                           test_labels,
                           attributes,
                           seen_dataset,
                           n_samples=400):
        '''
        Creates a synthetic dataset based on attribute vectors of unseen class
        Args:
            test_labels: A dict with key as original serial number in provided
                dataset and value as the index which is predicted during
                classification by network
            attributes: A np array containing class attributes for each class
                of dataset
            seen_dataset: A list of 3-tuple (x, _, y) where x belongs to one of the
                seen classes and y is corresponding label. Used for generating
                latent representations of seen classes in GZSL
            n_samples: Number of samples of each unseen class to be generated(Default: 400)
        Returns:
            A list of 3-tuple (z, _, y) where z is latent representations and y is
            corresponding label
        '''
        syn_dataset = []
        for test_cls, idx in test_labels.items():
            attr = attributes[test_cls - 1]

            self.c_encoder.eval()
            c = Variable(torch.FloatTensor(attr).unsqueeze(0)).to(self.device)
            mu, log_var = self.c_encoder(c)

            Z = torch.cat(
                [self.reparameterize(mu, log_var) for _ in range(n_samples)])

            syn_dataset.extend([(Z[i], test_cls, idx)
                                for i in range(n_samples)])

        if seen_dataset is not None:
            self.x_encoder.eval()
            for (x, att_idx, y) in seen_dataset:
                x = Variable(torch.FloatTensor(x).unsqueeze(0)).to(self.device)
                mu, log_var = self.x_encoder(x)
                z = self.reparameterize(mu, log_var).squeeze()
                syn_dataset.append((z, att_idx, y))

        return syn_dataset

    def compute_accuracy(self, generator):
        y_real_list, y_pred_list = [], []

        for idx, (x, _, y) in enumerate(generator):
            x = Variable(x.float()).to(self.device)
            y = Variable(y.long()).to(self.device)

            self.final_classifier.eval()
            self.x_encoder.eval()
            mu, log_var = self.x_encoder(x)
            logits = self.final_classifier(mu)

            _, y_pred = logits.max(dim=1)

            y_real = y.detach().cpu().numpy()
            y_pred = y_pred.detach().cpu().numpy()

            y_real_list.extend(y_real)
            y_pred_list.extend(y_pred)

        ## We have sequence of real and predicted labels
        ## find seen and unseen classes accuracy

        if self.gzsl:
            y_real_list = np.asarray(y_real_list)
            y_pred_list = np.asarray(y_pred_list)

            y_seen_real = np.extract(y_real_list < self.n_train, y_real_list)
            y_seen_pred = np.extract(y_real_list < self.n_train, y_pred_list)

            y_unseen_real = np.extract(y_real_list >= self.n_train,
                                       y_real_list)
            y_unseen_pred = np.extract(y_real_list >= self.n_train,
                                       y_pred_list)

            acc_seen = accuracy_score(y_seen_real, y_seen_pred)
            acc_unseen = accuracy_score(y_unseen_real, y_unseen_pred)

            return acc_seen, acc_unseen

        else:
            return accuracy_score(y_real_list, y_pred_list)
コード例 #14
0
def TrainSourceModel(options):
    #defining the models
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    options['device'] = device
    cEnc = ConvEncoder(latentDimension=options['latentD']).to(device)
    disc = Discriminator(latentDimension=options['latentD']).to(device)
    classify = Classifier(latentDimension=options['latentD']).to(device)

    # defining loss functions
    MSELoss = nn.MSELoss().to(device)  # mean squared error loss
    BCELoss = nn.BCELoss().to(device)  # binary cross-entropy
    NLLLoss = nn.NLLLoss().to(device)  # negative-log likelihood
    CELoss = nn.CrossEntropyLoss().to(device)  # cross entropy loss

    # loss log data
    lossData_a, lossData_b = [], []

    optimizer_a = optim.Adam(itertools.chain(cEnc.parameters(),
                                             classify.parameters()),
                             lr=options['lrA'])
    optimizer_b = optim.Adam(itertools.chain(disc.parameters()),
                             lr=options['lrB'])

    logText = ""
    train_loader = options['trainLoader']

    for epochIdx in range(options['epochs']):

        # defining the data loaders
        _ones = Variable(torch.FloatTensor(options['batchSize'], 1).fill_(1.0),
                         requires_grad=False).to(device)
        _zeros = Variable(torch.FloatTensor(options['batchSize'],
                                            1).fill_(0.0),
                          requires_grad=False).to(device)

        for batchIdx, (batchData, batchLabels) in enumerate(train_loader):

            # data setup
            _batchSize = batchData.shape[0]
            batchData = batchData.to(device)
            batchLabels = batchLabels.to(device)
            latentSpaceSample_A, latentSpaceClasses_A = getSampleFromLatentSpace(
                [_batchSize, options['latentD']], options)

            # convAutoencoder Pass
            encodedDataBatch = cEnc(batchData)
            classesPrediction = classify(encodedDataBatch)

            #sample pass
            sampleClassesPrediction = classify(latentSpaceSample_A)

            # optimzation step I
            optimizer_a.zero_grad()
            #--- first loss function
            loss_a = CELoss(classesPrediction, batchLabels)+\
                     options["lrA_DiscCoeff"]*BCELoss(disc(encodedDataBatch),_ones[:_batchSize])+\
                     CELoss(sampleClassesPrediction,latentSpaceClasses_A)

            loss_a.backward()
            optimizer_a.step()
            lossData_a.append(loss_a.data.item())

            # optimization step II
            #---train the discriminator, 1/0 is real/fake data
            optimizer_b.zero_grad()
            latentSpaceSample_B, latentSpaceClasses_B = getSampleFromLatentSpace(
                [_batchSize, options['latentD']], options)
            discDataInput = Variable(encodedDataBatch.view(
                _batchSize, options['latentD']).cpu().data,
                                     requires_grad=False).to(device)

            #---second loss function
            loss_b=BCELoss(disc(discDataInput),_zeros[:_batchSize])+\
                   BCELoss(disc(latentSpaceSample_B),_ones[:_batchSize])
            loss_b.backward()
            optimizer_b.step()
            lossData_b.append(loss_b.data.item())

            # print running accuracy on this batchData
            #predictedLabeles = classesPrediction.argmax(1)
            # print("{}/{} accuracy, and loss={}".format(float(torch.sum(predictedLabeles == batchLabels).data.cpu().numpy()),_batchSize,loss_a.data.item()))

        ####
        #### End of an epoch
        ####

        logText += validateModel(epochIdx,
                                 options,
                                 models=[cEnc, classify, disc])
        # end of an epoch - CHECK ACCURACY ON TEST SET

    outputs = {
        'lossA': lossData_a,
        'lossB': lossData_b,
        'encoder': cEnc,
        'disc': disc,
        'classifier': classify,
        'logText': logText
    }
    return outputs
コード例 #15
0
class MLCModel:
    """Summary
    Attributes:
        cfg (TYPE): Description
        criterion (TYPE): Description
        device (TYPE): cpu or gpu
        hparams (TYPE): hyper parameters from parser
        labels (TYPE): list of the diseases, see init_labels()
        model (TYPE): feature extraction backbone with classifier, see cfg.json
        names (TYPE): list of filenames in the images which have been from dataloader
        num_tasks (TYPE): 5 or 14, number of diseases
    """
    def __init__(self, hparams):
        """Summary

        Args:
            hparams (TYPE): hyper parameters from parser
        """
        super(MLCModel, self).__init__()
        self.hparams = hparams
        self.device = torch.device("cuda:{}".format(hparams.gpus) if torch.
                                   cuda.is_available() else "cpu")

        with open(self.hparams.json_path, 'r') as f:
            self.cfg = edict(json.load(f))
            hparams_dict = vars(self.hparams)
            self.cfg['hparams'] = hparams_dict
            if self.hparams.verbose is True:
                print(json.dumps(self.cfg, indent=4))

        if self.cfg.criterion in ['bce', 'focal', 'sce', 'bce_v2', 'bfocal']:
            self.criterion = init_loss_func(self.cfg.criterion,
                                            device=self.device)
        elif self.cfg.criterion == 'class_balance':
            samples_per_cls = list(
                map(int, self.cfg.samples_per_cls.split(',')))
            self.criterion = init_loss_func(self.cfg.criterion,
                                            samples_per_cls=samples_per_cls,
                                            loss_type=self.cfg.loss_type)
        else:
            self.criterion = init_loss_func(self.cfg.criterion)

        self.labels = init_labels(name=self.hparams.data_name)
        if self.cfg.extract_fields is None:
            self.cfg.extract_fields = ','.join(
                [str(idx) for idx in range(len(self.labels))])
        else:
            assert isinstance(self.cfg.extract_fields,
                              str), "extract_fields must be string!"

        self.model = Classifier(self.cfg, self.hparams)
        self.state_dict = None
        # Load cross-model from other configuration
        if self.hparams.load is not None and len(self.hparams.load) > 0:
            if not os.path.exists(hparams.load):
                raise ValueError('{} does not exists!'.format(hparams.load))
            state_dict = load_state_dict(self.hparams.load, self.model,
                                         self.device)
            self.state_dict = state_dict

        # DataParallel model
        if torch.cuda.device_count() > 1 and self.hparams.gpus == 0:
            self.model = nn.DataParallel(self.model)

        self.model.to(device=self.device)
        self.num_tasks = list(map(int, self.cfg.extract_fields.split(',')))
        self.names = list()
        self.optimizer, self.scheduler = self.configure_optimizers()
        self.train_loader = self.train_dataloader()
        self.valid_loader = self.val_dataloader()
        self.test_loader = self.test_dataloader()

    def forward(self, x):
        """Summary

        Args:
            x (TYPE): image

        Returns:
            TYPE: Description
        """
        return self.model(x)

    def train(self):
        epoch_start = 0

        summary_train = {
            'epoch': 0,
            'step': 0,
            'total_step': len(self.train_loader)
        }
        summary_dev = {'loss': float('inf'), 'score': 0.0}
        best_dict = {
            "score_dev_best": 0.0,
            "loss_dev_best": float('inf'),
            "score_top_k": [0.0],
            "loss_top_k": [0.0],
            "score_curr_idx": 0,
            "loss_curr_idx": 0
        }

        if self.state_dict is not None:
            summary_train = {
                'epoch': self.state_dict['epoch'],
                'step': self.state_dict['step'],
                'total_step': len(self.train_loader)
            }
            best_dict['score_dev_best'] = self.state_dict['score_dev_best']
            best_dict['loss_dev_best'] = self.state_dict['loss_dev_best']
            epoch_start = self.state_dict['epoch']

        for epoch in range(epoch_start, self.hparams.epochs):
            lr = self.create_scheduler(start_epoch=summary_train['epoch'])
            for param_group in self.optimizer.param_groups:
                param_group['lr'] = lr

            logging.info('Learning rate in epoch {}: {}'.format(
                epoch + 1, self.optimizer.param_groups[0]['lr']))
            print('Learning rate in epoch {}: {}'.format(
                epoch + 1, self.optimizer.param_groups[0]['lr']))

            summary_train, best_dict = self.training_step(
                summary_train, summary_dev, best_dict)

            self.validation_end(summary_dev, summary_train, best_dict)

            torch.save(
                {
                    'epoch': summary_train['epoch'],
                    'step': summary_train['step'],
                    'score_dev_best': best_dict['score_dev_best'],
                    'loss_dev_best': best_dict['loss_dev_best'],
                    'state_dict': self.model.state_dict()
                },
                os.path.join(self.hparams.save_path,
                             '{}_model.pth'.format(summary_train['epoch'] -
                                                   1)))

        logging.info('Training finished, model saved')
        print('Training finished, model saved')

    # def training_step(self, batch, batch_nb):
    def training_step(self, summary_train, summary_dev, best_dict):
        """Summary
        Extract the batch of datapoints and return the predicted logits
        Args:
            summary_train:
            summary_dev:
            best_dict:
        Returns:
            TYPE: Description
        """
        losses = AverageMeter()
        torch.set_grad_enabled(True)
        self.model.train()
        time_now = time.time()

        for i, (inputs, target, _) in enumerate(self.train_loader):
            if isinstance(inputs, tuple):
                inputs = tuple([
                    e.to(self.device) if type(e) == torch.Tensor else e
                    for e in inputs
                ])
            else:
                inputs = inputs.to(self.device)
            target = target.to(self.device)
            self.optimizer.zero_grad()

            if self.cfg.no_jsd:
                if self.cfg.n_crops:
                    bs, n_crops, c, h, w = inputs.size()
                    inputs = inputs.view(-1, c, h, w)

                    if len(self.hparams.mixtype) > 0:
                        if self.hparams.multi_cls:
                            target = target.view(target.size()[0], -1)
                            inputs, targets_a, targets_b, lam = self.mix_data(
                                inputs,
                                target.repeat(1, n_crops).view(-1),
                                self.device, self.hparams.alpha)
                        else:
                            inputs, targets_a, targets_b, lam = self.mix_data(
                                inputs,
                                target.repeat(1, n_crops).view(
                                    -1, len(self.num_tasks)), self.device,
                                self.hparams.alpha)

                    logits = self.forward(inputs)
                    if len(self.hparams.mixtype) > 0:
                        loss_func = self.mixup_criterion(
                            targets_a, targets_b, lam)
                        loss = loss_func(self.criterion, logits)
                    else:
                        if self.hparams.multi_cls:
                            target = target.view(target.size()[0], -1)
                            loss = self.criterion(
                                logits,
                                target.repeat(1, n_crops).view(-1))
                        else:
                            loss = self.criterion(
                                logits,
                                target.repeat(1, n_crops).view(
                                    -1, len(self.num_tasks)))
                else:
                    if len(self.hparams.mixtype) > 0:
                        inputs, targets_a, targets_b, lam = self.mix_data(
                            inputs, target, self.device, self.hparams.alpha)

                    logits = self.forward(inputs)
                    if len(self.hparams.mixtype) > 0:
                        loss_func = self.mixup_criterion(
                            targets_a, targets_b, lam)
                        loss = loss_func(self.criterion, logits)
                    else:
                        loss = self.criterion(logits, target)
            else:
                images_all = torch.cat(inputs, 0)
                logits_all = self.forward(images_all)
                logits_clean, logits_aug1, logits_aug2 = torch.split(
                    logits_all, inputs[0].size(0))

                # Cross-entropy is only computed on clean images
                loss = F.cross_entropy(logits_clean, target)

                p_clean, p_aug1, p_aug2 = F.softmax(
                    logits_clean,
                    dim=1), F.softmax(logits_aug1,
                                      dim=1), F.softmax(logits_aug2, dim=1)

                # Clamp mixture distribution to avoid exploding KL divergence
                p_mixture = torch.clamp((p_clean + p_aug1 + p_aug2) / 3., 1e-7,
                                        1).log()
                loss += 12 * (
                    F.kl_div(p_mixture, p_clean, reduction='batchmean') +
                    F.kl_div(p_mixture, p_aug1, reduction='batchmean') +
                    F.kl_div(p_mixture, p_aug2, reduction='batchmean')) / 3.

            assert not np.isnan(
                loss.item()), 'Model diverged with losses = NaN'

            loss.backward()
            self.optimizer.step()
            summary_train['step'] += 1
            losses.update(loss.item(), target.size(0))

            if summary_train['step'] % self.hparams.log_every == 0:
                time_spent = time.time() - time_now
                time_now = time.time()
                logging.info('Train, '
                             'Epoch : {}, '
                             'Step : {}/{}, '
                             'Loss: {loss.val:.4f} ({loss.avg:.4f}), '
                             'Run Time : {runtime:.2f} sec'.format(
                                 summary_train['epoch'] + 1,
                                 summary_train['step'],
                                 summary_train['total_step'],
                                 loss=losses,
                                 runtime=time_spent))
                print('Train, '
                      'Epoch : {}, '
                      'Step : {}/{}, '
                      'Loss: {loss.val:.4f} ({loss.avg:.4f}), '
                      'Run Time : {runtime:.2f} sec'.format(
                          summary_train['epoch'] + 1,
                          summary_train['step'],
                          summary_train['total_step'],
                          loss=losses,
                          runtime=time_spent))

            if summary_train['step'] % self.hparams.test_every == 0:
                self.validation_end(summary_dev, summary_train, best_dict)

            self.model.train()
            torch.set_grad_enabled(True)

        summary_train['epoch'] += 1
        return summary_train, best_dict

    def validation_step(self, summary_dev):
        """Summary
        Extract the batch of datapoints and return the predicted logits in validation step
        Args:
            summary_dev (TYPE): Description

        Returns:
            TYPE: Description
        """
        losses = AverageMeter()
        torch.set_grad_enabled(False)
        self.model.eval()

        output_ = np.array([])
        target_ = np.array([])

        with torch.no_grad():
            for i, (inputs, target, _) in enumerate(self.valid_loader):
                target = target.to(self.device)
                if isinstance(inputs, tuple):
                    inputs = tuple([
                        e.to(self.device) if type(e) == torch.Tensor else e
                        for e in inputs
                    ])
                else:
                    inputs = inputs.to(self.device)

                logits = self.forward(inputs)
                loss = self.criterion(logits, target)
                losses.update(loss.item(), target.size(0))

                if self.hparams.multi_cls:
                    output = F.softmax(logits)
                    _, output = torch.max(output, 1)
                else:
                    output = torch.sigmoid(logits)

                target = target.detach().to('cpu').numpy()
                target_ = np.concatenate(
                    (target_, target), axis=0) if len(target_) > 0 else target
                y_pred = output.detach().to('cpu').numpy()
                output_ = np.concatenate(
                    (output_, y_pred), axis=0) if len(output_) > 0 else y_pred

        summary_dev['loss'] = losses.avg
        return summary_dev, output_, target_

    def validation_end(self, summary_dev, summary_train, best_dict):
        """Summary
        After the validation end, calculate the metrics
        Args:
            summary_dev (TYPE): Description
            summary_train (TYPE): Description
            best_dict (TYPE): Description

        Returns:
            TYPE: Description
        """
        time_now = time.time()
        summary_dev, output_, target_ = self.validation_step(summary_dev)
        time_spent = time.time() - time_now

        if not self.hparams.auto_threshold:
            overall_pre, overall_rec, overall_fscore = get_metrics(
                copy.deepcopy(output_), target_, self.cfg.beta,
                self.cfg.threshold, self.cfg.metric_type)
        else:
            overall_pre, overall_rec, overall_fscore = self.find_best_fixed_threshold(
                output_, target_)

        resp = dict()
        if not self.hparams.multi_cls:
            for t in range(len(self.num_tasks)):
                y_pred = np.transpose(output_)[t]
                precision, recall, f_score = get_metrics(
                    copy.deepcopy(y_pred),
                    np.transpose(target_)[t], self.cfg.beta,
                    self.cfg.threshold, 'binary')

                resp['precision_{}'.format(
                    self.labels[self.num_tasks[t]])] = precision
                resp['recall_{}'.format(
                    self.labels[self.num_tasks[t]])] = recall
                resp['f_score_{}'.format(
                    self.labels[self.num_tasks[t]])] = f_score

        resp['overall_precision'] = overall_pre
        resp['overall_recall'] = overall_rec
        resp['overall_f_score'] = overall_fscore

        logging.info(
            'Dev, Step : {}/{}, Loss : {}, Fscore : {:.3f}, Precision : {:.3f}, '
            'Recall : {:.3f}, Run Time : {:.2f} sec'.format(
                summary_train['step'], summary_train['total_step'],
                summary_dev['loss'], resp['overall_f_score'],
                resp['overall_precision'], resp['overall_recall'], time_spent))
        print(
            'Dev, Step : {}/{}, Loss : {}, Fscore : {:.3f}, Precision : {:.3f}, '
            'Recall : {:.3f}, Run Time : {:.2f} sec'.format(
                summary_train['step'], summary_train['total_step'],
                summary_dev['loss'], resp['overall_f_score'],
                resp['overall_precision'], resp['overall_recall'], time_spent))

        save_best = False
        mean_score = resp['overall_f_score']
        if mean_score > min(best_dict['score_top_k']):
            self.update_top_k(mean_score, best_dict, 'score')
            if self.hparams.metric == 'score':
                save_best = True

        mean_loss = summary_dev['loss']
        if mean_loss < max(best_dict['loss_top_k']):
            self.update_top_k(mean_loss, best_dict, 'loss')
            if self.hparams.metric == 'loss':
                save_best = True

        if save_best:
            torch.save(
                {
                    'epoch': summary_train['epoch'],
                    'step': summary_train['step'],
                    'score_dev_best': best_dict['score_dev_best'],
                    'loss_dev_best': best_dict['loss_dev_best'],
                    'state_dict': self.model.state_dict()
                },
                os.path.join(self.hparams.save_path,
                             'best{}.pth'.format(best_dict['score_curr_idx'])))

            logging.info(
                'Best {}, Step : {}/{}, Loss : {}, Score : {:.3f}'.format(
                    best_dict['score_curr_idx'], summary_train['step'],
                    summary_train['total_step'], summary_dev['loss'],
                    best_dict['score_dev_best']))

            print('Best {}, Step : {}/{}, Loss : {}, Score : {:.3f}'.format(
                best_dict['score_curr_idx'], summary_train['step'],
                summary_train['total_step'], summary_dev['loss'],
                best_dict['score_dev_best']))

    def find_best_fixed_threshold(self, output_, target_):
        score = list()
        thrs = np.arange(0, 1.0, 0.01)
        pre_rec = list()
        for thr in tqdm.tqdm(thrs):
            pre, rec, fscore = get_metrics(copy.deepcopy(output_),
                                           copy.deepcopy(target_),
                                           self.cfg.beta, thr,
                                           self.cfg.metric_type)
            score.append(fscore)
            pre_rec.append([pre, rec])

        score = np.array(score)
        pm = score.argmax()
        best_thr, best_score = thrs[pm], score[pm].item()
        best_pre, best_rec = pre_rec[pm]
        print('thr={} F2={} prec{} rec{}'.format(best_thr, best_score,
                                                 best_pre, best_rec))
        return best_pre, best_rec, best_score

    def test_step(self):
        """Summary
        Extract the batch of datapoints and return the predicted logits in test step
        Args:
            batch (TYPE): Description
            batch_nb (TYPE): Description

        Returns:
            TYPE: Description
        """
        torch.set_grad_enabled(False)
        self.model.eval()

        output_ = np.array([])
        target_ = np.array([])

        with torch.no_grad():
            for i, batch in enumerate(self.test_loader):
                if self.hparams.infer == 'valid':
                    # Evaluate
                    inputs, target, names = batch
                    target = target.to(self.device)
                else:
                    # Test
                    inputs, names = batch

                if isinstance(inputs, tuple):
                    inputs = tuple([
                        e.to(self.device) if type(e) == torch.Tensor else e
                        for e in inputs
                    ])
                else:
                    inputs = inputs.to(self.device)

                self.names.extend(names)

                if self.cfg.n_crops:
                    bs, n_crops, c, h, w = inputs.size()
                    inputs = inputs.view(-1, c, h, w)

                logits = self.forward(inputs)

                if self.cfg.n_crops:
                    logits = logits.view(bs, n_crops, -1).mean(1)

                if self.hparams.multi_cls:
                    output = F.softmax(logits)
                    output = output[:, 1]
                else:
                    output = torch.sigmoid(logits)

                if self.hparams.infer == 'valid':
                    target = target.detach().to('cpu').numpy()
                    target_ = np.concatenate((target_, target), axis=0) if len(target_) > 0 else \
                        target
                y_pred = output.detach().to('cpu').numpy()
                output_ = np.concatenate(
                    (output_, y_pred), axis=0) if len(output_) > 0 else y_pred

        if self.hparams.infer == 'valid':
            return output_, target_
        else:
            return output_

    def test(self):
        """Summary
        After the test end, calculate the metrics
        Args:

        Returns:
            TYPE: Description
        """
        # inference dataset
        if self.hparams.infer == 'valid':
            output_, target_ = self.test_step()
        else:
            output_ = self.test_step()

        resp = dict()
        to_csv = {'Images': self.names}

        for t in range(len(self.num_tasks)):
            if self.hparams.multi_cls:
                y_pred = np.reshape(output_, output_.shape[0])
            else:
                y_pred = np.transpose(output_)[t]
            to_csv[self.labels[self.num_tasks[t]]] = y_pred

        # Only save scores to json file when in valid mode
        if self.hparams.infer == 'valid':
            overall_pre, overall_rec, overall_fscore = get_metrics(
                copy.deepcopy(output_), copy.deepcopy(target_), self.cfg.beta,
                self.cfg.threshold, self.cfg.metric_type)

            resp['overall_pre'] = overall_pre
            resp['overall_rec'] = overall_rec
            resp['overall_f_score'] = overall_fscore

            with open(
                    os.path.join(os.path.dirname(self.hparams.load),
                                 'scores_{}.csv'.format(uuid.uuid4())),
                    'w') as f:
                json.dump(resp, f)

        # Save predictions to csv file for computing metrics in off-line mode
        path_df = DataFrame(to_csv, columns=to_csv.keys())
        path_df.to_csv(os.path.join(os.path.dirname(self.hparams.load),
                                    'predictions_{}.csv'.format(uuid.uuid4())),
                       index=False)
        return resp

    def configure_optimizers(self):
        """Summary
        Must be implemented
        Returns:
            TYPE: Description
        """
        optimizer = create_optimizer(self.cfg, self.model.parameters())

        if self.cfg.lr_scheduler == 'step':
            scheduler = optim.lr_scheduler.StepLR(optimizer,
                                                  step_size=self.cfg.step_size,
                                                  gamma=self.cfg.lr_factor)
        elif self.cfg.lr_scheduler == 'cosin':
            scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer,
                                                             T_max=200,
                                                             eta_min=1e-6)
        elif self.cfg.lr_scheduler == 'cosin_epoch':
            scheduler = optim.lr_scheduler.CosineAnnealingLR(
                optimizer, T_max=self.cfg.tmax, eta_min=self.cfg.eta_min)
        elif self.cfg.lr_scheduler == 'onecycle':
            max_lr = [g["lr"] for g in optimizer.param_groups]
            scheduler = optim.lr_scheduler.OneCycleLR(
                optimizer,
                max_lr=max_lr,
                epochs=self.hparams.epochs,
                steps_per_epoch=len(self.train_dataloader()))
            scheduler = {"scheduler": scheduler, "interval": "step"}
        else:
            raise ValueError(
                'Does not support {} learning rate scheduler'.format(
                    self.cfg.lr_scheduler))
        return optimizer, scheduler

    def train_dataloader(self):
        """Summary
        Return the train dataset, see dataflow/__init__.py
        Returns:
            TYPE: Description
        """
        ds_train = init_dataset(self.hparams.data_name,
                                cfg=self.cfg,
                                data_path=self.hparams.data_path,
                                mode='train')
        return DataLoader(dataset=ds_train,
                          batch_size=self.cfg.train_batch_size,
                          shuffle=True,
                          num_workers=self.hparams.num_workers,
                          pin_memory=True)

    def val_dataloader(self):
        """Summary
        Return the val dataset, see dataflow/__init__.py
        Returns:
            TYPE: Description
        """
        ds_val = init_dataset(self.hparams.data_name,
                              cfg=self.cfg,
                              data_path=self.hparams.data_path,
                              mode='valid')
        return DataLoader(dataset=ds_val,
                          batch_size=self.cfg.dev_batch_size,
                          shuffle=False,
                          num_workers=self.hparams.num_workers,
                          pin_memory=True)

    def test_dataloader(self):
        """Summary
        Return the test dataset, see dataflow/__init__.py
        Returns:
            TYPE: Description
        """
        ds_test = init_dataset(self.hparams.data_name,
                               cfg=self.cfg,
                               data_path=self.hparams.data_path,
                               mode=self.hparams.infer)
        return DataLoader(dataset=ds_test,
                          batch_size=self.cfg.dev_batch_size,
                          shuffle=False,
                          num_workers=self.hparams.num_workers,
                          pin_memory=True)

    def mix_data(self, x, y, device, alpha=1.0):
        """
        Re-constructed input images and labels based on one of two regularization methods such as Mixup and Cutmix.
        :param x: input images
        :param y: labels
        :param device: cpu or gpu device
        :param alpha: parameter for beta distribution
        :return: mixed inputs, pairs of targets, and lambda
        """
        if alpha > 0.:
            lam = np.random.beta(alpha, alpha)
        else:
            lam = 1.
        batch_size = x.size()[0]
        index = torch.randperm(batch_size).to(device)
        y_a, y_b = y, y[index]

        if self.hparams.mixtype == 'mixup':
            mixed_x = lam * x + (1 - lam) * x[index, :]
        elif self.hparams.mixtype == 'cutmix':
            bbx1, bby1, bbx2, bby2 = self.rand_bbox(x.size(), lam)
            x[:, :, bbx1:bbx2, bby1:bby2] = x[index, :, bbx1:bbx2, bby1:bby2]
            mixed_x = x
            lam = 1 - ((bbx2 - bbx1) * (bby2 - bby1) /
                       (x.size()[-1] * x.size()[-2]))
        else:
            raise ValueError('Mixtype {} does not exists'.format(
                self.hparams.mixtype))

        return mixed_x, y_a, y_b, lam

    def create_scheduler(self, start_epoch):
        """
            Learning rate schedule with respect to epoch
            lr: float, initial learning rate
            lr_factor: float, decreasing factor every epoch_lr
            epoch_now: int, the current epoch
            lr_epochs: list of int, decreasing every epoch in lr_epochs
            return: lr, float, scheduled learning rate.
            """
        count = 0
        for epoch in self.hparams.lr_epochs.split(','):
            if start_epoch >= int(epoch):
                count += 1
                continue

            break

        return self.cfg.lr * np.power(self.cfg.lr_factor, count)

    @staticmethod
    def mixup_criterion(y_a, y_b, lam):
        """
        Re-constructured loss function based on regularization technique
        Args:
            y_a: original labels
            y_b: shuffled labels after random permutation
            lam: generated point in beta distribution
        Returns:
            Combined loss function
        """
        return lambda criterion, pred: lam * criterion(pred, y_a) + (
            1 - lam) * criterion(pred, y_b)

    @staticmethod
    def rand_bbox(size, lam):
        """
        Generate random bounding box for specified cutting rate
        Args:
            size: image size including weight and height
            lam: generated point in beta distribution
        Returns:
            Coordinates of top-left and right-bottom vertices of bounding box
        """
        W = size[2]
        H = size[3]
        cut_rat = np.sqrt(1. - lam)
        cut_w = np.int(W * cut_rat)
        cut_h = np.int(H * cut_rat)

        # uniform
        cx = np.random.randint(W)
        cy = np.random.randint(H)

        bbx1 = np.clip(cx - cut_w // 2, 0, W)
        bby1 = np.clip(cy - cut_h // 2, 0, H)
        bbx2 = np.clip(cx + cut_w // 2, 0, W)
        bby2 = np.clip(cy + cut_h // 2, 0, H)

        return bbx1, bby1, bbx2, bby2

    def update_top_k(self, mean, best_dict, metric):
        metric_dev_best = '{}_dev_best'.format(metric)
        metric_top_k = '{}_top_k'.format(metric)
        metric_curr_idx = '{}_curr_idx'.format(metric)

        if metric == 'loss':
            if mean < best_dict[metric_dev_best]:
                best_dict[metric_dev_best] = mean
        else:
            if mean > best_dict[metric_dev_best]:
                best_dict[metric_dev_best] = mean

        if len(best_dict[metric_top_k]) >= self.hparams.save_top_k:
            if metric == 'loss':
                min_idx = best_dict[metric_top_k].index(
                    max(best_dict[metric_top_k]))
            else:
                min_idx = best_dict[metric_top_k].index(
                    min(best_dict[metric_top_k]))
            curr_idx = min_idx
            best_dict[metric_top_k][min_idx] = mean
        else:
            curr_idx = len(best_dict[metric_top_k])
            best_dict[metric_top_k].append(mean)

        best_dict[metric_curr_idx] = curr_idx
コード例 #16
0
def train_sentiment(opts):
    
    device = torch.device("cuda" if use_cuda else "cpu")

    glove_loader = GloveLoader(os.path.join(opts.data_dir, 'glove', opts.glove_emb_file))
    train_loader = DataLoader(RottenTomatoesReviewDataset(opts.data_dir, 'train', glove_loader, opts.maxlen), \
        batch_size=opts.bsize, shuffle=True, num_workers=opts.nworkers)
    valid_loader = DataLoader(RottenTomatoesReviewDataset(opts.data_dir, 'val', glove_loader, opts.maxlen), \
        batch_size=opts.bsize, shuffle=False, num_workers=opts.nworkers)
    model = Classifier(opts.hidden_size, opts.dropout_p, glove_loader, opts.enc_arch)

    if opts.optim == 'adam':
        optimizer = torch.optim.Adam(model.parameters(), lr=opts.lr, weight_decay=opts.wd)
    else:
        raise NotImplementedError("Unknown optim type")

    criterion = nn.CrossEntropyLoss()

    start_n_iter = 0
    # for choosing the best model
    best_val_acc = 0.0

    model_path = os.path.join(opts.save_path, 'model_latest.net')
    if opts.resume and os.path.exists(model_path):
        # restoring training from save_state
        print ('====> Resuming training from previous checkpoint')
        save_state = torch.load(model_path, map_location='cpu')
        model.load_state_dict(save_state['state_dict'])
        start_n_iter = save_state['n_iter']
        best_val_acc = save_state['best_val_acc']
        opts = save_state['opts']
        opts.start_epoch = save_state['epoch'] + 1

    model = model.to(device)

    # for logging
    logger = TensorboardXLogger(opts.start_epoch, opts.log_iter, opts.log_dir)
    logger.set(['acc', 'loss'])
    logger.n_iter = start_n_iter

    for epoch in range(opts.start_epoch, opts.epochs):
        model.train()
        logger.step()

        for batch_idx, data in enumerate(train_loader):
            acc, loss = run_iter(opts, data, model, criterion, device)

            # optimizer step
            optimizer.zero_grad()
            loss.backward()
            nn.utils.clip_grad_norm_(model.parameters(), opts.max_norm)
            optimizer.step()

            logger.update(acc, loss)

        val_loss, val_acc, time_taken = evaluate(opts, model, valid_loader, criterion, device)
        # log the validation losses
        logger.log_valid(time_taken, val_acc, val_loss)
        print ('')

        # Save the model to disk
        if val_acc >= best_val_acc:
            best_val_acc = val_acc
            save_state = {
                'epoch': epoch,
                'state_dict': model.state_dict(),
                'optimizer': optimizer.state_dict(),
                'n_iter': logger.n_iter,
                'opts': opts,
                'val_acc': val_acc,
                'best_val_acc': best_val_acc
            }
            model_path = os.path.join(opts.save_path, 'model_best.net')
            torch.save(save_state, model_path)

        save_state = {
            'epoch': epoch,
            'state_dict': model.state_dict(),
            'optimizer': optimizer.state_dict(),
            'n_iter': logger.n_iter,
            'opts': opts,
            'val_acc': val_acc,
            'best_val_acc': best_val_acc
        }
        model_path = os.path.join(opts.save_path, 'model_latest.net')
        torch.save(save_state, model_path)
コード例 #17
0
ファイル: solver.py プロジェクト: BorisAnimal/TS-UDA
class Solver:
    def __init__(self):
        self.train_lr = 1e-4
        self.num_classes = 9
        self.clf_target = Classifier().cuda()
        self.clf2 = Classifier().cuda()
        self.clf1 = Classifier().cuda()
        self.encoder = Encoder().cuda()
        self.pretrain_lr = 1e-4
        self.weights_coef = 1e-3

    def to_var(self, x):
        """Converts numpy to variable."""
        if torch.cuda.is_available():
            x = x.cuda()
        return Variable(x, requires_grad=False).float()

    def loss(self, predictions, y_true, weights_coef=None):
        """
        :param predictions: list of prediction tensors
        """
        assert len(predictions[0].shape) == 2 and len(
            y_true.shape) == 1, (predictions.shape, y_true.shape)
        losses = [F.cross_entropy(y_hat, y_true) for y_hat in predictions]
        loss = sum(losses)

        # """
        # We add the term |W1^T W2| to the cost function, where W1, W2 denote fully connected layers’
        # weights of F1 and F2 which are first applied to the feature F(xi)
        # """
        if weights_coef:
            lw = torch.matmul(solver.clf1.fc1.weight,
                              solver.clf2.fc1.weight.T).abs().sum().mean()
            loss += weights_coef * lw

        return loss

    def pretrain(self, source_loader, target_val_loader, pretrain_epochs=1):
        source_iter = iter(source_loader)
        source_per_epoch = len(source_iter)
        print("source_per_epoch:", source_per_epoch)

        # pretrain
        log_pre = 250
        lr = self.pretrain_lr
        pretrain_iters = source_per_epoch * pretrain_epochs
        params = reduce(
            lambda a, b: a + b,
            map(lambda i: list(i.parameters()),
                [self.encoder, self.clf1, self.clf2, self.clf_target]))
        pretrain_optimizer = optim.Adam(params, lr)
        accuracies = []

        for step in range(pretrain_iters + 1):
            # ============ Initialization ============#
            # refresh
            if (step + 1) % source_per_epoch == 0:
                source_iter = iter(source_loader)
            # load the data
            source, s_labels = next(source_iter)
            source, s_labels = self.to_var(source), self.to_var(
                s_labels).long().squeeze()

            # ============ Training ============ #
            pretrain_optimizer.zero_grad()
            # forward
            features = self.encoder(source)
            y1_hat = self.clf1(features)
            y2_hat = self.clf2(features)
            y_target_hat = self.clf_target(features)

            # loss
            loss_source_class = self.loss([y1_hat, y2_hat, y_target_hat],
                                          s_labels,
                                          weights_coef=self.weights_coef)

            # one step
            loss_source_class.backward()
            pretrain_optimizer.step()
            pretrain_optimizer.zero_grad()
            # TODO: make this each step and on log_pre step just average and print previous results
            # ============ Validation ============ #
            if (step + 1) % log_pre == 0:
                with torch.no_grad():
                    source_val_features = self.encoder(source)
                    c_source1 = self.clf1(source_val_features)
                    c_source2 = self.clf2(source_val_features)
                    c_target = self.clf_target(source_val_features)
                    print("Train data (source) scores:")
                    print("Step %d | Source clf1=%.2f, clf2=%.2f | Source data clf_t=%.2f" \
                          % (step,
                             accuracy(c_source1, s_labels),
                             accuracy(c_source2, s_labels),
                             accuracy(c_target, s_labels))
                          )
                    acc = self.eval(target_val_loader, self.clf_target)
                    print("Val target data acc=%.2f" % acc)
                    print()

    def pseudo_labeling(self, loader, pool_size=4000, threshold=0.9):
        """
        When C1, C2 denote the class which has the maximum predicted probability for
        y1, y2, we assign a pseudo-label to xk if the following two
        conditions are satisfied. First, we require C1 = C2 to give
        pseudo-labels, which means two different classifiers agree
        with the prediction. The second requirement is that the
        maximizing probability of y1 or y2 exceeds the threshold
        parameter, which we set as 0.9 or 0.95 in the experiment.

        :return:
        """
        pool = []  # x, y_pseudo
        for x, _ in loader:
            batch_size = x.shape[0]
            x = self.to_var(x)
            ys1 = F.softmax(self.clf1(self.encoder(x)))
            ys2 = F.softmax(self.clf2(self.encoder(x)))
            # _, pseudo_labels = torch.max(pseudo_labels, 1)
            for i in range(batch_size):
                y1 = ys1[i]
                y2 = ys2[i]
                val1, idx1 = torch.max(y1, 0)
                val2, idx2 = torch.max(y2, 0)
                if idx1 == idx2 and max(val1, val2) >= threshold:
                    pool.append((x[i].cpu(), idx1.cpu().item()))
                if len(pool) >= pool_size:
                    return pool
        return pool

    def train(self, source_loader, source_val_loader, target_loader,
              target_val_loader, epochs):
        """
        :param epochs: target epochs the training will be done
        """

        # pretrain
        log_pre = 30
        lr = self.train_lr

        params1 = reduce(
            lambda a, b: a + b,
            map(lambda i: list(i.parameters()),
                [self.encoder, self.clf1, self.clf2]))
        params2 = list(self.encoder.parameters()) + list(
            self.clf_target.parameters())
        optimizer1 = optim.Adam(params1, lr)
        optimizer2 = optim.Adam(params2, lr)

        # ad-hoc
        acs1 = []
        acs2 = []
        acs3 = []

        for epoch in range(epochs):
            source_iter = iter(source_loader)
            target_iter = iter(target_loader)

            source_per_epoch = len(source_iter)
            target_per_epoch = len(target_iter)
            if epoch == 0:
                print("source_per_epoch, target_per_epoch:", source_per_epoch,
                      target_per_epoch)
            if epoch == 3:
                for param_group in optimizer1.param_groups:
                    param_group['lr'] = lr * 0.1

                for param_group in optimizer2.param_groups:
                    param_group['lr'] = lr * 0.1
            if epoch == 6:
                for param_group in optimizer1.param_groups:
                    param_group['lr'] = lr * 0.01

                for param_group in optimizer2.param_groups:
                    param_group['lr'] = lr * 0.01

            # ============ Pseudo-labeling  ============ #
            # Fill candidates
            target_candidates = self.pseudo_labeling(target_loader,
                                                     pool_size=4000 * epoch)
            print("Target candidates len:", len(target_candidates))
            if len(target_candidates) <= 1:
                target_candidates = self.pseudo_labeling(target_loader,
                                                         threshold=0.0)
                print("Target candidates len:", len(target_candidates))
            target_candidates_loader = self.wrap_to_loader(
                target_candidates, batch_size=target_loader.batch_size)
            for step, (target,
                       t_labels) in enumerate(target_candidates_loader):
                if (step + 1) % source_per_epoch == 0:
                    source_iter = iter(source_loader)

                source, s_labels = next(source_iter)
                target, t_labels = self.to_var(target), self.to_var(
                    t_labels).long().squeeze()
                source, s_labels = self.to_var(source), self.to_var(
                    s_labels).long().squeeze()

                # ============ Train F, F1, F2  ============ #
                optimizer1.zero_grad()
                # Source data
                # forward
                features = self.encoder(source)
                y1s_hat = self.clf1(features)
                y2s_hat = self.clf2(features)
                # loss
                loss_source_class = self.loss([y1s_hat, y2s_hat],
                                              s_labels,
                                              weights_coef=self.weights_coef)

                # Target data
                # forward
                features = self.encoder(target)
                y1t_hat = self.clf1(features)
                y2t_hat = self.clf2(features)
                # loss
                loss_target_class = self.loss([y1t_hat, y2t_hat],
                                              t_labels,
                                              weights_coef=self.weights_coef)
                # one step
                (loss_source_class + loss_target_class).backward()
                optimizer1.step()
                optimizer1.zero_grad()

                # ============ Train F, Ft  ============ #
                optimizer2.zero_grad()
                # Target data
                # forward
                y_target_hat = self.clf_target(self.encoder(target))
                # loss
                loss_target_class = self.loss([y_target_hat], t_labels)
                # one step
                loss_target_class.backward()
                optimizer2.step()
                optimizer2.zero_grad()

                # ============ Validation ============ #
                acs1.append(accuracy(y1s_hat, s_labels).item())
                acs2.append(accuracy(y2s_hat, s_labels).item())
                acs3.append(accuracy(y_target_hat, t_labels).item())

                if (step + 1) % log_pre == 0:
                    acc = self.eval(target_val_loader, self.clf_target)
                    print("Step %d | Val data target classifier acc=%.2f" %
                          (step, acc))
                    print(
                        "          Train accuracy clf1=%.2f, clf2=%.2f, clf_t=%.2f"
                        % (np.mean(acs1), np.mean(acs2), np.mean(acs3)))
                    acs1 = []
                    acs2 = []
                    acs3 = []

                    # acc1 = self.eval(source_val_loader, self.clf1)
                    # print("        | Val data source classifier1 acc=%.2f" % acc1)
                    # acc2 = self.eval(source_val_loader, self.clf2)
                    # print("        | Val data source classifier2 acc=%.2f" % acc2)
                    print()

    def save_models(self):
        torch.save(self.encoder, 'encoder.pth')
        torch.save(self.clf1, 'clf1.pth')
        torch.save(self.clf2, 'clf2.pth')
        torch.save(self.clf_target, 'clf_target.pth')

    def load_models(self):
        self.encoder = torch.load('encoder.pth')
        self.clf1 = torch.load('clf1.pth')
        self.clf2 = torch.load('clf2.pth')
        self.clf_target = torch.load('clf_target.pth')

    def eval(self, loader, classifier):
        """
        Evaluate encoder + passed classifier
        """
        # for x, y_true in loader:
        #     y_hat = classifier(self.encoder)
        #     acc = accuracy(y_hat, y_true)

        class_correct = [0] * self.num_classes
        class_total = [0.] * self.num_classes
        classes = shl_processing.coarse_label_mapping
        self.encoder.eval()
        classifier.eval()

        for x, y_true in loader:
            # forward pass: compute predicted outputs by passing inputs to the model
            x, y_true = self.to_var(x), self.to_var(y_true).long().squeeze()

            y_hat = classifier(self.encoder(x))
            _, pred = torch.max(y_hat, 1)
            correct = np.squeeze(pred.eq(y_true.data.view_as(pred)))
            # calculate test accuracy for each object class
            for i in range(len(y_true.data)):
                label = y_true.data[i]
                class_correct[label] += correct[i].item()
                class_total[label] += 1

        for i in range(self.num_classes):
            if class_total[i] > 0:
                print('\tTest Accuracy of %10s: %2d%% (%2d/%2d)' %
                      (classes[i], 100 * class_correct[i] / class_total[i],
                       np.sum(class_correct[i]), np.sum(class_total[i])))
            else:
                print('\tTest Accuracy of %10s: N/A (no training examples)' %
                      (classes[i]))

        self.encoder.train()
        classifier.train()

        return 100. * np.sum(class_correct) / np.sum(class_total)

    def wrap_to_loader(self, target_candidates, batch_size):
        """
        :param target_candidates: [(x,y_pseudo)]
        :return:
        """
        assert len(target_candidates) > 0
        tmp = target_candidates  # CondomDataset(target_candidates)
        return torch.utils.data.DataLoader(dataset=tmp,
                                           batch_size=batch_size,
                                           shuffle=True,
                                           num_workers=0)

    def confusion_matrix(self, loader, classifier):

        labels = []
        preds = []
        for x, y_true in loader:
            labels += list(y_true.cpu().detach().numpy().flatten())
            x, y_true = self.to_var(x), self.to_var(y_true).long().squeeze()

            y_hat = classifier(self.encoder(x))
            _, pred = torch.max(y_hat, 1)

            preds += list(pred.cpu().detach().numpy().flatten())

        cm = confusion_matrix(labels, preds)

        df_cm = pd.DataFrame(cm,
                             index=coarse_label_mapping,
                             columns=coarse_label_mapping,
                             dtype=np.int)
        plt.figure(figsize=(10, 7))
        sn.heatmap(df_cm, annot=True)

        plt.show()
コード例 #18
0
    trainset = torchvision.datasets.ImageFolder(root=path, transform=transform)

    trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=4)

    classes = set(values["classes"])

    net = Classifier()
    net.to(device)
    if use_cuda:
        net.cuda()

    # Set up loss function and optimiser

    criterion = torch.nn.CrossEntropyLoss()
    optimizer = torch.optim.SGD(net.parameters(), lr=0.0001, momentum=0.9)

    epoch = 0

    running_loss = 1.0

    # Simple training for 500 epochs

    for epoch in range(500):
        
        running_loss = 0.0
        for i, data in enumerate(trainloader, 0):
            inputs = data[0].to(device)
            labels = data[1].to(device)

            optimizer.zero_grad()
コード例 #19
0
                              pin_memory=True)
    args.num_class = trainset.num_class
    valset = Dataset('val', args)
    val_sampler = CategoriesSampler(valset.label, 200, valset.num_class,
                                    1 + args.query)  # test on 16-way 1-shot
    val_loader = DataLoader(dataset=valset,
                            batch_sampler=val_sampler,
                            num_workers=8,
                            pin_memory=True)
    args.way = valset.num_class
    args.shot = 1

    # construct trainer_single
    model = Classifier(args)
    if 'Conv' in args.backbone_class:
        optimizer = torch.optim.Adam(model.parameters(),
                                     lr=args.lr,
                                     weight_decay=0.0005)
    elif 'Res' in args.backbone_class:
        optimizer = torch.optim.SGD(model.parameters(),
                                    lr=args.lr,
                                    momentum=0.9,
                                    nesterov=True,
                                    weight_decay=0.0005)
    else:
        raise ValueError('No Such Encoder')
    criterion = torch.nn.CrossEntropyLoss()

    if torch.cuda.is_available():
        torch.backends.cudnn.benchmark = True
        if args.ngpu > 1:
コード例 #20
0
    transforms.ToTensor(),
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
])

data = ImageFolder(root='simpsons_dataset', transform=composed)

batch_size = 128

train_loader = DataLoader(data,
                          batch_size=batch_size,
                          num_workers=2,
                          shuffle=True)

classifier = Classifier()

optimizer = optim.Adam(classifier.parameters(), lr=.001)
criterion = CrossEntropyLoss()
epochs = 1

n_data = len(data)

for i in range(5):
    total_loss = 0
    for j, data in enumerate(train_loader, 0):
        images, labels = data

        optimizer.zero_grad()

        outputs = classifier(images)

        loss = criterion(outputs, labels)
コード例 #21
0
def TrainSourceTargetModel_exp(options):
    #defining the models
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    options['device'] = device
    cEnc = ConvEncoder(latentDimension=options['latentD']).to(device)
    disc = Discriminator(latentDimension=options['latentD']).to(device)
    classify = Classifier(latentDimension=options['latentD']).to(device)

    # defining loss functions
    MSELoss = nn.MSELoss().to(device)  # mean squared error loss
    BCELoss = nn.BCELoss().to(device)  # binary cross-entropy
    NLLLoss = nn.NLLLoss().to(device)  # negative-log likelihood
    CELoss = nn.CrossEntropyLoss().to(device)  # cross entropy loss

    # loss log data
    lossData_a, lossData_b = [], []

    optimizer_classification = optim.Adam(itertools.chain(
        classify.parameters()),
                                          lr=options['lrA'])
    optimizer_encoder = optim.Adam(itertools.chain(cEnc.parameters()),
                                   lr=options['lrA'])
    optimizer_discriminator = optim.Adam(itertools.chain(disc.parameters()),
                                         lr=options['lrB'])

    sourceLogText, targetLogText = "", ""
    sourceTrainLoader = options['sourceTrainLoader']
    targetTrainLoader = options['targetTrainLoader']

    for epochIdx in range(options['epochs']):

        # defining the data loaders
        _ones = Variable(torch.FloatTensor(options['batchSize'], 1).fill_(1.0),
                         requires_grad=False).to(device)
        _zeros = Variable(torch.FloatTensor(options['batchSize'],
                                            1).fill_(0.0),
                          requires_grad=False).to(device)

        for (batchData,
             batchLabels), (targetBatchData,
                            targetBatchLabels) in zip(sourceTrainLoader,
                                                      targetTrainLoader):

            #SOURCE DATA

            # data setup
            _batchSize = batchData.shape[0]
            _targetBatchSize = targetBatchData.shape[0]
            #source
            batchData = batchData.to(device)
            batchLabels = batchLabels.to(device)
            #target
            targetBatchData = targetBatchData.to(device)
            targetBatchLabels = targetBatchLabels.to(device)

            #generate synthetic sample from the feature space
            latentSpaceSample_A, latentSpaceClasses_A = getSampleFromLatentSpace(
                [_batchSize, options['latentD']], options)
            latentSpaceSample_B, latentSpaceClasses_B = getSampleFromLatentSpace(
                [_batchSize, options['latentD']], options)

            # cEnc pass
            encodedDataBatch = cEnc(batchData)
            targetEncodedDataBatch = cEnc(targetBatchData)

            #classification pass
            classesPrediction = classify(encodedDataBatch)
            sampleClassesPrediction = classify(latentSpaceSample_A)

            #discriminator pass
            sourceDiscOutput = disc(encodedDataBatch)
            targetDiscOutput = disc(targetEncodedDataBatch)

            # optimzation step I -- classification
            optimizer_classification.zero_grad()
            #--- first loss function
            loss_a = CELoss(sampleClassesPrediction, latentSpaceClasses_A)
            loss_a.backward()
            optimizer_classification.step()

            #optimization step II -- encoder
            optimizer_encoder.zero_grad()
            loss_b = CELoss(classesPrediction, batchLabels)
            loss_b.backward()
            optimizer_encoder.step()

            # loss_c=BCELoss(targetDiscDataInput,_zeros[:_targetBatchSize])+\
            #        BCELoss(sampleDiscOutputB,_ones[:_batchSize])

            #
            # #discriminator pass
            # discDataInput=Variable(encodedDataBatch.view(_batchSize,options['latentD']).cpu().data,requires_grad=False).to(device)
            # discDataOutput=disc(discDataInput)
            # targetDiscDataInput=Variable(targetEncodedDataBatch.view(_targetBatchSize,options['latentD']).cpu().data,requires_grad=False).to(device)
            # targetDiscDataInput=disc(targetDiscDataInput)
            # sampleDiscOutputB=disc(latentSpaceSample_B)
            # # optimization step II
            # #---train the discriminator, 1/0 is real/fake data
            # optimizer_b.zero_grad()

            #---second loss function
            # loss_b=BCELoss(discDataOutput,_zeros[:_batchSize])+\
            #        BCELoss(targetDiscDataInput,_zeros[:_targetBatchSize])+\
            #        BCELoss(sampleDiscOutputB,_ones[:_batchSize])
            # loss_b.backward()
            # optimizer_b.step()
            # lossData_b.append(loss_b.data.item())

        ####
        #### End of an epoch
        ####

        sourceLogText += validateModel(epochIdx,
                                       options,
                                       models=[cEnc, classify, disc])
        targetLogText += validateModel(epochIdx,
                                       options,
                                       source=False,
                                       models=[cEnc, classify, disc])

        # end of an epoch - CHECK ACCURACY ON TEST SET

    outputs = {
        'lossA': lossData_a,
        'lossB': lossData_b,
        'encoder': cEnc,
        'disc': disc,
        'classifier': classify,
        'sourceLogText': sourceLogText,
        'targetLogText': targetLogText,
    }
    return outputs
コード例 #22
0
ファイル: vada_train.py プロジェクト: ozanciga/dirt-t
from vat import VAT, ConditionalEntropyLoss

# discriminator network
feature_discriminator = Discriminator(large=args.large).cuda()

# classifier network.
classifier = Classifier(large=args.large).cuda()

# loss functions
cent = ConditionalEntropyLoss().cuda()
xent = nn.CrossEntropyLoss(reduction='mean').cuda()
sigmoid_xent = nn.BCEWithLogitsLoss(reduction='mean').cuda()
vat_loss = VAT(classifier).cuda()

# optimizer.
optimizer_cls = torch.optim.Adam(classifier.parameters(),
                                 lr=args.lr,
                                 betas=(args.beta1, args.beta2))
optimizer_disc = torch.optim.Adam(feature_discriminator.parameters(),
                                  lr=args.lr,
                                  betas=(args.beta1, args.beta2))

# datasets.
iterator_train = GenerateIterator(args)
iterator_val = GenerateIterator_eval(args)

# loss params.
dw = 1e-2
cw = 1
sw = 1
tw = 1e-2
コード例 #23
0
            scores = model(x_var)
            loss = loss_fn(scores, y_var)
            if (t + 1) % print_every == 0:
                print('t = %d, loss = %.4f' % (t + 1, loss.data[0]))

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()


data = dataSets()
torch.cuda.synchronize()
loss_fn = nn.CrossEntropyLoss()
model = Classifier()
optimizer = optim.Adam(model.parameters(), lr=5e-4, weight_decay=1e-4)

for m in model.modules():
    if isinstance(m, nn.Conv2d):
        n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
        m.weight.data.normal_(0, math.sqrt(2. / n))
    elif isinstance(m, nn.BatchNorm2d):
        m.weight.data.fill_(1)
        m.bias.data.zero_()

train(model,
      data.cifar10_train_loader,
      loss_fn,
      optimizer,
      valset=data.cifar10_val_loader)
print("-----checking accuracy on test set-------")
コード例 #24
0
import torch
import torch.optim as optim
from torch import nn
from torch.utils import data
from torchvision import datasets, transforms
from models import Classifier

cla = Classifier().cuda()
opt = optim.Adam(cla.parameters(), lr=1e-3)

## Step 1: train the classifier
trainloader = data.DataLoader(
	datasets.MNIST('../data', download=True, train=True, transform=transforms.Compose([
		   transforms.ToTensor(),
	   ])), batch_size=100, shuffle=True)

testloader = data.DataLoader(
	datasets.MNIST('../data', download=True, train=False, transform=transforms.Compose([
		   transforms.ToTensor(),
	   ])), batch_size=100, shuffle=True)

def accuracy(): 
    total_correct = 0.0
    total = 0.0
    with torch.no_grad():
        for images, targets in testloader:
            out = cla(images.cuda())
            preds = out.argmax(1)
            total_correct += (preds.cpu()==targets).float().sum()
            total += preds.shape[0]
    return total_correct/total
コード例 #25
0
n_layers = 3
dim_feedforward = 128
lr = 0.01

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

autoencoder = Autoencoder()
autoencoder.load_state_dict(torch.load(AUTOENCODER))
autoencoder.to(device)
autoencoder.eval()

model = Classifier(n_vid_features, n_aud_features, n_head, n_layers,
                   dim_feedforward)
model = model.to(device)
criterion = nn.BCEWithLogitsLoss()
optimizer = optim.Adam(model.parameters(), lr=lr)

start_time = datetime.datetime.now()
print(f'start time: {str(start_time)}')
print(f'using device: {device}')

train_dataset = EncodedDeepfakeDataset(TRAIN_FOLDERS,
                                       autoencoder.encoder,
                                       n_frames=n_frames,
                                       n_audio_reads=576,
                                       device=device,
                                       cache_folder="encode_cache",
                                       n_videos=epoch_size)
dataloader = torch.utils.data.DataLoader(train_dataset,
                                         batch_size=batch_size,
                                         shuffle=True)
コード例 #26
0
ファイル: train_lambda.py プロジェクト: aritzzz/ATCS
class BaselineTrainer(pl.LightningModule):
    """Trainer for the baseline experiments which trains BERT + MLP."""

    def __init__(self, config):
        super().__init__()
        self.save_hyperparameters()
        self.model = Classifier(config)
        self.model.init_phi_normal(config['n_classes'])
        self.config = config
        self.loss_func = self.get_loss_func()

    def configure_optimizers(self):
        """Configures optimizer for pytorch lightning."""
        optimizer_dict = {
                    "sgd": optim.SGD,
                    "adam": optim.Adam
                }
        optimizer = optimizer_dict[self.config['optimizer']]
        self.optimizer = optimizer(self.model.parameters(), self.config['lr'])
        self.scheduler = get_cosine_schedule_with_warmup(self.optimizer, 
                                                        num_training_steps=config['n_steps'],
                                                        num_warmup_steps=int(0.10*config['n_steps']))
        return [self.optimizer], self.scheduler

    def get_loss_func(self):
        """Returns loss function specified in config."""
        loss_dict = {
                    "ce": nn.CrossEntropyLoss(),
                    "bce": nn.BCEWithLogitsLoss()
                }
        return loss_dict[self.config['loss']]

    def forward(self, batch):
        """Performs a forward pass on the batch."""
        logits = self.model(self._to_device(batch['input_ids']), 
                    token_type_ids=self._to_device(batch['token_type_ids']), 
                    attention_mask=self._to_device(batch['attention_mask']))
        return logits

    def _to_device(self, inp):
        if not torch.is_tensor(inp):
            inp = torch.tensor(inp)
        return inp.to(self.config['device'])

    def calc_accuracy(self, logits, labels):
        """Utility function to calculate the accuracy given logits and labels. """
        if logits.size(-1) > 1:
            predictions = torch.argmax(logits, dim=1)
        else:
            predictions = (nn.functional.sigmoid(logits) > 0.5).float()
        return (predictions == labels).float().mean().item()

    def training_step(self, batch, batch_idx):
        """Performs a single training step and logs metrics."""
        labels = self._to_device(batch['labels'])
        logits = self.forward(batch)
        loss = self.loss_func(logits, labels)
        accuracy = self.calc_accuracy(logits, labels)

        sch = self.scheduler
        sch.step()

        self.log('train_loss', loss)
        self.log('train_accuracy', accuracy, on_step=False, on_epoch=True)
        return loss

    def evaluation_step(self, batch):
        """Performs a single evaluation step."""
        labels = self._to_device(batch['labels'])
        logits = self.forward(batch)
        loss = self.loss_func(logits, labels)
        accuracy = self.calc_accuracy(logits, labels)

        return loss, accuracy

    def validation_step(self, batch, batch_idx):
        """Performs an evaluation step and logs metrics for validation set. """
        loss, accuracy = self.evaluation_step(batch)

        self.log('validation_loss', loss)
        self.log('validation_accuracy', accuracy)

    def test_step(self, batch, batch_idx):
        """Performs an evaluation step and logs metrics for test set."""
        loss, accuracy = self.evaluation_step(batch)

        self.log('test_loss', loss)
        self.log('test_accuracy', accuracy)
コード例 #27
0
                        type=int,
                        default=28,
                        help='Image size (default to be squared images)')
    args = parser.parse_args()

    # load data
    transform = transforms.Compose(
        [transforms.CenterCrop(args.image_size),
         transforms.ToTensor()])
    trainset = datasets.MNIST('./data',
                              train=True,
                              download=True,
                              transform=transform)
    dataloader = torch.utils.data.DataLoader(trainset,
                                             batch_size=args.batch_size,
                                             shuffle=True,
                                             num_workers=1)

    model = Classifier(args)
    crit = nn.CrossEntropyLoss()
    opt = optim.Adam(model.parameters(), lr=args.learning_rate)
    writer = SummaryWriter(args.tensorboard_path)
    print(f"Training for {args.epochs} epochs")
    step = 0
    for epoch in range(args.epochs):
        loss, step = train(args, dataloader, model, opt, crit, step)
        avg_loss = np.average(loss)
        print(f"Epoch {epoch} loss = {avg_loss}")
        writer.add_scalar('class_loss', avg_loss, step)

    torch.save(model.state_dict(), args.save_path)
コード例 #28
0
def main():
    global args
    # Parse commands from ArgumentParser
    args = parser.parse_args()
    # Our text field for imdb data
    TEXT = torchtext.data.Field(lower=True)
    # Our label field for imdb data
    LABEL = torchtext.data.Field(sequential=False)
    # Load GloVE embeddings
    orig_embeddings = torch.load(args.data_folder + 'all_orig_emb.pt')
    total_words = len(orig_embeddings)
    # Load shared words and all GloVE words
    with open(args.data_folder + "shared_words.txt", "r") as file:
        shared_words = file.read().split('\n')
    with open(args.data_folder + "glove_words.txt", "r") as file:
        glove_words = file.read().split('\n')
    # Recreate GloVE_dict
    glove_dict = {}
    for i, word in enumerate(glove_words):
        glove_dict[word] = orig_embeddings[i]

    # Load IMDB dataset with standard splits and restrictions identical to paper
    train, test = torchtext.datasets.IMDB.splits(
        TEXT,
        LABEL,
        filter_pred=lambda ex: ex.label != 'neutral' and len(ex.text) <= 400)

    # Both loops go through the words of train and test dataset, finds words without glove vectors, and replaces them with <unk>
    for i in range(len(train)):
        review = train.examples[i].text
        for i, word in enumerate(review):
            if word not in glove_dict:
                review[i] = '<unk>'
    for i in range(len(test)):
        review = test.examples[i].text
        for i, word in enumerate(review):
            if word not in glove_dict:
                review[i] = '<unk>'

    # Build modified vocabulary
    TEXT.build_vocab(train)
    LABEL.build_vocab(train)

    # Create iterators over train and test set
    train_iter, test_iter = torchtext.data.BucketIterator.splits(
        (train, test), batch_size=args.batch_size, repeat=False, device=-1)

    # If we want to use baseline GloVE embeddings
    if args.embedding_type == 'baseline':
        # Initialize embedding
        comp_embedding = np.random.uniform(
            -0.25, 0.25, (len(TEXT.vocab), args.embedding_size))
        # For each vocab word, replace embedding vector with GloVE vector
        for word in shared_words:
            comp_embedding[TEXT.vocab.stoi[word]] = glove_dict[word]
        # Initialize Classifer with our GloVE embedding
        base_c = Classifier(torch.FloatTensor(comp_embedding), args.batch_size)
        # Put model into CUDA memory if using GPU
        if use_gpu:
            base_c = base_c.cuda()
        # Initialize Optimizer
        optimizer = optim.Adam(filter(lambda p: p.requires_grad,
                                      base_c.parameters()),
                               lr=args.lr)
        # Define Loss function
        loss_func = nn.NLLLoss()

    else:
        '''
        Note- the model in the paper is different because they only store the source dictionaries,
        making their model smaller than normal classifiers which is a major purpose of the paper.
        By my formulation, my model actually has the same size. However, they are fundamentally equivalent,
        except that the authors would have to preprocess the data (convert words into codes) whereas I
        simply make an embedding layer of size Vocab like GloVE vectors. Either way, I should get the same
        levels of accuracy, which is the primary importance of the sentiment classification task- to check
        whether the coding embeddings still give the same level of accuracy.
        '''
        # Initialize embedding
        code_embedding = torch.FloatTensor(
            np.random.uniform(-0.25, 0.25,
                              (len(TEXT.vocab), args.embedding_size)))
        # Load best model for code embedding generation
        model = Code_Learner(args.embedding_size, args.M, args.K)
        model = torch.load(args.model_file)
        # Put model into CUDA memory if using GPU
        if use_gpu:
            code_embedding = code_embedding.cuda()
            model = model.cuda()
        # For all words in vocab
        for i in range(len(TEXT.vocab)):
            # Try to see if it has a corresponding glove_vector
            try:
                glove_vec = glove_dict[TEXT.vocab.itos[i]]
                if use_gpu:
                    glove_vec = glove_vec.cuda()
                # If so, then generate our own embedding for the word using our model
                code_embedding[i] = model(glove_vec, training=False)
            # The word doesn't have a GloVE vector, keep it randomly initialized
            except KeyError:
                pass
        base_c = Classifier(torch.FloatTensor(code_embedding.cpu()),
                            args.batch_size)
        # Put model into CUDA memory if using GPU
        if use_gpu:
            base_c = base_c.cuda()
        # Initialize Optimizer
        optimizer = optim.Adam(filter(lambda p: p.requires_grad,
                                      base_c.parameters()),
                               lr=args.lr)
        # Define Loss function
        loss_func = nn.NLLLoss()

    classifier_train(args.epochs, base_c, optimizer, loss_func, train_iter,
                     test_iter, args.embedding_type)
コード例 #29
0
def run_training(opt):
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

    work_dir, epochs, train_batch, valid_batch, weights = \
        opt.work_dir, opt.epochs, opt.train_bs, opt.valid_bs, opt.weights

    # Directories
    last = os.path.join(work_dir, 'last.pt')
    best = os.path.join(work_dir, 'best.pt')

    # --------------------------------------
    # Setup train and validation set
    # --------------------------------------
    data = pd.read_csv(opt.train_csv)
    images_path = opt.data_dir

    n_classes = 6  # fixed coding :V

    data['class'] = data.apply(lambda row: categ[row["class"]], axis=1)

    train_loader, val_loader = prepare_dataloader(data,
                                                  opt.fold,
                                                  train_batch,
                                                  valid_batch,
                                                  opt.img_size,
                                                  opt.num_workers,
                                                  data_root=images_path)

    # if not opt.ovr_val:
    #     handwritten_data = pd.read_csv(opt.handwritten_csv)
    #     printed_data = pd.read_csv(opt.printed_csv)
    #     handwritten_data['class'] = handwritten_data.apply(lambda row: categ[row["class"]], axis =1)
    #     printed_data['class'] = printed_data.apply(lambda row: categ[row["class"]], axis =1)
    #     _, handwritten_val_loader = prepare_dataloader(
    #         handwritten_data, opt.fold, train_batch, valid_batch, opt.img_size, opt.num_workers, data_root=images_path)

    #     _, printed_val_loader = prepare_dataloader(
    #         printed_data, opt.fold, train_batch, valid_batch, opt.img_size, opt.num_workers, data_root=images_path)

    # --------------------------------------
    # Models
    # --------------------------------------

    model = Classifier(model_name=opt.model_name,
                       n_classes=n_classes,
                       pretrained=True).to(device)

    if opt.weights is not None:
        cp = torch.load(opt.weights)
        model.load_state_dict(cp['model'])

    # -------------------------------------------
    # Setup optimizer, scheduler, criterion loss
    # -------------------------------------------

    optimizer = AdamW(model.parameters(), lr=1e-4, weight_decay=1e-6)
    scheduler = CosineAnnealingWarmRestarts(optimizer,
                                            T_0=10,
                                            T_mult=1,
                                            eta_min=1e-6,
                                            last_epoch=-1)
    scaler = GradScaler()

    loss_tr = nn.CrossEntropyLoss().to(device)
    loss_fn = nn.CrossEntropyLoss().to(device)

    # --------------------------------------
    # Setup training
    # --------------------------------------
    if os.path.exists(work_dir) == False:
        os.mkdir(work_dir)

    best_loss = 1e5
    start_epoch = 0
    best_epoch = 0  # for early stopping

    if opt.resume == True:
        checkpoint = torch.load(last)

        start_epoch = checkpoint["epoch"]
        model.load_state_dict(checkpoint['model'])
        optimizer.load_state_dict(checkpoint['optimizer'])
        scheduler.load_state_dict(checkpoint["scheduler"])
        best_loss = checkpoint["best_loss"]

    # --------------------------------------
    # Start training
    # --------------------------------------
    print("[INFO] Start training...")
    for epoch in range(start_epoch, epochs):
        train_one_epoch(epoch,
                        model,
                        loss_tr,
                        optimizer,
                        train_loader,
                        device,
                        scheduler=scheduler,
                        scaler=scaler)
        with torch.no_grad():
            if opt.ovr_val:
                val_loss = valid_one_epoch_overall(epoch,
                                                   model,
                                                   loss_fn,
                                                   val_loader,
                                                   device,
                                                   scheduler=None)
            else:
                val_loss = valid_one_epoch(epoch,
                                           model,
                                           loss_fn,
                                           handwritten_val_loader,
                                           printed_val_loader,
                                           device,
                                           scheduler=None)

            if val_loss < best_loss:
                best_loss = val_loss
                best_epoch = epoch
                torch.save(
                    {
                        'epoch': epoch,
                        'model': model.state_dict(),
                        'optimizer': optimizer.state_dict(),
                        'scheduler': scheduler.state_dict(),
                        'best_loss': best_loss
                    }, os.path.join(best))

                print('best model found for epoch {}'.format(epoch + 1))

        torch.save(
            {
                'epoch': epoch,
                'model': model.state_dict(),
                'optimizer': optimizer.state_dict(),
                'scheduler': scheduler.state_dict(),
                'best_loss': best_loss
            }, os.path.join(last))

        if epoch - best_epoch > opt.patience:
            print("Early stop achieved at", epoch + 1)
            break

    del model, optimizer, train_loader, val_loader, scheduler, scaler
    torch.cuda.empty_cache()
コード例 #30
0
ファイル: mmd_adapt.py プロジェクト: lzx6/pytorch_DA
momentum = 0.9
total_epochs = 100
source_dataset_train, source_dataset_test = Data_Mnist()
target_dataset_train, target_dataser_test = Data_Mnist_M()

source_loader = torch.utils.data.DataLoader(source_dataset_train, batch_size = batch_size, shuffle = True)
target_loader = torch.utils.data.DataLoader(target_dataset_train, batch_size = batch_size, shuffle = True)
s_test_loader = torch.utils.data.DataLoader(source_dataset_test, batch_size = batch_size, shuffle = True)
t_test_loader = torch.utils.data.DataLoader(target_dataser_test, batch_size = batch_size, shuffle = True)
total_steps = total_epochs*len(source_loader)
'''定义网络框架'''
feature_extrator = Extractor()
class_classifier = Classifier()
class_criterion = nn.NLLLoss()
optimizer = optim.SGD([{'params': feature_extrator.parameters()},
                            {'params': class_classifier.parameters()}], lr= lr, momentum= momentum)

if torch.cuda.is_available():
    feature_extrator = feature_extrator.cuda()
    class_classifier = class_classifier.cuda()
    class_criterion = class_criterion.cuda()

def train(f,c,source,target,optimizer,step):
    result = []
    source_data, source_label = source
    target_data, target_label = target
    # torchvision.utils.save_image(source_data,'mnist.png')
    # torchvision.utils.save_image(target_data, 'mnist_M.png')
    size = min((source_data.shape[0], target_data.shape[0]))
    # print(size)
    source_data, source_label = source_data[0:size, :, :, :], source_label[0:size]