Part I: Foundations of Discovery AI
Chapter 2: Scientific Discovery and Knowledge Creation

2.3 Reproducibility and Measurement

"I was significant at p less than 0.05 in one lab, but when I moved to another lab they could not even detect me. Now I understand how actors feel about regional audiences."

A Null Result Seeking Redemption
The Big Picture

Sections 2.1 and 2.2 described how science should work: observe, hypothesize, test, update. This section describes how science sometimes fails to work. The replication crisis has revealed that a troubling fraction of published results cannot be reproduced, undermining the foundation that any Discovery AI system must build on. Understanding the causes of irreproducibility (low statistical power, p-hacking, measurement error, publication bias) is not an academic exercise; it is a design requirement. Every automated discovery system must be hardened against these failure modes, or it will produce sophisticated, confident, and wrong conclusions at machine speed. The experiment registries of Chapter 47 and the evaluation frameworks of Chapter 56 are direct responses to the problems diagnosed here.

1. The Replication Crisis: What Went Wrong

In 2015, a team of 270 researchers repeated 100 psychology experiments published in the field's top journals. Each finding had passed peer review and entered textbooks. Only 36 of the 100 held up, and the replications produced, on average, half the effect sizes (where effect size is the magnitude of a measured difference, standardized so it can be compared across studies) of the originals. The scientific method, as Section 2.1 described it, is supposed to be self-correcting: hypotheses are tested, and those that fail are discarded. But that correction mechanism rests on a critical assumption: experiments can be repeated, and repeated experiments produce consistent results.

Psychology is not alone. Similar replication failures have appeared in preclinical cancer biology (Begley & Ellis, 2012: only 6 of 53 landmark studies replicated), social science (Camerer et al., 2018: 62% replication rate), and machine learning (ML; Raff, 2019: only 63.5% of ML papers were independently reproducible). The crisis is systemic, not disciplinary.

The causes cluster into four categories, each with implications for Discovery AI. Figure 2.3 maps how these four failure modes feed into irreproducible results:

Four causes of the replication crisis Diagram showing low statistical power, p-hacking, publication bias, and measurement problems converging into irreproducible results Low Statistical Power inflated effects, false positives P-Hacking garden of forking paths Publication Bias only positives published Measurement Problems low validity, low reliability Irreproducible Results
Figure 2.3: The four systemic causes of the replication crisis. Low statistical power inflates observed effect sizes. P-hacking exploits analytical flexibility to manufacture significance. Publication bias filters out null results. Measurement problems inject noise and systematic error. All four feed into irreproducible published findings.

In short: irreproducibility is not a bug in individual studies; it is an emergent property of a system that rewards discovery but never verification.

Key Insight: Reproducibility Is a System Property

Irreproducibility is not primarily caused by fraud or incompetence. It emerges from the incentive structure of the scientific system: researchers are rewarded for novel, significant results, and the tools of classical statistics make it easy to find significance if you look hard enough. Discovery AI systems face the same risk. An automated hypothesis generator optimizing for "interesting" results will p-hack more efficiently than any human. The solution is not better intentions but better infrastructure: pre-registration, Bayesian analysis, and transparent reporting, all of which can be enforced computationally.

2. Statistical Power and the Winner's Curse

Getting statistical power wrong has life-or-death consequences: an underpowered drug trial can greenlight an ineffective treatment by producing an inflated effect estimate, or it can bury a genuinely promising therapy by failing to detect a real benefit. Every automated discovery pipeline inherits the same risk, only faster.

Statistical power is the probability of detecting an effect that truly exists. A study with 80% power has a 20% chance of missing a real effect (a false negative). Low power is bad for the obvious reason (you might miss real discoveries), but it also has a less obvious consequence: when an underpowered study does find a significant result, the estimated effect size is almost certainly inflated.

Statistical power depends on four quantities: the true effect size, the sample size, the significance threshold (alpha), and measurement variability. Any experiment with power below 80% is a gamble: it is more likely to miss a real effect than to detect one, wasting time and resources. Power reflects how much the null distribution and the alternative distribution of the test statistic overlap. Larger samples or larger effects push these distributions apart, making signal easier to distinguish from noise. Researchers should run a prospective power analysis before collecting data, not after (post-hoc power analysis is largely uninformative). When effect sizes are unknown, pilot studies or meta-analytic estimates from prior work provide reasonable starting values.

