예제 #1
0
class Actor():
    """ Create an agent and set it up for Proximal Policy Optimization """
    maxGradientNormilization = 0.5
    clipParameter = 0.1
    bufferSize = 2500
    batchSize = 128
    epoch = 10

    def __init__(self,
                 outputModel,
                 inputModel,
                 discount=0.99,
                 framesPerState=8,
                 trainingMode=False,
                 hwDevice='cpu'):
        """ The actor constructor
        

            Parameters
            -------
            outputModel : string
                the path to where the output model should be saved, excluding the file extension.
            inputModel : string
                the path, including file extension to the input model.
            discount : float
                The discount factor.
            framesPerState : int
                Number of frames per state.
            trainingMode: : boolean
                Whether this Actor is used for training or predicting.
            hwDevice : string, 
                CPU or CUDA (whether to offload to GPU or use the CPU).
        """

        self.hardwareDevice = hwDevice
        self.trainingMode = trainingMode
        self.inputPath = inputModel
        self.outputPath = outputModel
        self.discount = discount
        self.transition = np.dtype([
            ('s', np.float64, (framesPerState, 96, 96)),
            ('matrix_a', np.float64, (3, )), ('coefficient', np.float64),
            ('slice_to_concat', np.float64),
            ('index_exp ', np.float64, (framesPerState, 96, 96))
        ])

        self.nn = NN().double().to(self.hardwareDevice)
        self.buffer = np.empty(self.bufferSize, dtype=self.transition)
        self.optimizer = optim.Adam(self.nn.parameters(), lr=1e-3)
        self.trainingStep = 0
        self.counter = 0

    def saveModel(self):
        """ Save a model to a pytorch PKL file
        
            Raises
            -------
            AssertionError
                Raised if the output path hasn't been provided

            Notes
            -------
            `self.outputPath` has to be provided WITHOUT a file extension.
        """
        assert self.outputPath != None, "You haven't given an output path!"

        path = f"{self.outputPath}"
        while (True):
            if (not os.path.exists(f'{path}.pkl')):
                filename = f'{self.outputPath}.pkl'
                torch.save(self.nn.state_dict(), filename)
                break
            else:
                path = f'{path}-new'

    def loadModel(self):
        """ Load a model from a pytorch PKL file
        
            Raises
            -------
            AssertionError
                Raised if the given model path doesn't exist in the filesystem

            Notes:
            -------
            `self.inputPath` is a path to a model file INCLUDING it's file extension (usually `.pkl`)
        """
        if not self.inputPath:
            print(
                'No input model argument was given, starting point is now set to untrained.'
            )
            return

        assert os.path.exists(
            self.inputPath), "The given model path doesn't exist!"
        self.nn.load_state_dict(torch.load(self.inputPath))

    def chooseAction(self, state):
        """
            Choose an action to perform on the track

            Parameters
            -------
            state:
                The current state of the car.

            Returns
            -------
            action : np.ndarray
                An action for the network to run on the track

            Notes
            -------
                This function is only called when the --train flag is NOT provided.
        """
        state = torch.from_numpy(state).double().to(
            self.hardwareDevice).unsqueeze(0)
        with torch.no_grad():
            alpha, beta = self.nn(state)[0]

        action = alpha / (alpha + beta)
        return action.squeeze().cpu().numpy()

    def chooseActionTrain(self, state):
        """ Choose an action during training mode
        
            Parameters
            -------
            state:
                The current state of the car.

            Returns
            -------
            action : np.ndarray
                The actions to run on the track
            coefficient : float
                The logarithmic probability for an action

            Notes
            -------
                This function is only called when the --train flag IS provided.
        """
        state = torch.from_numpy(state).double().to(
            self.hardwareDevice).unsqueeze(0)
        with torch.no_grad():
            alpha, beta = self.nn(state)[0]
        dist = Beta(alpha, beta)
        action = dist.sample()
        coefficient = dist.log_prob(action).sum(dim=1)

        action = action.squeeze().cpu().numpy()
        coefficient = coefficient.item()

        return action, coefficient

    def storeInBuffer(self, transition):
        """ Store a transition in a buffer

            Parameters
            -------
            transition : dtype=self.transition 
                A transition element which is saved to the internal memory buffer

            Returns
            -------
            Boolean
                A boolean representing whether the buffer was SUCCESFULLY stored and didn't overflow.
        """
        self.buffer[self.counter] = transition
        self.counter += 1

        if not self.bufferSize == self.counter:
            return False

        self.counter = 0
        return True

    def update(self):
        """ Run an update on the network """
        self.trainingStep += 1

        sliceToConcat = torch.tensor(self.buffer['slice_to_concat'],
                                     dtype=torch.double).to(
                                         self.hardwareDevice).view(-1, 1)
        matrixA = torch.tensor(self.buffer['matrix_a'],
                               dtype=torch.double).to(self.hardwareDevice)
        indexExp = torch.tensor(self.buffer['index_exp'],
                                dtype=torch.double).to(self.hardwareDevice)
        s = torch.tensor(self.buffer['s'],
                         dtype=torch.double).to(self.hardwareDevice)

        old_coefficient = torch.tensor(self.buffer['coefficient'],
                                       dtype=torch.double).to(
                                           self.hardwareDevice).view(-1, 1)

        with torch.no_grad():
            target = sliceToConcat + self.discount * self.nn(indexExp)[1]
            advantage = target - self.nn(s)[1]

        for _ in range(self.epoch):
            for index in BatchSampler(
                    SubsetRandomSampler(range(self.bufferSize)),
                    self.batchSize, False):
                alpha, beta = self.nn(s[index])[0]
                distance = Beta(alpha, beta)
                coefficient = distance.log_prob(matrixA[index]).sum(
                    dim=1, keepdim=True)
                relativeAdvantage = torch.exp(coefficient -
                                              old_coefficient[index])

                s1 = relativeAdvantage * advantage[index]
                s2 = torch.clamp(ratio, 1.0 - self.clipParameter,
                                 1.0 + self.clipParameter) * advantage[index]

                # Loss on an action
                aLoss = -torch.min(s1, s2).mean()

                # Loss on the value
                vLoss = F.smooth_l1_loss(self.nn(s[index])[1], target[index])

                # Total loss calculation
                loss = aLoss + (vLoss * 2.0)

                self.optimizer.zero_grad()
                loss.backward()
                self.optimizer.step()
