UTRGAN / scripts /train.py
wuxing0105's picture
Upload folder using huggingface_hub (part 2)
53ebf66 verified
Raw
History Blame Contribute Delete
13.4 kB
import os
import sys
from pathlib import Path
# Keep the official ``src`` package importable after adopting the standard
# conf/model/scripts/weight layout.
PROJECT_ROOT = Path(__file__).resolve().parents[1]
MODEL_ROOT = PROJECT_ROOT / "model"
if str(MODEL_ROOT) not in sys.path:
sys.path.insert(0, str(MODEL_ROOT))
# The released H5 files use the legacy Keras serialization format.
os.environ.setdefault("TF_USE_LEGACY_KERAS", "1")
import numpy as np
import pandas as pd
import pdb
import tensorflow as tf
# from IPython.display import clear_output
import time
from src.gan.lib import models
from src.gan.lib import utils
import socket
import datetime
from tqdm import tqdm
import random
import matplotlib.pyplot as plt
import argparse
import tensorflow.keras.backend as K
from tensorflow.keras.optimizers import Adam
tf.compat.v1.enable_eager_execution()
parser = argparse.ArgumentParser()
parser.add_argument('-d', type=str, required=False,
default=str(PROJECT_ROOT / 'conf' / 'data' / 'utrdb2.csv'))
parser.add_argument('-bs', type=int, required=False ,default=64)
parser.add_argument('-lr', type=int, required=False ,default=5)
parser.add_argument('-mil', type=int, required=False ,default=64)
parser.add_argument('-mxl', type=int, required=False ,default=128)
parser.add_argument('-dim', type=int, required=False ,default=40)
parser.add_argument('-gpu', type=str, required=False ,default='-1')
parser.add_argument('-e', '--epochs', type=int, default=4000,
help='Number of complete passes over the filtered UTRdb dataset.')
parser.add_argument('--output-dir', type=str,
default=str(PROJECT_ROOT / 'outputs' / 'train'),
help='Directory for logs, generated samples, and checkpoints.')
args = parser.parse_args()
MODEL_NAME = 'WGAN-TF2'
RUN_ROOT = Path(args.output_dir).expanduser().resolve()
OUTPUT_PATH = RUN_ROOT / 'outputs' / MODEL_NAME
TRAIN_LOGDIR = RUN_ROOT / 'tensorboard' / MODEL_NAME / 'train_data'
OUTPUT_PATH.mkdir(parents=True, exist_ok=True)
TRAIN_LOGDIR.mkdir(parents=True, exist_ok=True)
file_writer = tf.summary.create_file_writer(str(TRAIN_LOGDIR))
if args.gpu == '-1':
device = 'cpu'
else:
os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu
device = 'cuda'
def plot(x, y, logdir, name, xlabel=None, ylabel=None, title=None):
plt.plot(x,y,'-')
plt.title(title)
plt.xlabel(xlabel)
plt.ylabel(ylabel)
plt.savefig(logdir+'/'+name+'.png')
plt.clf()
def plot_valid(x1, y1, x2, y2, logdir, name, xlabel=None, ylabel=None, title=None):
plt.plot(x2,y2,'-',color='tab:blue')
plt.plot(x1,y1,'-',color='tab:orange')
plt.title(title)
plt.xlabel(xlabel)
plt.ylabel(ylabel)
plt.savefig(logdir+'/'+name+'.png')
plt.clf()
def gradient_penalty_loss( y_true, y_pred, discriminator):
"""
Computes gradient penalty based on prediction and weighted real / fake samples
"""
alpha = K.random_uniform((DIM, 1, 1))
averaged_samples = (alpha * y_pred) + ((1 - alpha) * y_true)
gradients = K.gradients(y_pred, averaged_samples)[0]
# compute the euclidean norm by squaring ...
gradients_sqr = K.square(gradients)
# ... summing over the rows ...
gradients_sqr_sum = K.sum(gradients_sqr,
axis=np.arange(1, len(gradients_sqr.shape)))
# ... and sqrt
gradient_l2_norm = K.sqrt(gradients_sqr_sum)
# compute lambda * (1 - ||grad||)^2 still for each single sample
gradient_penalty = K.square(1 - gradient_l2_norm)
# return the mean as loss over all the batch samples
return K.mean(gradient_penalty)
def log(samples_dir=False,suff=None):
stamp = datetime.date.strftime(datetime.datetime.now(), "%Y.%m.%d-%Hh%Mm%Ss") + "_{}".format(socket.gethostname())
full_logdir = os.path.join(str(RUN_ROOT / "logs"), stamp)
if suff:
full_logdir = full_logdir + suff
os.makedirs(full_logdir, exist_ok=True)
if samples_dir: os.makedirs(os.path.join(full_logdir, "samples"), exist_ok=True)
log_dir = "{}:{}".format(socket.gethostname(), full_logdir)
return full_logdir, 0
data_path = args.d
data_utr = pd.read_csv(data_path)
UTRdf = data_utr['seq'].to_numpy()
seqs = []
UTR_LEN = args.mxl
for i in range(len(UTRdf)):
if len(UTRdf[i]) < UTR_LEN+1 and len(UTRdf[i]) > int(UTR_LEN/2):
if UTRdf[i] not in seqs:
seqs.append(UTRdf[i])
sequences = np.array(seqs)
sequences = [x.upper() for x in sequences]
rna_vocab = {"A":0,
"C":1,
"G":2,
"U":3,
"*":4}
rev_rna_vocab = {v:k for k,v in rna_vocab.items()}
def one_hot_encode(seq, SEQ_LEN=UTR_LEN):
mapping = dict(zip("ACGT*", range(5)))
seq2 = [mapping[i] for i in seq]
if len(seq2) < SEQ_LEN:
extra = [np.eye(5)[4]] * (SEQ_LEN - len(seq2))
return np.vstack([np.eye(5)[seq2] , extra])
return np.eye(5)[seq2]
def one_hot_encode_2(seq, SEQ_LEN=UTR_LEN):
mapping = dict(zip("ACGT", range(4)))
seq2 = [mapping[i] for i in seq]
return np.eye(4)[seq2]
ohe_sequences = np.asarray([one_hot_encode(x) for x in sequences])
BATCH_SIZE = args.bs # Batch size
ITERS = args.epochs # How many complete dataset iterations to train for
SEQ_LEN = UTR_LEN # Sequence length in characters
DIM = args.dim # Model dimensionality.
CRITIC_ITERS = 5 # How many critic iterations per generator iteration.
LAMBDA = 10 # Gradient penalty lambda hyperparameter.
# README defines ``-lr 5`` as 1e-5. The upstream ``e**args.lr`` expression
# is inconsistent with that documented interface.
LR = np.power(10.0, -args.lr)
LAMBDA = 10 # For gradient penalty
CURRENT_EPOCH = 1 # Epoch start from
SAVE_EVERY_N_EPOCH = 50 # Save checkpoint at every n epoch
MIN_LR = 0.000001 # Minimum value of learning rate
DECAY_FACTOR=1.00004 # learning rate decay factor
'''
Set seed for reproducibility
'''
seed = 35
np.random.seed(seed)
# tf.set_random_seed(seed)
tf.random.set_seed(seed)
logdir, checkpoint_baseline = log(samples_dir=True)
logdir2 = ''
'''
Build GAN
'''
model_type = "resnet"
data_enc_dim = 5
data_size = SEQ_LEN * data_enc_dim
# data_size = 256
gen_layers = 3
disc_layers = 3
lmbda = 10. #lipschitz penalty hyperparameter.
SAMPLE_SIZE = 128
N_CHANNELS = DIM
G = models.resnet_g2(DIM,N_CHANNELS,SEQ_LEN,5,res_layers=gen_layers)
D = models.resnet_d2(N_CHANNELS,SEQ_LEN,5,res_layers=disc_layers)
G.summary()
D.summary()
D_optimizer = Adam(learning_rate=LR, beta_1=0.5, beta_2=0.99)
G_optimizer = Adam(learning_rate=LR, beta_1=0.5, beta_2=0.99)
EPOCHs = ITERS
@tf.function
def WGAN_GP_train_d_step(real_sample, batch_size, step):
noise = tf.random.normal([batch_size, DIM])
epsilon = tf.random.uniform(shape=[batch_size, 1, 1], minval=0, maxval=1)
###################################
# Train D
###################################
with tf.GradientTape(persistent=True) as d_tape:
with tf.GradientTape() as gp_tape:
fake_sample = G([noise], training=True)
fake_sample_mixed = epsilon * tf.dtypes.cast(real_sample, tf.float32) + ((1 - epsilon) * fake_sample)
fake_mixed_pred = D([fake_sample_mixed], training=True)
# Compute gradient penalty
grads = gp_tape.gradient(fake_mixed_pred, fake_sample_mixed)
grad_norms = tf.sqrt(tf.reduce_sum(tf.square(grads), axis=[1,2])) # Originally axis=[1,2]
# grad_norms = tf.norm(grads, axis=[1,2])
gradient_penalty = tf.reduce_mean(tf.square(grad_norms - 1.))
fake_pred = D([fake_sample], training=True)
real_pred = D([real_sample], training=True)
D_loss = tf.reduce_mean(fake_pred) - tf.reduce_mean(real_pred) + LAMBDA * gradient_penalty
# Calculate the gradients for discriminator
D_gradients = d_tape.gradient(D_loss,D.trainable_variables)
# Apply the gradients to the optimizer
D_optimizer.apply_gradients(zip(D_gradients,D.trainable_variables))
# Write loss values to tensorboard
if step % 10 == 0:
with file_writer.as_default():
tf.summary.scalar('D_loss', tf.reduce_mean(D_loss), step=step)
return D_loss, gradient_penalty
@tf.function
def WGAN_GP_train_g_step(real_sample, batch_size, step):
noise = tf.random.normal([batch_size, DIM])
###################################
# Train G
###################################
with tf.GradientTape() as g_tape:
fake_sample = G([noise], training=True)
fake_pred = D([fake_sample], training=True)
G_loss = -tf.reduce_mean(fake_pred)
G_gradients = g_tape.gradient(G_loss,
G.trainable_variables)
# Apply the gradients to the optimizer
G_optimizer.apply_gradients(zip(G_gradients,
G.trainable_variables))
# Write loss values to tensorboard
if step % 10 == 0:
with file_writer.as_default():
tf.summary.scalar('G_loss', G_loss, step=step)
return G_loss, noise
checkpoint_path = os.path.join(str(RUN_ROOT), "checkpoints", "tensorflow", MODEL_NAME)
ckpt = tf.train.Checkpoint(generator=G,
discriminator=D,
G_optimizer=G_optimizer,
D_optimizer=D_optimizer)
ckpt_manager = tf.train.CheckpointManager(ckpt, checkpoint_path, max_to_keep=40)
def generate_and_save_samples(model, epoch, test_input, figure_size=(12,6), subplot=(3,6), save=True, is_flatten=False):
'''
Generate samples and plot it.
'''
predictions = model.predict(test_input)
utils.save_samples(logdir, predictions, epoch, rev_rna_vocab, annotated=False)
'''
load data
'''
Train = True
validate = True
data = ohe_sequences
if validate:
split = len(data) // 10
# print(split)
valid_data = data[:split]
train_data = data[split:]
if len(train_data) == 1: train_data = train_data[0]
if len(valid_data) == 1: valid_data = valid_data[0]
else:
train_data = data
train_data = train_data.astype('float32')
valid_data = valid_data.astype('float32')
train_seqs = tf.data.Dataset.from_tensor_slices(train_data).shuffle(len(train_data)).batch(BATCH_SIZE)
valid_seqs = tf.data.Dataset.from_tensor_slices(valid_data).shuffle(len(valid_data)).batch(split)
plot_iter = 10
current_learning_rate = LR
trace = True
n_critic_count = 0
d_losses = []
g_losses = []
gradient_penalties = []
iterations = 0
iteration_numbers = []
iteration_numbers_valid = []
d_validation_losses = []
random_name = time.strftime("%Y%m%d-%H%M%S")
gen_iters = 0
if Train:
sample_noise = tf.random.normal([BATCH_SIZE, DIM])
generate_and_save_samples(G, 0, [sample_noise], figure_size=(12,6), subplot=(3,6), save=False, is_flatten=False)
pbar = tqdm(range(EPOCHs))
for epoch in pbar:
start = time.time()
tdataset = train_seqs.enumerate()
for step, tdata in tdataset.as_numpy_iterator():
current_batch_size = tdata.shape[0]
d_loss, gp = WGAN_GP_train_d_step(tdata, batch_size=tf.constant(current_batch_size, dtype=tf.int64), step=tf.constant(step, dtype=tf.int64))
n_critic_count += 1
if n_critic_count >= CRITIC_ITERS:
g_loss, noise = WGAN_GP_train_g_step(tdata, batch_size= tf.constant(current_batch_size, dtype=tf.int64), step=tf.constant(step, dtype=tf.int64))
gen_iters += 1
n_critic_count = 0
if step % 10 == 0:
print ('.', end='')
if epoch % SAVE_EVERY_N_EPOCH == 0 and epoch != 0:
ckpt_save_path = ckpt_manager.save()
utils.save_checkpoints(logdir,G,epoch)
if epoch % 50 == 0:
generate_and_save_samples(G, epoch, [sample_noise], figure_size=(12,6), subplot=(3,6), save=True, is_flatten=False)
os.system('clear')
iteration_numbers.append(iterations)
g_losses.append(-g_loss)
d_losses.append(-d_loss)
gradient_penalties.append(gp)
# plot(iteration_numbers, d_losses, logdir, 'discriminator_loss', xlabel="Iteration", ylabel="Discriminator Cost")
# plot(iteration_numbers, g_losses, logdir, 'generator_loss', xlabel="Iteration", ylabel="Generator Cost")
# plot(iteration_numbers, gradient_penalties, logdir, 'gradient_penalty', xlabel="Iteration", ylabel="Gradient Penalty")
iterations+=1
iteration_numbers_valid.append(iterations)
fake_sample_valid = G([noise], training=True)
fake_pred_valid = D([fake_sample_valid], training=True)
real_pred_valid = D([tf.convert_to_tensor(list(valid_seqs.as_numpy_iterator())[0])], training=True)
D_loss_valid = tf.reduce_mean(fake_pred_valid) - tf.reduce_mean(real_pred_valid)
d_validation_losses.append(-D_loss_valid)
# plot_valid(iteration_numbers_valid, d_validation_losses, iteration_numbers, d_losses, logdir, 'validation_loss', xlabel="Iteration", ylabel="D Validation Loss")
ckpt_save_path = ckpt_manager.save()
print ('Saving checkpoint for epoch {} at {}'.format(EPOCHs,
ckpt_save_path))
print("####################################################")
print(f"############### Gen Iterations : {gen_iters} #####")
print("####################################################")