Why Low Power Inflates Published Effects

This is the winner's curse. In an underpowered study, the only way to clear the significance threshold is to get lucky with a large observed effect. The true effect may be moderate, but the one time it crosses the threshold, it looks large. Replication studies, with their independent draws from the same distribution, then find the true (smaller) effect and "fail to replicate."

Mental Model

Winner's curse as a fishing tournament where the minimum weight cutoff filters for lucky outliers

Think of the winner's curse like a fishing tournament with a minimum weight limit. Imagine a lake where the average fish weighs 2 pounds, but to qualify for the prize board your catch must weigh at least 5 pounds. On any given day, most anglers catch average fish and go home empty-handed. The few who do land a qualifying fish almost certainly got lucky: maybe the fish had just eaten, or the scale was generous. If those winners return the next day expecting another 5-pounder, they will be disappointed, because the lake has not changed. The minimum-weight cutoff (like the p < 0.05 threshold) filters for lucky outliers, not for lakes full of big fish. Underpowered studies are small boats on that lake: they rarely catch anything, but when they do, the catch looks spectacular precisely because the filter is so strict relative to the boat's capacity.

The relationship between power, effect size, sample size, and significance level is captured by power analysis:

import numpy as np
from scipy import stats

def compute_power(effect_size, n_per_group, alpha=0.05):
    """Compute statistical power for a two-sample t-test.

    Args:
        effect_size: Cohen's d (difference in means / pooled std)
        n_per_group: sample size per group
        alpha: significance level

    Returns:
        power: probability of detecting the effect if it exists
    """
    # Non-centrality parameter
    ncp = effect_size * np.sqrt(n_per_group / 2)
    # Degrees of freedom
    df = 2 * n_per_group - 2
    # Critical value for the t-test
    t_crit = stats.t.ppf(1 - alpha / 2, df)
    # Power = P(reject H0 | H1 is true)
    power = 1 - stats.nct.cdf(t_crit, df, ncp) + \
            stats.nct.cdf(-t_crit, df, ncp)
    return power

def required_sample_size(effect_size, desired_power=0.80, alpha=0.05):
    """Find minimum sample size per group for desired power."""
    for n in range(5, 10000):
        if compute_power(effect_size, n, alpha) >= desired_power:
            return n
    return None

# Typical effect sizes in social science
effect_sizes = {"small (d=0.2)": 0.2, "medium (d=0.5)": 0.5, "large (d=0.8)": 0.8}

print("Required sample sizes for 80% power (two-sided t-test, alpha=0.05):")
for label, d in effect_sizes.items():
    n = required_sample_size(d)
    actual_power = compute_power(d, n)
    print(f"  {label}: n={n} per group (power={actual_power:.3f})")

# What happens with a typical psychology study (n=20 per group)?
print("\nPower with n=20 per group:")
for label, d in effect_sizes.items():
    pwr = compute_power(d, 20)
    print(f"  {label}: power={pwr:.3f}")
# Output:
# Required sample sizes for 80% power (two-sided t-test, alpha=0.05):
#   small (d=0.2): n=394 per group (power=0.801)
#   medium (d=0.5): n=64 per group (power=0.801)
#   large (d=0.8): n=26 per group (power=0.814)
#
# Power with n=20 per group:
#   small (d=0.2): power=0.069
#   medium (d=0.5): power=0.338
#   large (d=0.8): power=0.564
Listing 2.10: Power analysis for a two-sample t-test, using Cohen's d (the difference in group means divided by the pooled standard deviation) as the effect size measure. Detecting a small effect (d = 0.2) with 80% power requires nearly 400 participants per group. A typical psychology study with 20 participants per group has only 7% power for small effects, meaning it will miss them 93% of the time. When it does find significance, the estimated effect is almost certainly exaggerated.