예제 #2
0
def train(fold_ind, dataset_dir, type_name, setting_symbol, device_id=None):
    if device_id is not None:
        device_ind = device_id
    else:
        device_ind = (fold_ind - 1) % 4
    device = torch.device(
        f'cuda:{device_ind}' if torch.cuda.is_available() else 'cpu')
    print(device)

    # loss
    if args.classifier == "nn":
        crit = nn.NLLLoss()
    elif args.classifier == "dm" or args.classifier == "ip":
        crit = nn.BCELoss()

    # read dataset
    dataset = torch.load(
        os.path.join(dataset_dir, f'dataset_fold_{fold_ind}.pt'))
    num_node_features = dataset.num_node_features
    dataset = dataset.to(device)

    print(dataset)

    # read train and test
    with open(
            os.path.join(dataset_dir, f"train_test_split_fold_{fold_ind}.pkl"),
            "rb") as f:
        positive_train, positive_test = pickle.load(f)
    with open(
            os.path.join(
                dataset_dir,
                f"../10/negative_train_test_split_fold_{fold_ind}.pkl"),
            "rb") as f:
        negative_train, negative_test = pickle.load(f)
    # generate data loader
    if args.classifier == "nn":
        train_loader, test_loader = read_train_test_nn(positive_train,
                                                       positive_test,
                                                       negative_train,
                                                       negative_test, args.bs)
    elif args.classifier == "dm" or args.classifier == "ip":
        train_loader, test_loader = read_train_test_dm(positive_train,
                                                       positive_test,
                                                       negative_train,
                                                       negative_test, args.bs)

    # read omim and test (use for eval_all)
    with open(f"preprocess/edgelist_result/union_omim_gene_list.pkl",
              "rb") as f:
        omim_list, gene_list = pickle.load(f)
    with open(os.path.join(dataset_dir, f"id_conversion_fold_{fold_ind}.pkl"),
              "rb") as f:
        node_name_to_contiguous_id, contiguous_id_to_node_name = pickle.load(f)
    refine_gene_list = []
    for gene in gene_list:
        if gene in node_name_to_contiguous_id:
            refine_gene_list.append(node_name_to_contiguous_id[gene])
        else:
            refine_gene_list.append(-1)

    add_links = []
    if "S" in type_name:
        sc_add_name = "sc_add_topall20.txt"
        with open(
                os.path.join("preprocess/edgelist_result/disease_gene/",
                             sc_add_name), "r") as f:
            for line in f.read().strip().split("\n"):
                d, g = line.strip().split("\t")
                d, g = "omim:" + str(d), "gene:" + str(g)
                if d in omim_list and g in gene_list:
                    add_links.append([
                        node_name_to_contiguous_id[d],
                        node_name_to_contiguous_id[g]
                    ])

    # embedding gcn
    gcn = GCN_EMB(num_node_features, args.gcn_dim, args.conv_type,
                  args.dropout_ratio).to(device)

    # classifier
    if args.classifier == "nn":
        classifier = NN(args.nn_dim, device).to(device)
    elif args.classifier == "dm":
        classifier = DM(args.dm_dim).to(device)
    elif args.classifier == "ip":
        classifier = IP().to(device)

    params = list(gcn.parameters()) + list(classifier.parameters())
    optimizer = torch.optim.SGD(params,
                                lr=args.lr,
                                momentum=0.9,
                                weight_decay=5e-4)
    scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer,
                                                     milestones=args.milestone,
                                                     gamma=0.1)

    # train
    best_auc = 0.0
    tqdm_train = tqdm(range(args.epoch_num))
    for epoch in tqdm_train:
        t1 = time.time()
        gcn.train()
        classifier.train()
        epoch_loss = 0.0
        count = 0
        # calculate loss based on train and test split
        delta_time = 0.0
        for batch_ind, batch_target in train_loader:
            optimizer.zero_grad()
            batch_target = batch_target.to(device)
            # forward
            emb = gcn(dataset)
            # distmult
            batch_output = classifier(emb, batch_ind)
            # loss
            loss = crit(batch_output, batch_target)
            epoch_loss += loss.item() * batch_target.size(0)
            count += batch_target.size(0)
            loss.backward()
            optimizer.step()

        epoch_loss /= count

        # eval acc
        if args.classifier == "nn":
            acc, test_loss, roc_auc = eval_test_nn(gcn, classifier,
                                                   test_loader, device,
                                                   dataset, crit)
        elif args.classifier == "dm" or args.classifier == "ip":
            acc, test_loss, roc_auc = eval_test_dm(gcn, classifier,
                                                   test_loader, device,
                                                   dataset, crit)

        tqdm_train.set_description(
            f"fold {fold_ind}, epoch {epoch+1}, average loss: {round(epoch_loss, 4)}, test accuracy: {round(acc, 4)} , roc auc: {round(roc_auc, 4)} , test loss: {round(test_loss, 4)}"
        )

        if roc_auc >= best_auc:
            best_auc = roc_auc
            torch.save(
                gcn.state_dict(),
                f"best_auc_gcn_{type_name}_{setting_symbol}_fold_{fold_ind}.pth"
            )
            torch.save(
                classifier.state_dict(),
                f"best_auc_classifier_{type_name}_{setting_symbol}_fold_{fold_ind}.pth"
            )

        scheduler.step()

    # final evaluation
    # eval on last
    if args.classifier == "nn":
        mean_auc, mean_rank, fpr_list, tpr_list = eval_all_nn(
            gcn, classifier, device, dataset, refine_gene_list,
            positive_train + add_links, positive_test, negative_train)
    elif args.classifier == "dm" or args.classifier == "ip":
        mean_auc, mean_rank, fpr_list, tpr_list = eval_all_dm(
            gcn, classifier, device, dataset, refine_gene_list,
            positive_train + add_links, positive_test, negative_train)
    print(
        f"====== \n {type_name}_{setting_symbol}, fold {fold_ind}, eval on last \n mean auc is: {round(mean_auc, 4)} \n mean rank is: {round(mean_rank, 4)} \n======"
    )
    torch.save(gcn.state_dict(),
               f"last_gcn_{type_name}_{setting_symbol}_fold_{fold_ind}.pth")
    torch.save(
        classifier.state_dict(),
        f"last_classifier_{type_name}_{setting_symbol}_fold_{fold_ind}.pth")

    # save fold result
    each_mean_auc_on_last[fold_ind - 1].append(mean_auc)
    each_mean_rank_on_last[fold_ind - 1].append(mean_rank)
    each_fpr_list_on_last[fold_ind - 1].extend(fpr_list)
    each_tpr_list_on_last[fold_ind - 1].extend(tpr_list)

    # eval on best auc
    gcn.load_state_dict(
        torch.load(
            f"best_auc_gcn_{type_name}_{setting_symbol}_fold_{fold_ind}.pth"))
    classifier.load_state_dict(
        torch.load(
            f"best_auc_classifier_{type_name}_{setting_symbol}_fold_{fold_ind}.pth"
        ))
    if args.classifier == "nn":
        mean_auc, mean_rank, fpr_list, tpr_list = eval_all_nn(
            gcn, classifier, device, dataset, refine_gene_list,
            positive_train + add_links, positive_test, negative_train)
    elif args.classifier == "dm" or args.classifier == "ip":
        mean_auc, mean_rank, fpr_list, tpr_list = eval_all_dm(
            gcn, classifier, device, dataset, refine_gene_list,
            positive_train + add_links, positive_test, negative_train)
    print(
        f"====== \n {type_name}_{setting_symbol}, fold {fold_ind}, eval on best auc \n mean auc is: {round(mean_auc, 4)} \n mean rank is: {round(mean_rank, 4)} \n======"
    )

    # save fold result
    each_mean_auc[fold_ind - 1].append(mean_auc)
    each_mean_rank[fold_ind - 1].append(mean_rank)
    each_fpr_list[fold_ind - 1].extend(fpr_list)
    each_tpr_list[fold_ind - 1].extend(tpr_list)
