| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| """AlphaGenome finetuning example script. |
| |
| This script demonstrates how to finetune the AlphaGenome model on custom genomic data, suitable for the following scenarios: |
| - ATAC-seq/ChIP-seq signal prediction for new cell types or tissues |
| - Adaptation to specific experimental data |
| - Transfer learning to new species |
| |
| Data requirements: |
| - Reference genome FASTA file |
| - BigWig signal track files pointed to by file_path in metadata |
| - Training regions CSV file (columns: chromosome, start, end) |
| |
| Usage: |
| python run_finetuning.py \ |
| --fasta_path /path/to/GRCh38.fa \ |
| --regions_csv /path/to/regions.csv \ |
| --output_dir ./finetuned_model \ |
| --num_steps 1000 \ |
| --batch_size 2 |
| """ |
|
|
| import pathlib |
| import sys |
|
|
| _PROJECT_ROOT = pathlib.Path(__file__).resolve().parents[1] |
| _SRC_DIR = _PROJECT_ROOT / "src" |
| if str(_SRC_DIR) not in sys.path: |
| sys.path.insert(0, str(_SRC_DIR)) |
|
|
| from absl import app |
| from absl import flags |
| from absl import logging |
|
|
| from alphagenome._sdk.data import fold_intervals |
| from alphagenome._sdk.models import dna_model as dna_model_types |
| import jax |
| import optax |
| import orbax.checkpoint as ocp |
|
|
| from alphagenome.finetuning.finetune import ( |
| get_dataset_iterator, |
| get_forward_fn, |
| get_train_step, |
| ) |
| from alphagenome.evals.track_prediction import load_model as load_model_from_kaggle |
| from alphagenome.model.metadata import metadata as metadata_lib |
|
|
| FLAGS = flags.FLAGS |
|
|
| flags.DEFINE_string( |
| 'fasta_path', |
| None, |
| 'Reference genome FASTA path.', |
| required=True, |
| ) |
| flags.DEFINE_string( |
| 'regions_csv', |
| None, |
| 'Training regions CSV path with chromosome,start,end columns.', |
| required=True, |
| ) |
| flags.DEFINE_list( |
| 'bigwig_paths', |
| None, |
| 'Deprecated compatibility flag. BigWig paths are read from metadata ' |
| 'file_path columns.', |
| ) |
| flags.DEFINE_string( |
| 'model_dir', |
| None, |
| 'Pretrained checkpoint directory. If unset, Kaggle Hub is used.', |
| ) |
| flags.DEFINE_string( |
| 'output_dir', |
| './finetuned_model', |
| 'Directory to save finetuned checkpoints.', |
| ) |
| flags.DEFINE_integer('num_steps', 1000, 'Number of training steps.') |
| flags.DEFINE_integer('batch_size', 2, 'Training batch size.') |
| flags.DEFINE_float('learning_rate', 1e-5, 'Initial learning rate.') |
| flags.DEFINE_integer('log_every', 50, 'Log interval in steps.') |
| flags.DEFINE_integer('save_every', 200, 'Checkpoint interval in steps.') |
| flags.DEFINE_enum( |
| 'model_version', 'FOLD_0', |
| ['FOLD_0', 'FOLD_1', 'FOLD_2', 'FOLD_3', 'FOLD_4'], |
| 'Pretrained model version.', |
| ) |
| flags.DEFINE_enum( |
| 'organism', 'HOMO_SAPIENS', |
| ['HOMO_SAPIENS', 'MUS_MUSCULUS'], |
| 'Target organism.', |
| ) |
|
|
|
|
| def _resolve_local_model_dir(path: str) -> pathlib.Path: |
| model_dir = pathlib.Path(path).expanduser() |
| if not model_dir.is_dir(): |
| raise FileNotFoundError( |
| f'Pretrained checkpoint directory does not exist: {model_dir}' |
| ) |
| return model_dir |
|
|
|
|
| def _load_pretrained_state(model_version: dna_model_types.ModelVersion): |
| if FLAGS.model_dir: |
| checkpoint_path = _resolve_local_model_dir(FLAGS.model_dir) |
| logging.info('Loading pretrained model from local checkpoint: %s', |
| checkpoint_path) |
| return ocp.StandardCheckpointer().restore(str(checkpoint_path)) |
|
|
| logging.info('Loading pretrained model from Kaggle Hub: %s', |
| model_version.name) |
| params, state, _ = load_model_from_kaggle(model_version) |
| return params, state |
|
|
|
|
| def main(_): |
| output_dir = pathlib.Path(FLAGS.output_dir) |
| output_dir.mkdir(parents=True, exist_ok=True) |
|
|
| model_version = dna_model_types.ModelVersion[FLAGS.model_version] |
| organism = dna_model_types.Organism[FLAGS.organism] |
|
|
| logging.info('JAX devices: %s', jax.devices()) |
| logging.info('Finetuning config: lr=%.2e, steps=%d, batch_size=%d', |
| FLAGS.learning_rate, FLAGS.num_steps, FLAGS.batch_size) |
|
|
| |
| params, state = _load_pretrained_state(model_version) |
|
|
| |
| output_metadata = metadata_lib.load(organism) |
|
|
| |
| schedule = optax.warmup_cosine_decay_schedule( |
| init_value=0.0, |
| peak_value=FLAGS.learning_rate, |
| warmup_steps=100, |
| decay_steps=FLAGS.num_steps, |
| ) |
| optimizer = optax.chain( |
| optax.clip_by_global_norm(1.0), |
| optax.adam(learning_rate=schedule), |
| ) |
| opt_state = optimizer.init(params) |
|
|
| |
| forward = get_forward_fn({organism: output_metadata}) |
| train_step = get_train_step( |
| predict_fn=forward.apply, |
| optimizer=optimizer, |
| ) |
|
|
| |
| logging.info('Building finetuning dataset iterator...') |
| dataset_iter = get_dataset_iterator( |
| batch_size=FLAGS.batch_size, |
| sequence_length=1_048_576, |
| output_metadata=output_metadata, |
| model_version=model_version, |
| subset=fold_intervals.Subset.TRAIN, |
| organism=organism, |
| fasta_path=FLAGS.fasta_path, |
| example_regions_path=FLAGS.regions_csv, |
| ) |
|
|
| |
| checkpointer = ocp.CheckpointManager( |
| output_dir / 'checkpoints', |
| options=ocp.CheckpointManagerOptions(max_to_keep=3), |
| ) |
|
|
| |
| logging.info('Starting finetuning training...') |
| for step, batch in enumerate(dataset_iter): |
| if step >= FLAGS.num_steps: |
| break |
|
|
| params, state, opt_state, metrics = train_step( |
| params, state, opt_state, batch |
| ) |
|
|
| if step % FLAGS.log_every == 0: |
| loss = float(metrics.get('loss', float('nan'))) |
| logging.info('Step %d/%d | loss=%.4f', step, FLAGS.num_steps, loss) |
|
|
| if step % FLAGS.save_every == 0 and step > 0: |
| checkpointer.save(step, args=ocp.args.StandardSave({'params': params, 'state': state})) |
| logging.info('Checkpoint saved (step=%d)', step) |
|
|
| |
| checkpointer.save( |
| FLAGS.num_steps, |
| args=ocp.args.StandardSave({'params': params, 'state': state}), |
| ) |
| logging.info('Finetuning complete, final model saved to %s', output_dir / 'checkpoints') |
|
|
|
|
| if __name__ == '__main__': |
| app.run(main) |