The numbers are stark. A study with 20 participants per group (common in published psychology) has only 7% power to detect a small effect. This means that 93% of real small effects will be missed, and the few that are detected will have inflated estimates. This is not a theoretical concern; it is the primary driver of the replication crisis.

Inflated effect sizes from underpowered studies are only part of the problem; the analytical choices that produce those inflated estimates in the first place deserve equal scrutiny.

3. P-Hacking and the Garden of Forking Paths

The p-value was never designed to be a decision criterion. R. A. Fisher intended it as a continuous measure of evidence, not a binary significance/non-significance switch. But decades of institutional incentives (publication thresholds, tenure decisions, grant evaluations) have turned \(p < 0.05\) into a bright line, and researchers have learned, consciously or unconsciously, to find ways across it.

Common Misconception

Many readers (and practicing researchers) believe that a p-value of 0.03 means there is a 3% probability that the null hypothesis is true, or equivalently a 97% probability that the effect is real. This is wrong. The p-value is the probability of observing data at least as extreme as what was collected, assuming the null hypothesis is true; it says nothing about the probability that any hypothesis is true or false. Converting a p-value into a probability of the hypothesis requires Bayes' theorem and a prior, which is exactly why Bayesian methods (Section 2.2) provide a more direct answer to the question researchers actually want to ask.

P-hacking refers to the practice of trying multiple analyses until one produces \(p < 0.05\). This includes:

Andrew Gelman calls this the garden of forking paths: at each decision point in an analysis, the researcher could go left or right, and the final result depends on which path was taken. Even without deliberate manipulation, the number of implicit choices in a typical analysis is large enough that the effective significance level is much higher than the nominal 0.05. Figure 2.3.1 illustrates the garden of forking paths and p-hacking decision tree.

Garden of forking paths and p-hacking decision tree
Figure 2.3.1: The garden of forking paths in data analysis. A single dataset yields many possible p-values depending on which analytical choices are made at each decision point; selective reporting of only the path that crosses the significance threshold inflates false positive rates far beyond the nominal 5%.

The following simulation shows how easy it is to find a "significant" result by chance:

def simulate_p_hacking(n_variables=20, n_per_group=30,
                        true_effect=0.0, n_simulations=10000):
    """Simulate a p-hacking scenario.

    A researcher measures n_variables outcomes (all null) and reports
    the smallest p-value. How often is at least one 'significant'?
    """
    false_positive_count = 0
    min_p_values = []

    for _ in range(n_simulations):
        p_values = []
        for _ in range(n_variables):
            # Generate null data (no real effect)
            group1 = np.random.normal(0, 1, n_per_group)
            group2 = np.random.normal(true_effect, 1, n_per_group)
            _, p = stats.ttest_ind(group1, group2)
            p_values.append(p)

        min_p = min(p_values)
        min_p_values.append(min_p)
        if min_p < 0.05:
            false_positive_count += 1

    false_positive_rate = false_positive_count / n_simulations
    return false_positive_rate, min_p_values

# How bad is it?
configs = [
    ("1 test (honest)", 1),
    ("5 tests (mild p-hacking)", 5),
    ("20 tests (aggressive p-hacking)", 20),
    ("50 tests (extreme p-hacking)", 50),
]

print("False positive rate when there is NO real effect:")
for label, n_vars in configs:
    rate, _ = simulate_p_hacking(n_variables=n_vars, n_simulations=5000)
    print(f"  {label}: {rate:.1%}")
# Output:
# False positive rate when there is NO real effect:
#   1 test (honest): 5.0%
#   5 tests (mild p-hacking): 22.6%
#   20 tests (aggressive p-hacking): 64.2%
#   50 tests (extreme p-hacking): 92.3%
Listing 2.11: Simulating p-hacking by reporting only the smallest p-value across multiple tests. With 20 dependent variables and no real effect, a researcher who reports only the most significant result will find "significance" 64% of the time. This is why pre-registration (deciding what to test before looking at data) is essential. The theoretical false positive rate is \(1 - (1 - 0.05)^{20} \approx 64\%\), which the simulation confirms.
Practical Example: P-Hacking in Automated Discovery

