def processing(): dir_sent_train = f"../data/data_preprocessed/{domain}/train/" dir_sent_test = f"../data/data_preprocessed/{domain}/test/" # dir_doc = "../data/data_doc/" dir_output = "../data/pkl/IMN/" if not os.path.exists(dir_output): os.mkdir(dir_output) print("reading data file...") dataset_sent_train = read_data1(dir_sent_train) dataset_sent_test = read_data1(dir_sent_test) # dataset_doc = read_data2(dir_doc) # datasets = [dataset_sent_train, dataset_sent_test, dataset_doc] datasets = [dataset_sent_train, dataset_sent_test] print("making vocab...") vocab = get_vocab(datasets) word2idx, idx2word = get_word_to_idx(vocab) # read the embedding files print("making embedding") emb_dir = "../data/embeddings/" general_emb_file = emb_dir + "glove.840B.300d.txt" domain_emb_file = emb_dir + f"{domain}.txt" general_embeddings = read_emb_idx(general_emb_file, word2idx, 300) domain_embeddings = read_emb_idx(domain_emb_file, word2idx, 100) # dataset_total = {"train_sent": dataset_sent_train, "train_doc": dataset_doc, "test_sent": dataset_sent_test} dataset_total = {"train_sent": dataset_sent_train, "test_sent": dataset_sent_test} # transform sentence to word index datasets = make_datasets(dataset_total, word2idx) # dir_output the transformed files print("making pickle file...") utils.pkl_dump(datasets, dir_output + "/features.pkl") utils.pkl_dump(word2idx, dir_output + "/word2idx.pkl") utils.pkl_dump(general_embeddings, dir_output + "/general_embeddings.pkl") utils.pkl_dump(domain_embeddings, dir_output + "/domain_embeddings.pkl") utils.pkl_dump(idx2word, dir_output + "/idx2word.pkl")
def persist_experiment(t_experiment, i_episode, agent, scores): os.chdir(t_experiment) torch.save(agent.actor_local.state_dict(), "checkpoint_actor_{}.pth".format(i_episode)) torch.save(agent.critic_local.state_dict(), "checkpoint_critic_{}.pth".format(i_episode)) pkl_dump(scores, "scores_{}.pkl".format(i_episode)) os.chdir("..")
def get_results(test_ds, type): dl = DataLoader(test_ds, batch_size=len(test_ds), num_workers=5) retdict = train.eval_model(model, dl, args.OP_tgt, 3) model_dir = os.path.join('models', args.modelname) try: os.makedirs(os.path.join(model_dir, f'{type}_eval_results')) except: shutil.rmtree(os.path.join(model_dir, f'{type}_eval_results')) os.makedirs(os.path.join(model_dir, f'{type}_eval_results')) retdict['modelname'] = args.modelname # Print pprint.pprint(retdict) utils.pkl_dump( retdict, os.path.join('models', args.modelname, f'{type}_report.dict'))
def df_to_training_pairs(self, seq_dir, auto_id, grp): def decompose_slice(indices): input_df = grp.loc[indices[0]: indices[1]] # Slice out an input sequence first_month = input_df.MONTH.iloc[0] seq_name = f'{auto_id}_{first_month}' # input_df = pd.DataFrame(self.scaler.transform(input_df), columns=input_df.columns) x = input_df[self.col_dict['input']] x_obs = x.shift(1).fillna(x.iloc[0]).values x = x.values m = input_df[self.col_dict['missing']].values t = input_df[self.col_dict['delta']].values return seq_name, np.array([x, m, t, x_obs]) input_start_ix = grp.index[0] input_final_ix = grp.index[-1] - self.min_rows_reqd + 1 input_seq_df = [(pos, pos + self.history_len - 1) for pos in range(input_start_ix, input_final_ix + 1) ] # pandas slicing is inclusive target_start_ix = grp.index[0] + self.history_len target_final_ix = grp.index[-1] - self.future_len + 1 target_seq_df = [(pos, pos + self.future_len - 1) for pos in range(target_start_ix, target_final_ix + 1) ] tgt_types = ['tgt1', 'tgt2'] label_dict = {} target_loader = TargetFunc(grp) # sliding window for slice_ix in range(len(input_seq_df)): name, x = decompose_slice(input_seq_df[slice_ix]) utils.pkl_dump(x, os.path.join(seq_dir, name + '.npy')) label_dict[name] = {} for tgt in tgt_types: fn = eval(f"target_loader.{tgt}") label_dict[name][tgt] = fn(target_seq_df[slice_ix]) return label_dict # return for collation with other patients
def train_model(train_iter, valid_iter, X_Mean, tgt_col, aux_cols, epochs, modelname, nb_classes, \ lr=0.001, aux_alpha=0, tr_alpha=0, class_weights=None, l2=None, model=None, print_every=100): """ Train a GRUD model :param train_iter: Train DataLoader :param valid_iter: Valid DataLoader :param X_Mean: Empirical Mean values for each dimension in the input (only important for variables with missing data) :param tgt_col: (str) Name of OP target :param aux_cols: list(str) of names of Aux targets. :param epochs: Int of epochs to run :param modelname: Unique name for this model :param nb_classes: Number of OP target classes :param aux_alpha: Weight for Aux Loss :param tr_alpha: Weight for TR Loss :param class_weights (optional): Weights to scale OP Loss (for skewed datasets) """ device = utils.try_gpu() # Set directory for model outputs try: os.makedirs(os.path.join('models',modelname)) os.makedirs(os.path.join('models',modelname, 'gradflow')) except FileExistsError: pass # Initialize plotter class for gradflow plotter = TrainPlot(modelname) # Initialize model and learners class_weights = class_weights or [1]*nb_classes l2 = l2 or 0 for X,y in train_iter: break input_dim = X.size(-1) aux_dim = [ (y[aux_c].size(-1) if len(y[aux_c].size())>1 else 1) for aux_c in aux_cols] # if-else for targets with single dimennsion. their size(-1) will be batchsize model = StackedGRUDClassifier(input_dim, nb_classes, X_Mean, aux_dim).to(device=device, dtype=torch.float) criterion = nn.CrossEntropyLoss(weight=torch.Tensor(class_weights).to(device=device)) optimizer = torch.optim.Adam(model.parameters(), lr=lr, weight_decay=l2) scheduler = torch.optim.lr_scheduler.StepLR(optimizer, 30, 0.85) # Store training metrics train_meta = {} train_meta['train_losses'] = [] train_meta['valid_losses'] = [] train_meta['min_valid_loss'] = sys.maxsize train_meta['epoch_results'] = [] for epoch in range(epochs): # TRAIN EPOCH t0 = time.time() metrics = train_epoch(model, train_iter, tgt_col, aux_cols, criterion, optimizer, aux_alpha, tr_alpha, scheduler, print_every=print_every, plotter=plotter) if epoch<200:scheduler.step() print(f"Epoch trained in {time.time()-t0}") # EVALUATE AGAINST VALIDATION SET t0 = time.time() eval_scores = eval_model(model, valid_iter, tgt_col, nb_classes) train_meta['epoch_results'].append(eval_scores) print(f"Evaluation done in {time.time()-t0}") t0 = time.time() # SAVE CHECKPOINT if eval_scores['loss'] < train_meta['min_valid_loss'] or epoch % 20 == 0: train_meta['min_valid_loss'] = min(eval_scores['loss'], train_meta['min_valid_loss']) checkpoint = { 'epoch': epoch + 1, 'state_dict': model.state_dict(), 'optimizer': optimizer.state_dict() } save_ckp(checkpoint, True, os.path.join('models', modelname, 'checkpoint.pt'), os.path.join('models', modelname, 'best_model.pt')) print(f"Checkpoint created") # LOG PROGRESS print("\n\n================================================================================================================\n") print(f"Epoch: {epoch+1} TrainLoss: {metrics[1]/metrics[0]} ValidLoss: {eval_scores['loss']} ValidAcc:{eval_scores['accuracy']} WallTime: {datetime.datetime.now()}\n") print(eval_scores['conf_matrix']) print(pd.DataFrame.from_dict(eval_scores['clf_report'])) print(eval_scores['brier']) print(eval_scores['roc']) print("\n\n================================================================================================================\n") # SAVE TRAINING PROGRESS DATA train_meta['train_losses'].append(metrics[1]/metrics[0]) train_meta['valid_losses'].append(eval_scores['loss']) utils.pkl_dump(train_meta, os.path.join('models', modelname, 'trainmeta.dict')) print(f"post eval dumping took {time.time()-t0}") # PLOT LOSSES t0 = time.time() plt.figure(1) plt.plot(train_meta['train_losses']) plt.plot(train_meta['valid_losses']) plt.xlabel("Minibatch") plt.ylabel("Loss") plt.savefig(os.path.join('models', modelname, modelname+'_lossPlot.png'), bbox_inches='tight') print(f"plotting took {time.time()-t0}") return model
def train_test_split(self, dataset, x_mean, datadir, train_size): """ IBDSequenceGenerator.write_to_disk: - Reads padded X, M, T matrices - Generate overlapping sequences and {tgt_type} training labels for each patient - Persist sequences as numpy arrays at data/{datadir}/{train, valid, test}/{ID}_{START_TS}.npy - Persist labels for all sequences in data/{datadir}/{train, valid, test}/label_dict.pkl - Persist empirical mean values at data/{datadir}/x_mean.pkl """ print(SequenceGenerator.write_to_disk.__doc__) # Create out directories if not datadir: datadir = f'm{self.history_len}p{self.future_len}' out_fp = os.path.join('data', datadir) train_seq_dir = os.path.join(out_fp, 'train') valid_seq_dir = os.path.join(out_fp, 'valid') test_seq_dir = os.path.join(out_fp, 'test') if not os.path.exists(out_fp): os.makedirs(out_fp) if not os.path.exists(train_seq_dir): os.makedirs(train_seq_dir) if not os.path.exists(valid_seq_dir): os.makedirs(valid_seq_dir) if not os.path.exists(test_seq_dir): os.makedirs(test_seq_dir) groups = dataset.groupby('ID') TRAIN_LABELS = {} VALID_LABELS = {} TEST_LABELS = {} valid_size = (1 + train_size) / 2 patients_dropped = 0 for auto_id, grp in groups: grplen = grp.shape[0] if grplen < self.min_rows_reqd: patients_dropped += 1 continue train = grp.iloc[:int(train_size * grplen)] valid = grp.iloc[int(train_size * grplen):int(valid_size * grplen)] test = grp.iloc[int(valid_size * grplen):] # if not enough observations for a validation sequence, use them either as test or train (don't waste any data) if valid.shape[0] < self.min_rows_reqd: if valid.shape[0] + test.shape[0] >= self.min_rows_reqd: test = pd.concat([valid, test]) valid = None else: train = pd.concat([train, valid, test]) valid = None test = None TRAIN_LABELS.update( self.df_to_training_pairs(train_seq_dir, auto_id, train)) if valid is not None: VALID_LABELS.update( self.df_to_training_pairs(valid_seq_dir, auto_id, valid)) if test is not None: TEST_LABELS.update( self.df_to_training_pairs(test_seq_dir, auto_id, test)) utils.pkl_dump(TRAIN_LABELS, os.path.join(train_seq_dir, 'label_dict.pkl')) utils.pkl_dump(VALID_LABELS, os.path.join(valid_seq_dir, 'label_dict.pkl')) utils.pkl_dump(TEST_LABELS, os.path.join(test_seq_dir, 'label_dict.pkl')) utils.pkl_dump(x_mean[2:], os.path.join( out_fp, 'x_mean.pkl')) # remove auto id and month ts print(f"Patients dropped: {patients_dropped}")
all_data = pd.concat([df, m, t], axis=1) col_dict = {'input': df.columns, 'missing': m.columns, 'delta': t.columns} return all_data, col_dict, x_mean if __name__ == "__main__": # Generate dummy data arr = pd.DataFrame(np.random.rand(5, 5, 5).reshape(25, 5), columns=[f'col{i+1}' for i in range(5)]) arr['ID'] = sum([[i] * 5 for i in range(3, 8)], []) arr['YEAR'] = 2020 arr['MONTH'] = [1, 4, 5, 7, 8] * 5 # Generate cleaned, resampled, imputed data with missing mask and delta + save to pickles folder df, col_dict, x_mean = clean_longitudinal_inputs(arr) # Init SequenceGenerator with look-back and look-forward durations seqgen = SequenceGenerator(3, 1, col_dict) # Generate time series inputs with their target labels # X (input arrays) pickled to disk at /tmp/input_id.npy # y returned as a dict {input_id : {tgt1: 0, tgt2: 1}} c = 0 target_dict = {} for auto_id, group in df.groupby('ID'): target_dict.update(seqgen.df_to_training_pairs('tmp', auto_id, group)) utils.pkl_dump(target_dict, 'tmp/label_dict.pkl')
def ddpg_multiagent(env, agent1, agent2, cfg, db): # Get configuration n_episodes = cfg["Training"]["Number_episodes"] max_t = cfg["Training"]["Max_timesteps"] print_every = cfg["Training"]["Score_window"] starting_random = cfg["Training"]["Starting_random"] brain_index = cfg["Agent"]["Brain_index"] persist_mongodb = cfg["Training"]["Persist_mongodb"] success = cfg["Environment"]["Success"] #Initialize score lists scores_deque = deque(maxlen=print_every) scores = [] # Create a directory to save the findings. # experiment_dir = setup_experiment(cfg) if persist_mongodb: experiment_id = setup_experiment(db, cfg) brain_name = env.brain_names[brain_index] # Train for n_episodes for i_episode in range(1, n_episodes + 1): env_info = env.reset(train_mode=True)[brain_name] n_agents = len(env_info.agents) states = env_info.vector_observations agent1.reset() agent2.reset() actions = np.zeros((n_agents, agent1.action_size)) score = np.zeros(n_agents) for t in range(max_t): if i_episode < starting_random: actions = 2 * np.random.randn(n_agents, agent1.action_size) - 1.0 else: actions[0, :] = agent1.act(states[0, :]) actions[1, :] = agent2.act(states[1, :]) # for i_agent in range(n_agents): # actions[i_agent, :] = agent.act(states[i_agent, :]) next_states, rewards, dones, _ = step_unity( env, actions, brain_name) for i_agent in range(n_agents): # Add experience to both of the agent's replay buffers agent1.step(states[i_agent, :], actions[i_agent, :], rewards[i_agent], next_states[i_agent, :], dones[i_agent]) agent2.step(states[i_agent, :], actions[i_agent, :], rewards[i_agent], next_states[i_agent, :], dones[i_agent]) states = next_states score += rewards if np.any(dones): break scores_deque.append(score) scores.append(score) mean_score = np.vstack(scores_deque).mean(axis=0).max() print("\rEpisode {}\tAverage Score: {:.4f}\tNoise Modulation: {:.3f}". format(i_episode, mean_score, agent1.noise_modulation), end="") # print("\rEpisode {}\tAverage Score: {}".format(i_episode, scores_deque), end="") visualize = False if i_episode % print_every == 0: # persist_experiment(experiment_dir, i_episode, agent, scores) if persist_mongodb: persist_experiment(db, experiment_id, i_episode, agent1, scores, print_every) persist_experiment(db, experiment_id, i_episode, agent2, scores, print_every) else: torch.save(agent1.actor_local.state_dict(), f"checkpoint_actor_1_{i_episode}.pth") torch.save(agent1.critic_local.state_dict(), f"checkpoint_critic_1_{i_episode}.pth") torch.save(agent2.actor_local.state_dict(), f"checkpoint_actor_2_{i_episode}.pth") torch.save(agent2.critic_local.state_dict(), f"checkpoint_critic_2_{i_episode}.pth") print("\rEpisode {}\tAverage Score: {:.4f}".format( i_episode, mean_score)) if mean_score >= success: # This is going to be the first thing I'd be digging in the database for, # so here you go. fpath_actor_1 = "checkpoint_actor_1_winner_{}.pth".format( i_episode) fpath_critic_1 = "checkpoint_critic_1_winner_{}.pth".format( i_episode) torch.save(agent1.actor_local.state_dict(), fpath_actor_1) torch.save(agent1.critic_local.state_dict(), fpath_critic_1) fpath_actor_2 = "checkpoint_actor_2_winner_{}.pth".format( i_episode) fpath_critic_2 = "checkpoint_critic_2_winner_{}.pth".format( i_episode) torch.save(agent2.actor_local.state_dict(), fpath_actor_2) torch.save(agent2.critic_local.state_dict(), fpath_critic_2) pkl_dump(scores, "scores_winner.pkl") break return scores
def ddpg_selfplay(env, agent, cfg, db): # Get configuration n_episodes = cfg["Training"]["Number_episodes"] max_t = cfg["Training"]["Max_timesteps"] print_every = cfg["Training"]["Score_window"] starting_random = cfg["Training"]["Starting_random"] brain_index = cfg["Agent"]["Brain_index"] dump_agent = cfg["Training"]["Dump_agent"] success = cfg["Environment"]["Success"] persist_mongodb = cfg["Training"]["Persist_mongodb"] pretrained = cfg["Training"]["Pretrained"] agent.update_every = max_t * starting_random * 2 #Initialize score lists scores_deque = deque(maxlen=print_every) scores = [] # Create a directory to save the findings. # experiment_dir = setup_experiment(cfg) experiment_id = setup_experiment(db, cfg) print("Experiment ID: {}".format(experiment_id)) brain_name = env.brain_names[brain_index] # Train for n_episodes for i_episode in range(1, n_episodes + 1): env_info = env.reset(train_mode=True)[brain_name] n_agents = len(env_info.agents) states = env_info.vector_observations agent.reset() actions = np.zeros((n_agents, agent.action_size)) score = np.zeros(n_agents) if i_episode == starting_random and pretrained: print("Loading pre-trained weights") agent = load_agent_weights(agent, cfg) print("Pre-trained weights loaded!") agent.update_every = cfg["Agent"]["Update_every"] for t in range(max_t): if i_episode < starting_random: actions = 2 * np.random.rand(n_agents, agent.action_size) - 1.0 else: for i_agent in range(n_agents): actions[i_agent, :] = agent.act(states[i_agent, :]) next_states, rewards, dones, _ = step_unity( env, actions, brain_name) for i_agent in range(n_agents): # Add experience to both of the agent's replay buffers agent.step(states[i_agent, :], actions[i_agent, :], rewards[i_agent], next_states[i_agent, :], dones[i_agent]) states = next_states score += rewards if np.any(dones): break scores_deque.append(score) scores.append(score) mean_score = np.vstack(scores_deque).max(axis=1).mean() print( "\rEpisode {}\tAverage Score: {:.4f}\t Score: {:.3f} {:.3f} noise {:.2f}" .format(i_episode, mean_score, score[0], score[1], agent.noise_modulation), end="") # print("\rEpisode {}\tAverage Score: {}".format(i_episode, scores_deque), end="") visualize = False if i_episode % print_every == 0: print("\rEpisode {}\tAverage Score: {:.4f}".format( i_episode, mean_score)) if persist_mongodb: persist_experiment(db, experiment_id, i_episode, agent, scores, print_every) else: torch.save(agent.actor_local.state_dict(), f"checkpoint_actor_{i_episode}.pth") torch.save(agent.critic_local.state_dict(), f"checkpoint_critic_{i_episode}.pth") if i_episode % dump_agent == 0: # To heck with it let's save some to disk even though I have utilities to load. # It's important. fpath_actor = "checkpoint_actor_{}.pth".format(i_episode) fpath_critic = "checkpoint_critic_{}.pth".format(i_episode) torch.save(agent.actor_local.state_dict(), fpath_actor) torch.save(agent.critic_local.state_dict(), fpath_critic) if mean_score >= success: # This is going to be the first thing I'd be digging in the database for, # so here you go. fpath_actor = "checkpoint_actor_winner_{}.pth".format(i_episode) fpath_critic = "checkpoint_critic_winner_{}.pth".format(i_episode) torch.save(agent.actor_local.state_dict(), fpath_actor) torch.save(agent.critic_local.state_dict(), fpath_critic) pkl_dump(scores, "scores_winner.pkl") break return scores