class Train:
    def __init__(self, data_name):
        self.dataset = get_dataset(data_name)
        self.n_entities = self.dataset.n_entities
        self.n_relations = self.dataset.n_relations

    def prepareData(self):
        print("Perpare dataloader")
        self.train = TrainDataset(self.dataset)
        self.trainloader = None
        self.valid = EvalDataset(self.dataset)
        self.validloader = DataLoader(self.valid,
                                      batch_size=self.valid.n_triples,
                                      shuffle=False)

    def prepareModel(self):
        print("Perpare model")
        self.model = TransE(self.n_entities, self.n_relations, embDim=100)
        if GPU:
            self.model.cuda()

    def saveModel(self):
        pickle.dump(self.model.get_emb_weights(), open('emb_weight.pkl', 'wb'))

    def fit(self):
        optim = torch.optim.Adam(self.model.parameters(), lr=LR)
        minLoss = float("inf")
        bestMR = float("inf")
        GlobalEpoch = 0
        for seed in range(100):
            print(f"# Using seed: {seed}")
            self.train.regenerate_neg_samples(seed=seed)
            self.trainloader = DataLoader(self.train,
                                          batch_size=1024,
                                          shuffle=True,
                                          num_workers=4)
            for epoch in range(EPOCHS_PER_SEED):
                GlobalEpoch += 1
                for sample in self.trainloader:
                    if GPU:
                        pos_triples = torch.LongTensor(
                            sample['pos_triples']).cuda()
                        neg_triples = torch.LongTensor(
                            sample['neg_triples']).cuda()
                    else:
                        pos_triples = torch.LongTensor(sample['pos_triples'])
                        neg_triples = torch.LongTensor(sample['neg_triples'])

                    self.model.normal_emb()

                    loss = self.model(pos_triples, neg_triples)
                    if GPU:
                        lossVal = loss.cpu().item()
                    else:
                        lossVal = loss.item()

                    optim.zero_grad()
                    loss.backward()
                    optim.step()

                    if minLoss > lossVal:
                        minLoss = lossVal
                MR = Eval_MR(self.validloader, "L2",
                             **self.model.get_emb_weights())
                if MR < bestMR:
                    bestMR = MR
                    print('save embedding weight')
                    self.saveModel()
                print(
                    f"Epoch: {epoch + 1}, Total_Train: {GlobalEpoch}, Loss: {lossVal}, minLoss: {minLoss},"
                    f"MR: {MR}, bestMR: {bestMR}")
                if GlobalEpoch % LR_DECAY_EPOCH == 0:
                    adjust_learning_rate(optim, 0.96)
Пример #2
0
def main():
    opts = get_train_args()
    print("load data ...")
    data = DataSet('data/modified_triples.txt')
    dataloader = DataLoader(data, shuffle=True, batch_size=opts.batch_size)
    print("load model ...")
    if opts.model_type == 'transe':
        model = TransE(opts, data.ent_tot, data.rel_tot)
    elif opts.model_type == "distmult":
        model = DistMult(opts, data.ent_tot, data.rel_tot)
    if opts.optimizer == 'Adam':
        optimizer = optim.Adam(model.parameters(), lr=opts.lr)
    elif opts.optimizer == 'SGD':
        optimizer = optim.SGD(model.parameters(), lr=opts.lr)
    model.cuda()
    model.relation_normalize()
    loss = torch.nn.MarginRankingLoss(margin=opts.margin)

    print("start training")
    for epoch in range(1, opts.epochs + 1):
        print("epoch : " + str(epoch))
        model.train()
        epoch_start = time.time()
        epoch_loss = 0
        tot = 0
        cnt = 0
        for i, batch_data in enumerate(dataloader):
            optimizer.zero_grad()
            batch_h, batch_r, batch_t, batch_n = batch_data
            batch_h = torch.LongTensor(batch_h).cuda()
            batch_r = torch.LongTensor(batch_r).cuda()
            batch_t = torch.LongTensor(batch_t).cuda()
            batch_n = torch.LongTensor(batch_n).cuda()
            pos_score, neg_score, dist = model.forward(batch_h, batch_r,
                                                       batch_t, batch_n)
            pos_score = pos_score.cpu()
            neg_score = neg_score.cpu()
            dist = dist.cpu()
            train_loss = loss(pos_score, neg_score,
                              torch.ones(pos_score.size(-1))) + dist
            train_loss.backward()
            optimizer.step()
            batch_loss = torch.sum(train_loss)
            epoch_loss += batch_loss
            batch_size = batch_h.size(0)
            tot += batch_size
            cnt += 1
            print('\r{:>10} epoch {} progress {} loss: {}\n'.format(
                '', epoch, tot / data.__len__(), train_loss),
                  end='')
        end = time.time()
        time_used = end - epoch_start
        epoch_loss /= cnt
        print('one epoch time: {} minutes'.format(time_used / 60))
        print('{} epochs'.format(epoch))
        print('epoch {} loss: {}'.format(epoch, epoch_loss))

        if epoch % opts.save_step == 0:
            print("save model...")
            model.entity_normalize()
            torch.save(model.state_dict(), 'model.pt')

    print("save model...")
    model.entity_normalize()
    torch.save(model.state_dict(), 'model.pt')
    print("[Saving embeddings of whole entities & relations...]")
    save_embeddings(model, opts, data.id2ent, data.id2rel)
    print("[Embedding results are saved successfully.]")