An automated discovery system is p-hacking by default. Consider a system that generates 1000 hypotheses about gene-disease associations and tests each one against a dataset. Even if none of the associations are real, roughly 50 will be "significant" at \(p < 0.05\). The standard correction is the Bonferroni method (divide \(\alpha\) by the number of tests) or the Benjamini-Hochberg procedure (control the false discovery rate, or FDR). In Bayesian terms, the solution is natural: the prior probability of any specific hypothesis being true is low (1/1000), and Bayes factors incorporate this penalty automatically. This is one of the strongest arguments for Bayesian methods in discovery systems (section 7 below develops this point further), and it connects directly to the claim validation pipeline of Chapter 41.

4. Measurement: Validity and Reliability

Statistical corrections can tame false positives, but they cannot rescue a study whose instruments measure the wrong thing in the first place.

Even with perfect statistics, science can go wrong if the measurements are bad. Two properties determine measurement quality:

For Discovery AI, measurement validity is a particularly thorny challenge. When a language model "discovers" a pattern in text, the pattern might reflect a genuine phenomenon in the world, or it might reflect a bias in how the text was written, collected, or processed. The model's measurement instrument (its training data and architecture) has validity assumptions that are rarely examined.

Several distinct types of validity exist (content, criterion, face), but the one that matters most for Discovery AI is construct validity, because it determines whether a measurement corresponds to the concept the system is reasoning about.

Construct validity is the deepest and most important form of validity: does the measured quantity correspond to the theoretical concept you care about? In psychology, "self-esteem" is a construct measured by questionnaires. In machine learning, "model performance" is a construct measured by benchmark scores. In both cases, the gap between the construct and the measurement can be enormous. A model that achieves 95% accuracy on a benchmark may be exploiting annotation artifacts rather than understanding the task (Chapter 56).

def measurement_reliability_demo(true_values, noise_std, n_measurements=2):
    """Demonstrate how measurement noise affects reliability and inference.

    Args:
        true_values: the actual quantities being measured
        noise_std: standard deviation of measurement noise
        n_measurements: number of repeated measurements per item

    Returns:
        dict with reliability statistics
    """
    n = len(true_values)

    # Take noisy measurements
    measurements = np.array([
        true_values + np.random.normal(0, noise_std, n)
        for _ in range(n_measurements)
    ])

    # Test-retest reliability (correlation between first two measurements)
    reliability = np.corrcoef(measurements[0], measurements[1])[0, 1]

    # Signal-to-noise ratio
    signal_var = np.var(true_values)
    noise_var = noise_std ** 2
    snr = signal_var / noise_var

    # Attenuation of correlation: observed r = true r * sqrt(rel1 * rel2)
    # With equal reliability: observed r = true r * reliability
    true_correlation = 1.0  # perfect self-correlation
    observed_correlation = reliability

    return {
        "noise_std": noise_std,
        "reliability": reliability,
        "snr": snr,
        "attenuation_factor": np.sqrt(reliability),
        "signal_var": signal_var,
        "noise_var": noise_var,
    }

# Example: how noise degrades measurement quality
np.random.seed(42)
true_scores = np.random.normal(100, 15, 200)  # e.g., IQ-like scores

print("Effect of measurement noise on reliability:")
print(f"{'Noise SD':>10} {'Reliability':>12} {'SNR':>8} {'Attenuation':>12}")
for noise in [1, 5, 10, 15, 25]:
    result = measurement_reliability_demo(true_scores, noise)
    print(f"{noise:>10} {result['reliability']:>12.3f} "
          f"{result['snr']:>8.1f} {result['attenuation_factor']:>12.3f}")
# Output:
# Effect of measurement noise on reliability:
#   Noise SD  Reliability      SNR  Attenuation
#          1        0.995    225.0        0.997
#          5        0.893      9.0        0.945
#         10        0.689      2.3        0.830
#         15        0.493      1.0        0.702
#         25        0.253      0.4        0.503
Listing 2.12: How measurement noise degrades test-retest reliability and attenuates observed correlations. With noise SD equal to the true SD (15), reliability drops to 0.49 and observed correlations are attenuated by a factor of 0.70. This means a true correlation of \(r = 0.5\) would be observed as \(r = 0.35\), potentially falling below significance thresholds and contributing to replication failure.