예제 #3
0
dataset,loader,test_dataset,test_loader = loadDatasets(args.train_dataset,
args.test_dataset,args.window_size,args.batch_size,shuffle=True,vocab_size=args.vocab_size,compute_dicts = args.embeddings_path is None)
print("Number of training examples / test examples: {} / {}".format(len(dataset),len(test_dataset)))

if args.embeddings_path is not None:
    embLoader = EmbeddingsLoader(args.embeddings_path)
    print("Embeddings loaded, vocab size: {} embedding dims: {}".format(embLoader.get_dimensions()[0],embLoader.get_dimensions()[1]))
    args.vocab_size,args.embedding_size = embLoader.get_dimensions()

model = NN(vocab_size=args.vocab_size,number_tags=dataset.get_num_tags(),
batch_size=args.batch_size,gpu=args.gpu,window_size=args.window_size,
include_cap=args.capitalization,number_suffix=dataset.get_num_suffix(),
embedding_dim=args.embedding_size,activation=args.activation)

model.load_state_dict(torch.load(args.trained_model))

if args.gpu and torch.cuda.is_available():
    model.cuda()

tagged_file = open(args.output_file,"w")

if args.embeddings_path is not None:
    word_to_index = embLoader.word_to_index
else:
    word_to_index = dataset.word_to_index

for i,(words_input,tags) in enumerate(test_loader):
    input_tensor,target_tensor,cap_tensor,suf_tensor = model.get_train_tensors(words_input,tags,
    word_to_index,dataset.tag_to_index,suffix2id=dataset.suffix_to_index)
    output = model(Variable(input_tensor),Variable(cap_tensor),Variable(suf_tensor))