Setting Probabilities for Transforms in Augmentation Pipelines ๐
Each augmentation in Albumentations has a parameter named p that controls the probability of applying that augmentation to input data. Understanding how probabilities work is essential for creating effective and predictable augmentation pipelines.
Quick Reference ๐
Key Concepts:
p=1.0: Transform is always considered for applicationp=0.0: Transform is never considered for applicationp=0.5: Transform has a 50% chance of being considered- Pipeline probability: Overall chance the entire pipeline runs
- Nested probabilities: How probabilities combine in composition blocks like
OneOf
Basic Probability Mechanics ๐
Individual Transform Probability ๐
Setting p=1 means the transform will always be considered for application, while p=0 means it will never be considered. A value between 0 and 1 represents the chance it will be considered.
Some transforms default to p=1, while others default to p=0.5. Since default values can vary, it is recommended to explicitly set the p value for each transform in your pipeline to ensure clarity and avoid unexpected behavior.
Probability in Practice ๐
import albumentations as A
import numpy as np
# Create a simple example
transform = A.Compose([
A.HorizontalFlip(p=0.5), # 50% chance to flip
A.RandomBrightnessContrast(p=0.8), # 80% chance to adjust brightness/contrast
A.GaussianBlur(p=0.3), # 30% chance to blur
])
# Each transform runs independently based on its p value
image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
transformed = transform(image=image)
Complex Probability Example ๐
Let's examine a more complex pipeline to understand how probabilities interact:
import albumentations as A
import numpy as np
# Define probabilities for clarity
prob_pipeline = 0.95
prob_rotate = 0.85
prob_oneof_noise = 0.75
# Define the augmentation pipeline
transform = A.Compose([
A.RandomRotate90(p=prob_rotate), # 85% chance to be considered
A.OneOf([
A.GaussNoise(p=0.9), # 90% weight within OneOf block
A.ISONoise(p=0.7), # 70% weight within OneOf block
], p=prob_oneof_noise) # 75% chance for OneOf block to run
], p=prob_pipeline, # 95% chance for entire pipeline to run
seed=137) # Seed for reproducibility
# Apply the transform
image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
transformed = transform(image=image)
transformed_image = transformed['image']
print("Transformation applied:", not np.array_equal(image, transformed_image))
How Different Probability Levels Work ๐
Pipeline Probability (prob_pipeline) ๐
The p parameter in A.Compose determines if any augmentations within it are applied:
p=0.0: Pipeline never runs, input is always returned unchangedp=1.0: Pipeline always runs, inner transforms get a chance based on their own probabilities0 < p < 1: Pipeline runs with that specific probability
In our example (prob_pipeline = 0.95), the pipeline runs 95% of the time.
Individual Transform Probability (prob_rotate) ๐
Once the pipeline runs, each transform has its own probability:
RandomRotate90withp=0.85has an 85% chance of being applied- This is independent of other transforms in the pipeline
Composition Block Probability (prob_oneof_noise) ๐
Composition utilities like OneOf have their own probability layer:
OneOfblock withp=0.75has a 75% chance to run- If it runs, it executes exactly one of its contained transforms
Probability Calculations in OneOf ๐
How Selection Works ๐
When a OneOf block runs, it normalizes the probabilities of inner transforms to determine selection weights:
Example transforms in OneOf:
GaussNoise(p=0.9)ISONoise(p=0.7)
Normalization process:
- Sum of probabilities:
0.9 + 0.7 = 1.6 - Normalized probability for
GaussNoise:0.9 รท 1.6 = 0.5625(56.25%) - Normalized probability for
ISONoise:0.7 รท 1.6 = 0.4375(43.75%)
Selection Results ๐
If the OneOf block runs:
GaussNoiseis selected 56.25% of the timeISONoiseis selected 43.75% of the time
Overall Probability Calculations ๐
The actual probability of each transform being applied to the original image is the product of all probability layers:
Mathematical Breakdown ๐
| Transform | Calculation | Final Probability |
|---|---|---|
RandomRotate90 | 0.95 ร 0.85 | 80.75% |
GaussNoise | 0.95 ร 0.75 ร 0.5625 | 40.08% |
ISONoise | 0.95 ร 0.75 ร 0.4375 | 31.15% |
Formula Pattern ๐
Final Probability = Pipeline_p ร Block_p ร Normalized_Transform_p
Edge Cases: When p=1 Doesn't Change the Image ๐
Even when a transform is applied (p=1 or probability check succeeds), the image might not visually change in certain cases:
Identity Operations ๐
Transforms with identity operations in their selection:
RandomRotate90: Can select 0ยฐ rotation (no change)D4: Can select identity transformationRandomGridShuffle: Might shuffle back to original positions
Identity Parameter Sampling ๐
Geometric transforms can sample identity parameters:
Affine(rotate=(-10, 10)): Might sample rotation = 0ยฐShiftScaleRotate: Could sample shift=0, scale=1, rotate=0
Example:
# This always applies identity transformation
A.Affine(rotate=0, scale=1, translate_px=0, p=1)
# This might randomly sample identity parameters
A.Affine(rotate=(-10, 10), scale=(0.9, 1.1), p=1)
Key Point: The
pparameter controls whether a transform runs, but the transform's internal logic determines whether that execution visually changes the image.
Best Practices ๐
Probability Setting Guidelines ๐
- Be Explicit: Always set
pvalues explicitly rather than relying on defaults - Consider Independence: Remember that transform probabilities are independent within
Compose - Calculate Overall Effects: Use the multiplication rule to understand final probabilities
- Test Your Pipeline: Verify that your probability settings achieve the desired augmentation frequency
Common Patterns ๐
# Light augmentation (conservative)
light_transform = A.Compose([
A.HorizontalFlip(p=0.3),
A.RandomBrightnessContrast(p=0.2),
A.GaussianBlur(p=0.1),
])
# Moderate augmentation (balanced)
moderate_transform = A.Compose([
A.HorizontalFlip(p=0.5),
A.OneOf([
A.RandomBrightnessContrast(p=1.0),
A.HueSaturationValue(p=1.0),
], p=0.3),
A.GaussianBlur(p=0.2),
])
# Heavy augmentation (aggressive)
heavy_transform = A.Compose([
A.HorizontalFlip(p=0.7),
A.RandomBrightnessContrast(p=0.6),
A.OneOf([
A.GaussianBlur(p=1.0),
A.MedianBlur(p=1.0),
A.MotionBlur(p=1.0),
], p=0.4),
])
Where to Go Next? ๐
Understanding probabilities is crucial for controlling your augmentation pipelines. Now you can:
- Review Pipelines: See how probabilities function within different composition utilities like
Compose,OneOf,SomeOf, andSequential. - Visually Explore Transforms: Experiment with different augmentations, their parameters, and consider the impact of their
pvalues. - See Basic Usage Examples: Look at practical code applying pipelines with specific probabilities for different tasks.
- Learn How to Pick Augmentations: Get insights into choosing appropriate transforms and their probabilities.
- Understand Reproducibility: Learn how seeds interact with probabilities to ensure consistent results when needed. For custom transforms, also see Custom Transform Reproducibility.