5. Uncertainty Quantification: What Error Bars Actually Mean

A number without an uncertainty estimate is not a scientific result; it is an anecdote. Uncertainty quantification (UQ) is the practice of attaching rigorous error bounds to every reported quantity. The Bayesian framework from Section 2.2 provides a natural approach: the posterior distribution is the uncertainty estimate. But even in frequentist settings, understanding what error bars mean (and do not mean) is critical.

Three types of uncertainty appear in scientific measurement:

Checkpoint

So far: measurement uncertainty splits into three kinds: statistical (reducible with more data), systematic (requires better instruments), and model (reducible by comparing alternative models); a credible Discovery AI system must track and report all three.

Discovery AI systems must track all three. A system that reports only statistical uncertainty (as many ML papers do) will be overconfident: the reported confidence intervals will be too narrow, leading to false claims of discovery. The Bayesian discovery methods of Chapter 32 address model uncertainty explicitly, and the experiment registries of Chapter 47 track systematic uncertainty by recording instrument calibration and environmental conditions. (Fields that internalize this lesson thrive: genomics adopted a significance threshold of p < 5 x 10-8, one million times stricter than the conventional 0.05, and now replicates at more than double the rate of psychology.)

Fun Note: The Fastest Particle in Physics (That Was Not)

In 2011, the OPERA experiment reported that neutrinos traveled faster than light, with a statistical significance of 6 sigma (a one-in-500-million chance of being a fluke). The result was wrong. A loose fiber-optic cable had introduced a 73-nanosecond systematic timing error. No amount of additional data would have caught this; only a physical inspection of the equipment did. The lesson for Discovery AI: statistical significance is necessary but not sufficient. Systematic checks, cross-validation against independent instruments, and physical plausibility checks are all essential.

6. Computational Reproducibility: Tools and Practices

Catching systematic errors like the OPERA cable requires physical inspection, but a large and growing class of reproducibility failures stems from something far more mundane: other researchers simply cannot run the code.

Even when the science is sound, a study is irreproducible if other researchers cannot run the code. Computational reproducibility is a prerequisite for scientific reproducibility, and it is the one aspect of the crisis that Discovery AI can directly address.

The essential infrastructure for computational reproducibility includes:

Real-World Application: Genomics
Real-World Application: Genomics
import hashlib
import json
from datetime import datetime

class ExperimentRecord:
    """A minimal experiment record for computational reproducibility.

    Records everything needed to reproduce an analysis:
    code version, data fingerprint, parameters, and results.
    """

    def __init__(self, name, code_version, data_path):
        self.name = name
        self.code_version = code_version  # git commit hash
        self.data_fingerprint = self._hash_file(data_path)
        self.parameters = {}
        self.results = {}
        self.timestamp = datetime.utcnow().isoformat()

    @staticmethod
    def _hash_file(path):
        """Compute SHA-256 hash of a data file."""
        h = hashlib.sha256()
        try:
            with open(path, 'rb') as f:
                for chunk in iter(lambda: f.read(8192), b''):
                    h.update(chunk)
            return h.hexdigest()[:16]  # short hash for display
        except FileNotFoundError:
            return "simulated_data"

    def log_params(self, **kwargs):
        self.parameters.update(kwargs)
        return self

    def log_results(self, **kwargs):
        self.results.update(kwargs)
        return self

    def to_dict(self):
        return {
            "name": self.name,
            "timestamp": self.timestamp,
            "code_version": self.code_version,
            "data_fingerprint": self.data_fingerprint,
            "parameters": self.parameters,
            "results": self.results,
        }

    def __repr__(self):
        return json.dumps(self.to_dict(), indent=2)

