CoolFace
Datasetpublic

nancyH/token_evaluation

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes1.4kdownloads
tok_split_full_ablation.py156 linesDownload Raw Back to root
1import os2import random3from os.path import join4from collections import Counter5import numpy as np6import pysam7from tokenizers import Tokenizer8from tokenizers.models import BPE9from tokenizers.trainers import BpeTrainer10from tokenizers.pre_tokenizers import PreTokenizer11from tokenizers.pre_tokenizers import ByteLevel12from tokenizers.pre_tokenizers import Whitespace13from tokenizers.pre_tokenizers import CharDelimiterSplit14from tokenizers.normalizers import Sequence, Lowercase15from tokenizers import models, pre_tokenizers, decoders16from tokenizers.pre_tokenizers import Split17 18 19def writetsv(data, label, savefile):20    with open(savefile, 'w') as f:21        f.write('sequence\tlabels\n')22        for seq, lab in zip(data, label):23            f.write(f'{seq}\t{lab}\n')24 25 26def nonoverlap_split(tokens, maxlen, tolerance=0.5):27    seqs = []28    skipped = 029 30    num_windows = len(tokens) // maxlen31 32    for i in range(num_windows):33        window = tokens[i*maxlen:(i+1)*maxlen]34 35        # NEW: token-aware N detection36        num_N = sum('N' in tok for tok in window)37 38        if num_N / maxlen < tolerance:39            seqs.append(" ".join(window))40        else:41            skipped += 142 43    print(f"In this chromosome, skipped sequences: {skipped}")44    return seqs45 46 47def tokenize_full_sequence_collect(tokenizer, sequence, chunk_size=1_000_000):48    raw_tokens = []49 50    for i in range(0, len(sequence), chunk_size):51        chunk = sequence[i:i + chunk_size]52        encoded = tokenizer.encode(chunk)53        raw_tokens.extend(encoded.tokens)54 55        if i % (10 * chunk_size) == 0:56            print(f"Processed {i:,} bp")57 58    return raw_tokens59 60maxlen = 51261tolerance = 0.562CHUNK_SIZE = 1_000_00063fasta_path = '/home/n5huang/dna_token/hg38.fa'64args_token_path = '/home/n5huang/dna_token/output_tokens'65os.makedirs(args_token_path, exist_ok=True)66 67# Set to a list like ["chr1", "chr2"] to limit processing.68CHROMOSOMES = None69EXCLUDE_CHROMS = set()70 71 72# --- ABLATION TOKENIZERS ---73VOCAB_PATHS = {74    "ablation_no_partition": "/home/n5huang/dna_token/tokenizer_evaluation/ablation/vocab_5120/ablation_no_partition.json",75    "ablation_no_priority":  "/home/n5huang/dna_token/tokenizer_evaluation/ablation/vocab_5120/ablation_no_priority.json",76    "ablation_no_length":    "/home/n5huang/dna_token/tokenizer_evaluation/ablation/vocab_5120/ablation_no_length.json",77}78 79tokenizers = {}80for name, path in VOCAB_PATHS.items():81    tokenizers[name] = Tokenizer.from_file(path)82 83 84with pysam.FastaFile(fasta_path) as genome:85    chroms = genome.references if CHROMOSOMES is None else CHROMOSOMES86    chroms = [c for c in chroms if c not in EXCLUDE_CHROMS]87 88    for tok_name, tok in tokenizers.items():89        print(tok.pre_tokenizer)90        print(tok.model)91 92        print(f"\n=== Processing tokenizer: {tok_name} ===")93 94        all_seqs = []95        all_labels = []96 97        for chrm in chroms:98            full_sequence = genome.fetch(reference=chrm)99 100            print(f"\nChromosome: {chrm}")101            print(f"Total length: {len(full_sequence):,} bases")102            print(f"First 100 bases:\n{full_sequence[:100]}")103 104            # 1. Tokenize full chromosome105            raw_tokens = tokenize_full_sequence_collect(106                tok,107                full_sequence,108                chunk_size=CHUNK_SIZE109            )110            print(f"Total raw tokens: {len(raw_tokens):,}")111 112            # 2. Build sequences113            final_seqs = nonoverlap_split(114                tokens=raw_tokens,115                maxlen=maxlen,116                tolerance=tolerance117            )118 119            print(f"Total sequences for pretrain: {len(final_seqs):,}")120 121            all_seqs.extend(final_seqs)122            all_labels.extend([chrm] * len(final_seqs))123 124        if not all_seqs:125            print(f"No sequences generated for tokenizer: {tok_name}")126            continue127 128        # 3. Shuffle129        combined = list(zip(all_seqs, all_labels))130        random.seed(42)131        random.shuffle(combined)132        shuffle_data, shuffle_labels = zip(*combined)133 134        # 4. Train / Val split135        train_num = int(0.9 * len(shuffle_data))136 137        train_data = shuffle_data[:train_num]138        train_labels = shuffle_labels[:train_num]139        val_data = shuffle_data[train_num:]140        val_labels = shuffle_labels[train_num:]141 142        # 5. Save TSVs143        train_path = join(144            args_token_path,145            f"{tok_name}_allchr_all_tokenized_train.tsv"146        )147        val_path = join(148            args_token_path,149            f"{tok_name}_allchr_all_tokenized_val.tsv"150        )151 152        writetsv(train_data, train_labels, train_path)153        writetsv(val_data, val_labels, val_path)154 155        print(f"Saved:\n  {train_path}\n  {val_path}")156