BalanceVectors
Balances a labeled training-vector TSV (produced by VcfToTrainingVectors) into train/validation splits for neural-network training. Keeps all positives and performs stratified negative sampling so rare but difficult false positives are not drowned out by common easy ones. Sampling is spread across category axes — variant type crossed with depth, score, and event length — plus optional artifact axes (homopolymer run length, allele fraction, strand ratio, and mapping quality) where false positives concentrate. The remainder of the negative quota is filled with a representative random sample. All sampling and shuffling are deterministic given a seed.
Basic Usage
balancevectors.sh in=<vectors.tsv> outtrain=<file> outval=<file>
The input must be a tab-delimited vector file in the format produced by VcfToTrainingVectors, where the last column is a 0/1 label (1 = true variant, 0 = false positive). The tool writes two output files: a training split and a held-out validation split.
Sampling Strategy
Balancing proceeds in five steps, all deterministic given seed:
- Load and partition: All positives (label > 0.5) are kept in full. Negatives are separated for sampling.
- Target count: The number of negatives to select is chosen so that positives represent
posfractionof the final output (default 30%). - Enriched negatives: A per-category quota is drawn across existing axes (variant type × depth, score, event length; plus depth alone). If
newcats=t, additional artifact axes (type × homopolymer run, allele fraction bins, strand ratio bins, mapping quality bins) are sampled atnewweighttimes the base quota. - Representative negatives: The remainder of the target is filled from a random sample of negatives not already selected by enrichment.
- Shuffle and split: Positives and chosen negatives are combined, globally shuffled, and split: the last
valfractionof rows go to the validation file and the rest to training.
Memory Management
BalanceVectors loads all input vectors into memory at once. Budget approximately 1.5× the input file size in heap. The default JVM allocation is 4 GB; override with -Xmx for large inputs (tens of millions of vectors).
Parameters
I/O Parameters
- in=<file>
- Input labeled vector TSV. The last column must be a 0/1 floating-point label. Produced by VcfToTrainingVectors. Compressed input is supported.
- outtrain=<file>
- (train) Output training split. Receives the larger portion of the balanced and shuffled data. If
valfraction=0the entire balanced set is written here. - outval=<file>
- (val, validate) Output validation split. Receives the last
valfractionof the shuffled balanced set. Used for evaluating the trained model without data leakage.
Balancing Parameters
- posfraction=0.3
- (ratio) Target fraction of positives in the balanced output. 0.3 means 30% true variants and 70% negatives. Must be strictly between 0 and 1. The actual negative count is derived as
pos_count × (1 − posfraction) / posfraction. - valfraction=0.1
- Fraction of the final balanced set held out as the validation split. 0.1 means 10% goes to
outvaland 90% toouttrain. Must be in [0, 1). - enrich=t
- When true, use stratified category sampling for negatives before filling the remainder randomly. When false, all negatives are drawn by simple random sampling with no category structure.
- newcats=t
- (artifactcats) When true, include the four artifact category axes — variant type × homopolymer run length, allele fraction bins, strand ratio bins, and mapping quality bins — in addition to the standard type/depth/score/event-length axes. These axes target regions where false positives concentrate. Sampled at
newweighttimes the base per-category quota. - newweight=0.3
- Fraction of the base per-category quota used when sampling the artifact axes (when
newcats=t). A value of 0.3 means artifact-axis categories are sampled at 30% of the rate of existing categories, keeping them a minority of the enriched set rather than equal weight. - quota=
- Override the automatically derived per-existing-category sample size. By default the quota is
(targetNeg / 2) / numCategories. Setting this explicitly forces a fixed sample from each category bucket regardless of category count. - noscore=t
- When true, the composite-score column (column index 29 in the VectorUMP45 33-feature layout) is replaced with 0 in both output files. This prevents the neural network from learning to copy the existing heuristic score rather than deriving its own features. Strongly recommended when training a new scoring model.
- seed=42
- Random seed for both the partial Fisher-Yates shuffles used during enriched category sampling and the full Fisher-Yates global shuffle before the train/val split. Given the same input and seed, the output is byte-for-byte reproducible.
Java Parameters
- -Xmx
- Set Java heap size, e.g.
-Xmx64g. Large inputs (tens of millions of vectors) require enough heap to hold all lines simultaneously; budget approximately 1.5× the uncompressed file size. The default allocation is 4 GB. - -eoom
- Exit on out-of-memory exception. Requires Java 8u92 or later. Recommended when running in automated pipelines so the process fails cleanly rather than hanging.
- -da
- Disable Java assertions. May improve throughput slightly in production, but assertions catch bugs during development and are left on by default.
Examples
Basic Balanced Split
# Balance a vector file and split into 90% train / 10% validation
balancevectors.sh in=variants.tsv outtrain=train.tsv outval=val.tsv
Uses all defaults: 30% positive target, 10% held out for validation, artifact category axes enabled, composite score zeroed, seed 42. Prints category counts, enriched negative count, representative fill count, and final positive fraction to stderr.
Higher Positive Fraction with Custom Seed
# 40% positives, 15% validation hold-out, reproducible with a different seed
balancevectors.sh in=variants.tsv outtrain=train.tsv outval=val.tsv \
posfraction=0.4 valfraction=0.15 seed=1234
Use a higher posfraction when the dataset has very few positives and you want to reduce the training imbalance further. A different seed is useful for cross-validation experiments to verify that results are not seed-dependent.
Simple Random Sampling Without Artifact Axes
# Disable stratified enrichment entirely for a flat random negative sample
balancevectors.sh in=variants.tsv outtrain=train.tsv outval=val.tsv enrich=f
# Enrichment on but artifact axes off (use only type/depth/score/length axes)
balancevectors.sh in=variants.tsv outtrain=train.tsv outval=val.tsv newcats=f
enrich=f turns off all stratified sampling; negatives are drawn uniformly at random. newcats=f keeps the standard enrichment axes but drops the four artifact axes, which reduces the number of category buckets and raises the per-bucket quota. Both options are useful baselines for ablation studies.
Algorithm Details
Category Axes
BalanceVectors builds category keys from the VectorUMP45 33-feature layout. Each negative can appear in multiple buckets simultaneously; the enrichment pass deduplicates chosen indices so a single vector is never double-counted.
Existing axes (always used when enrich=t):
- Type × depth: {SUB, INS, DEL, OTHER} × logarithmically binned read depth
- Type × score: {SUB, INS, DEL, OTHER} × composite-score bins (0–19)
- Type × event length: {SUB, INS, DEL, OTHER} × {len1, len2-5, len6-20, len20+}
- Depth alone: logarithmically binned depth without variant type
Artifact axes (used when newcats=t, sampled at newweight × base quota):
- Type × homopolymer: Slippage-prone sites; homopolymer run length encoded as 1/(run+1) and inverted
- Allele fraction: Bins {0–10%, 10–30%, 30–60%, 60%+}; low-VAF errors concentrate below 10%
- Strand ratio: Bins {0–10%, 10–30%, 30%+}; extreme strand bias indicates artifact
- Mapping quality: Bins {0–10, 10–20, 20–40, 40+}; low-MAPQ reads are enriched for false positives
Sampling Procedure
Within each category bucket the tool applies a partial Fisher-Yates shuffle (Knuth) to draw up to quota indices uniformly without replacement. Because each negative index can appear in many buckets, a global chosen[] boolean array ensures that the total enriched set contains distinct vectors. The representative fill then draws uniformly from all unchosen negatives using another partial shuffle, pinning the final positive fraction to posfraction.
Score Column Zeroing
With noscore=t (default), column 29 (the CallVariants composite score) is replaced with the literal character 0 on output. The zeroing is done at the byte level during the write pass — no floating-point parsing — so the remainder of each line is reproduced exactly. This is the recommended setting when training a replacement scoring model: the network cannot shortcut learning by copying a preexisting signal.
Related Tools
- CallVariants — Calls SNPs and indels from aligned reads; the variant call output feeds into VcfToTrainingVectors to produce the labeled vector files that BalanceVectors consumes.
- VcfToTrainingVectors — Converts a VCF and its associated BAM/SAM into the labeled TSV vector format that BalanceVectors expects as input.
Support
For questions and support:
- Email: bbushnell@lbl.gov
- Documentation: bbmap.org