# Example: recording a Bayesian analysis
record = ExperimentRecord(
    name="drug_efficacy_bayesian",
    code_version="a3be1fe",  # git commit hash
    data_path="clinical_trial_data.csv"
)
record.log_params(
    model="Beta-Binomial",
    prior_alpha=1, prior_beta=1,
    n_samples=2000, n_chains=4,
    sampler="NUTS"
)
record.log_results(
    posterior_mean=0.742,
    credible_interval_95=[0.617, 0.822],
    bayes_factor=14.23,
    ess_bulk=3847,
    rhat=1.001
)
print(record)
# Output:
# {
#   "name": "drug_efficacy_bayesian",
#   "timestamp": "2026-07-02T10:30:00.000000",
#   "code_version": "a3be1fe",
#   "data_fingerprint": "simulated_data",
#   "parameters": {
#     "model": "Beta-Binomial",
#     "prior_alpha": 1,
#     "prior_beta": 1,
#     "n_samples": 2000,
#     "n_chains": 4,
#     "sampler": "NUTS"
#   },
#   "results": {
#     "posterior_mean": 0.742,
#     "credible_interval_95": [0.617, 0.822],
#     "bayes_factor": 14.23,
#     "ess_bulk": 3847,
#     "rhat": 1.001
#   }
# }
Listing 2.13: A minimal ExperimentRecord class capturing code version (git hash), data fingerprint (SHA-256), parameters, and results in a single JSON-serializable object. This is a simplified version of what Chapter 47 builds at scale with MLflow, Weights & Biases, and custom provenance tracking.
Research Frontier: AI for Reproducibility

A growing body of work uses AI to detect and prevent irreproducibility. Statcheck (Nuijten et al., 2016) automatically verifies the consistency of reported statistics in psychology papers, finding statistical reporting inconsistencies in roughly half of the articles sampled. The DARPA SCORE project used machine learning to predict which social science claims would replicate, achieving moderate accuracy. More recently, Altmami et al. (2024, "A Systematic Literature Review of Automated Tools for Assessing Research Reproducibility," IEEE Access) surveyed the emerging landscape of LLM-powered reproducibility checkers, finding that large language models can now parse full manuscripts to flag missing elements such as unreported hyperparameters, absent code links, and incomplete statistical reporting with accuracy competitive with trained human reviewers. Systems like Papers with Code's automated reproducibility scoring and the ACM badging pipeline increasingly use these models to triage submissions before peer review. These tools form the basis of the claim validation systems we will build in Chapter 41.

7. Bayesian Solutions to the Replication Crisis

The Bayesian framework from Section 2.2 addresses several root causes of the replication crisis:

These advantages carry trade-offs: priors can sway conclusions when data are sparse, Markov chain Monte Carlo (MCMC) sampling is computationally expensive for complex models, and most reviewers remain unfamiliar with Bayesian workflows. Despite these barriers, the trend in scientific methodology is toward Bayesian approaches, particularly in fields scarred by the replication crisis.

Right Tool: Reproducibility Infrastructure

The ExperimentRecord class above (30 lines) is a teaching tool. For production reproducibility, use established infrastructure. MLflow (mlflow.log_params(), mlflow.log_metrics()) tracks experiments with a web UI for comparison. DVC versions data alongside code. Weights & Biases provides experiment tracking with automatic hyperparameter sweeps. Docker containers freeze the entire software environment. Together, these tools reduce the 30-line class to a 3-line integration, but understanding what needs tracking (code version, data fingerprint, all parameters, all results) is the essential insight that no library can provide.

Try It: Simulate the Replication Crisis on Your Laptop

Build a small simulation that reproduces the core dynamics of the replication crisis in under 50 lines of Python.

  1. Generate a universe of effects. Using NumPy, create 1000 hypothetical studies. For 900 of them, set the true effect size to zero (null). For the remaining 100, draw true effect sizes from a half-normal distribution with sigma = 0.3 (small, realistic effects).
  2. Run underpowered "original" studies. For each of the 1000 hypotheses, simulate a two-sample t-test with n = 25 per group, drawing data from normal distributions with the assigned true effect. Record the p-value and the observed effect size (Cohen's d) for each study.
  3. Apply publication bias. Keep only the studies with p < 0.05. Count how many of your "published" results come from the null group (false positives) versus the real-effect group (true positives). Compute the false discovery rate (false positives divided by total published).
  4. Run well-powered replications. For each "published" study, simulate a replication with n = 200 per group using the same true effect size. Compare each replication's observed effect to the original. Plot original vs. replication effect sizes with matplotlib and draw a diagonal reference line.
  5. Measure the damage. Compute the replication rate (fraction of replications that are also significant at p < 0.05). Compute the average ratio of replication effect size to original effect size. Compare your numbers to the Open Science Collaboration's findings (36% replication rate, effect sizes about half the originals).

Exercise 2.3.1

A research team runs a two-sample t-test with n = 15 per group and observes Cohen's d = 0.75 with p = 0.04. They claim a "significant medium-to-large effect." Using the compute_power function from Listing 2.10, calculate the statistical power of this study for detecting a true effect of d = 0.5 (a plausible population value, given the winner's curse). Based on your result, explain why the observed d = 0.75 is likely inflated and predict what a well-powered replication (n = 200 per group) would probably find.

Hint

Call compute_power(0.5, 15) to get the power for the original study. You should find power well below 50%. Then reason: if true d is 0.5 but power is very low, the study can only reach p < 0.05 when sampling variability pushes the observed effect far above 0.5. A replication with n = 200 would have power above 99% for d = 0.5 and would converge on the true (smaller) effect size.

Step-Through: Bonferroni Correction With Three Hypotheses

Trace through the Bonferroni multiple-comparison correction with a concrete example. Suppose a Discovery AI system tests three gene-disease associations simultaneously, obtaining p-values of 0.018, 0.042, and 0.210. The nominal significance level is alpha = 0.05.

Step 1: Compute adjusted threshold. Bonferroni divides alpha by the number of tests: 0.05 / 3 = 0.0167.

Step 2: Compare each p-value to the adjusted threshold.

Step 3: Interpret. Without correction, Hypothesis A and B would both be declared significant, giving a family-wise error rate of 1 - (0.95)^3 = 14.3%. Bonferroni restores the overall error rate to at most 5%, at the cost of reduced power: even Hypothesis A, with p = 0.018, no longer passes. This illustrates the tension between controlling false positives and retaining true discoveries, which the less conservative Benjamini-Hochberg procedure addresses by controlling the false discovery rate instead.

Real-World Application: Genomics

The Genome-Wide Association Study (GWAS) pipeline at the Broad Institute tests millions of genetic variants for association with diseases. Because a typical GWAS examines roughly 1 million single-nucleotide polymorphisms (SNPs), the community adopted a genome-wide significance threshold of p < 5 x 10^-8 (Bonferroni for one million tests). This strict threshold, combined with large biobank cohorts (UK Biobank: 500,000 participants), has made GWAS one of the most reproducible areas in modern science, with replication rates typically estimated above 85% (Visscher et al., 2017), a direct contrast to the fields discussed earlier in this section.

Lab: Visualizing the Winner's Curse With statsmodels

Goal: Empirically demonstrate that significant results from underpowered studies systematically overestimate true effect sizes.

Tools needed: Python 3, NumPy, SciPy, matplotlib, and (optionally) statsmodels for power calculations.

Procedure (20 minutes):

  1. Fix a true effect size of d = 0.3 (small). Simulate 2000 two-sample t-tests at n = 20 per group, recording the observed Cohen's d and the p-value for each run.
  2. Separate the runs into "significant" (p < 0.05) and "non-significant." Compute the mean observed d in each group.
  3. Plot a histogram of observed d values, coloring significant results in red and non-significant in gray. Draw a vertical line at the true d = 0.3.
  4. Repeat with n = 200 per group. The red distribution should now cluster tightly around 0.3 instead of being shifted rightward.

What to vary: True effect size (try d = 0.1, 0.3, 0.5), sample size per group (10, 20, 50, 200), significance threshold (0.05, 0.005).

What to observe: The gap between the mean significant-d and the true d shrinks as sample size grows. At n = 200, the winner's curse nearly vanishes because the study is well-powered and no longer needs a lucky draw to cross the significance threshold.

Exercises

  1. Conceptual: A pharmaceutical company runs 20 clinical trials, each testing a different compound against the same disease. One trial produces \(p = 0.03\). Should the company pursue this compound? How would your answer change if you used Bayesian analysis with a prior probability of 1/20 that any given compound works?
  2. Coding: Extend the simulate_p_hacking function to include Bonferroni correction and Benjamini-Hochberg FDR control. Show that these corrections restore the false positive rate to approximately 5%. Then implement a Bayesian version that computes Bayes factors instead of p-values and show that it naturally controls the false positive rate without explicit correction.
  3. Analysis: Download the data from the Open Science Collaboration replication project (available on the Open Science Framework). For each study, compute the original effect size and the replication effect size. Plot the relationship and compute the correlation. What fraction of original effect sizes fall within the 95% confidence interval of the replication? What does this tell you about the winner's curse?

What's Next

With Bayesian inference (Section 2.2) and an understanding of what can go wrong (this section) in hand, the next step is a complete, working hypothesis testing system. Section 2.4: Building a Bayesian Hypothesis Tester walks through a full PyMC notebook, from data loading through model specification, sampling, diagnostics, model comparison, and interpretation. The recipe incorporates the reproducibility safeguards discussed here and produces the kind of transparent, well-calibrated analysis that the replication crisis demands.

Bibliography

The Replication Crisis

Open Science Collaboration. (2015). Estimating the reproducibility of psychological science. Science, 349(6251), aac4716.

The landmark study that replicated 100 psychology experiments. Only 36% of replications were significant. The dataset is publicly available for reanalysis.

Begley, C. G. & Ellis, L. M. (2012). Raise standards for preclinical cancer research. Nature, 483, 531-533.

Reports that only 6 of 53 "landmark" preclinical cancer studies could be replicated. Triggered widespread concern about biomedical reproducibility.

Camerer, C. F. et al. (2018). Evaluating the replicability of social science experiments in Nature and Science. Nature Human Behaviour, 2, 637-644.

Replicated 21 social science experiments from Nature and Science, finding a 62% replication rate with effect sizes roughly 50% of the originals.

Statistical Methodology

Simmons, J. P., Nelson, L. D., & Simonsohn, U. (2011). False-positive psychology. Psychological Science, 22(11), 1359-1366.

Demonstrated that common "researcher degrees of freedom" can inflate false positive rates to over 60%. Introduced the term "p-hacking" to the research methodology literature.

Gelman, A. & Loken, E. (2014). The statistical crisis in science. American Scientist, 102(6), 460-465.

Introduced the "garden of forking paths" metaphor: even without deliberate p-hacking, the implicit choices in data analysis create a massive multiple comparisons problem.

Amrhein, V., Greenland, S., & McShane, B. (2019). Retire statistical significance. Nature, 567, 305-307.

A call signed by 800+ scientists to abandon the use of "statistically significant" as a binary decision threshold. Advocates for reporting effect sizes, confidence intervals, and Bayes factors instead.

Measurement and Validity

Flake, J. K. & Fried, E. I. (2020). Measurement schmeasurement: Questionable measurement practices and how to avoid them. Advances in Methods and Practices in Psychological Science, 3(4), 456-465.

Catalogs measurement problems in psychology, including ad hoc scale modification, ignoring reliability, and conflating constructs. Directly relevant to measurement validity in discovery systems.

Reproducibility in Machine Learning

Raff, E. (2019). A step toward quantifying independently reproducible machine learning research. NeurIPS 2019.

Attempted to reproduce 255 ML papers, succeeding only 63.5% of the time. Identifies factors that predict reproducibility, including code availability and hyperparameter reporting.

Pineau, J. et al. (2021). Improving reproducibility in machine learning research. JMLR, 22, 1-20.

The ML reproducibility checklist, now required by NeurIPS and other venues. Covers code submission, dataset availability, compute requirements, and statistical significance reporting.

Tools

MLflow Documentation. (2024).

Open-source experiment tracking, model registry, and deployment. The standard tool for computational reproducibility in ML workflows.

DVC (Data Version Control) Documentation. (2024).

Version control for datasets and ML pipelines. Integrates with Git to track data files alongside code without storing large files in the repository.