Привет! С вами команда аналитиков "Пятёрочки" X5 Tech. В данной статье мы расскажем про один из классических тестов в статистике – тест Уэлча (Welch’s Test). Постараемся максимально раскрыть, когда и где стоит его применять и является ли он на самом деле тестом по умолчанию вместо t-test’a.
Т-test в первый раз
Легко представить стажёра, которому впервые дали рассчитать результаты Т-test двух выборок, заранее сказав, что все требования к тесту соблюдены. Немного самостоятельного поиска может навести его на метод scipy.stats.ttest_ind, где опционально можно изменить аргумент equal_var с True на False. И это как раз то место, где вероятен ход (если не прочитать документацию* или не понять её): equal_var = False. Ну а что? У выборок же разные дисперсии, поэтому и False.
Метод scipy.stats.ttest_ind
https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.ttest_ind.html
If True (default), perform a standard independent 2 sample test that assumes equal population variances. If False, perform Welch’s t-test, which does not assume equal population variance
Но в том-то и дело, что спрашивают вас о том, поменяется ли у вас дисперсия генеральной совокупности или нет из-за вашего тритмента. У выборок они и без того будут разными, но другое дело, что в случае предположения о неизменчивости дисперсии из-за тритмента обе выборочные дисперсии будут оценками одной и той же дисперсии генеральной, поэтому их "объединяют"* (pooled). В случае изменчивости разброса у генеральной, так сделать уже нельзя. И вот тогда как будто и стоит указать equal_var = False, что превратит ваш Т-test, на самом деле, в тест Welch’a. Но стоит ли?
Пояснение по "объединяют"* (pooled):
*На мой взгляд, это не самая удачная формулировка из-за ассоциации со сложением. Лучше использовать что-то вроде "скомбинировать", "скомпилировать" через обычное или взвешенное среднее – зависит от того, одинаковый ли размер выборок. Усреднение вполне логично: ведь эти дисперсии – оценки одной и той же генеральной, мы берём из них значение между.
Тут сразу следует сказать, что в случае больших* выборок (а в рамках крупного бизнеса с поюзерными экспериментами часто это так и есть, чего не скажешь о таких объектах тестирования, как офлайн магазины, рестораны и пр.), t-test даёт одно и тоже t-распределение и контролирует ошибку 1-го рода вне зависимости от изменчивости дисперсии, которую мог бы дать тритмент.
Пояснения по большим выборкам:
*Кратко: для формального определения "большой"/"маленькой" выборки сошлюсь, во-первых, на неравенство Берри-Эссеена. Если оно выполняется для той же t-статистики при некоторой выборке n, тогда эта большая выборка.
Во-вторых, можно пойти через симуляцию: генерим ряд A/A тестов ~ 10k для оценки корректной работы критерия через контроль ошибки 1-го рода.

Код для воспроизведения гистограмм справа
Для самостоятельного воспроизведения гистограмм
'''
t-test
- Нормальные генеральные,
- Одна и та же Mu,
- Разные дисперсии,
- Одинаковый размер выборок
Смотрим t-распределения
'''
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats
from statsmodels.stats.proportion import proportion_confint
mu = 24
sigma = 2
sigma_alt = 20
size = 1000000
population = np.random.default_rng().normal(mu, sigma, size)
population_alt_var = np.random.default_rng().normal(mu, sigma_alt, size)
size_a = 500
size_b = 500
alpha = 0.05
trials = 10000
t_stats_h0 = []
for i in range(trials):
a = np.random.choice(population, size=size_a)
b = np.random.choice(population, size=size_b)
t_stat, p_value = scipy.stats.ttest_ind(a, b, equal_var=True)
t_stats_h0.append(t_stat)
t_stats_hA = []
for i in range(trials):
a = np.random.choice(population, size=size_a)
b = np.random.choice(population_alt_var, size=size_b)
t_stat, p_value = scipy.stats.ttest_ind(a, b, equal_var=True)
t_stats_hA.append(t_stat)
plt.hist(t_stats_h0, density=True, bins='auto', label='sigma одинаковая', alpha=0.5);
plt.hist(t_stats_hA, density=True, bins='auto', label='sigma разная', alpha=0.5);
plt.title('Распределение t-статистики')
plt.xlim([-10, 10])
plt.xlabel('t')
plt.legend()
plt.show()
Для проверки ошибок 1-го рода:
'''
t-test
- Нормальные генеральные,
- Одна и та же Mu,
- Разные дисперсии,
- Одинаковый размер выборок
Исследуем ошибку 1-го рода
'''
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats
from statsmodels.stats.proportion import proportion_confint
mu = 24
sigma = 2
sigma_alt = 20
size = 1000000
population = np.random.default_rng().normal(mu, sigma, size)
population_alt_var = np.random.default_rng().normal(mu, sigma_alt, size)
size_a = 500
size_b = 500
alpha = 0.05
trials = 10000
bad_ttest_count = 0
for i in range(trials):
a = np.random.choice(population, size=size_a)
b = np.random.choice(population_alt_var, size=size_b)
t_stat, p_value = scipy.stats.ttest_ind(a, b, equal_var=True)
if p_value <= alpha:
bad_ttest_count += 1
left_ttest_level, right_ttest_level = proportion_confint(count = bad_ttest_count, nobs = trials, alpha=alpha, method='wilson')
print(bad_ttest_count/trials)
print(f"T-test significance level: {round(bad_ttest_count / trials, 4)}, [{round(left_ttest_level, 4)}, {round(right_ttest_level, 4)}]")

На всякий случай: аналогичная картина наблюдается, если распределения ненормальные (примеры не имеют реального аналога, это специальное сравнение из радикально разных распределений, где лишь одинаковая средняя):

Другое дело, если выборки засплитованы не 50 на 50, а как-то иначе. Чем больше дисбаланс, тем больше будет ошибок первого рода, чем мы бы хотели:

Код для воспроизведения
'''
t-test
- Нормальные генеральные,
- Одна и та же Mu,
- Разные дисперсии,
- Разный размер выборок
Исследуем ошибку 1-го рода
'''
import numpy as np
import scipy.stats
from statsmodels.stats.proportion import proportion_confint
#средняя
mu = 24
#отклонение
sigma = 2
sigma_alt = 20
#размер выборки
size = 1000000
#данные
population = np.random.default_rng().normal(mu, sigma, size)
population_alt_var = np.random.default_rng().normal(mu, sigma_alt, size)
size_a = 700
size_b = 300
alpha = 0.05
trials = 10000
bad_ttest_count = 0
for i in range(trials):
a = np.random.choice(population, size=size_a)
b = np.random.choice(population_alt_var, size=size_b)
t_stat, p_value = scipy.stats.ttest_ind(a, b, equal_var=True)
if p_value <= alpha:
bad_ttest_count += 1
left_ttest_level, right_ttest_level = proportion_confint(count = bad_ttest_count, nobs = trials, alpha=alpha, method='wilson')
print(bad_ttest_count/trials)
print(f"T-test significance level: {round(bad_ttest_count / trials, 4)}, [{round(left_ttest_level, 4)}, {round(right_ttest_level, 4)}]")
И вот в этом случае как раз тест Welch'a сработал бы как надо:

Код для воспроизведения
'''
Welch-t
- Нормальные генеральные,
- Одна и та же Mu,
- Разные дисперсии,
- Разный размер выборок
Исследуем ошибку 1-го рода
'''
import numpy as np
import scipy.stats
from statsmodels.stats.proportion import proportion_confint
mu = 24
sigma = 2
sigma_alt = 20
size = 1000000
population = np.random.default_rng().normal(mu, sigma, size)
population_alt_var = np.random.default_rng().normal(mu, sigma_alt, size)
size_a = 700
size_b = 300
alpha = 0.05
trials = 10000
bad_ttest_count = 0
for i in range(trials):
a = np.random.choice(population, size=size_a)
b = np.random.choice(population_alt_var, size=size_b)
t_stat, p_value = scipy.stats.ttest_ind(a, b, equal_var=False)
if p_value <= alpha:
bad_ttest_count += 1
left_ttest_level, right_ttest_level = proportion_confint(count = bad_ttest_count, nobs = trials, alpha=alpha, method='wilson')
print(bad_ttest_count/trials)
print(f"T-test significance level: {round(bad_ttest_count / trials, 4)}, [{round(left_ttest_level, 4)}, {round(right_ttest_level, 4)}]")
Вернемся к случаю сплита 50 на 50 и большим выборкам. Важно, что в случае наличия эффекта вне зависимости от того, сдвиг ли это просто средней или и средней и дисперсии, оба теста обладают приблизительно схожей чувствительностью, но чуть чаще (~60% случаев) мощнее был t-test.
Что логично, так как у Welch'a degrees of freedom, d, систематически хоть немного, но занижаются из-за размеров выборки и дисперсии (в выводе формулы будет видна зависимость d от этих двух параметров). Только при бесконечной большой выборке Welch сравнялся бы с t-test.
1.Сдвиг средней:



Код для воспроизведения
'''
t-test
- Нормальные генеральные,
- Разные средние
- Одинаковые дисперсии,
- Oдинаковый размер выборок
Исследуем мощность
'''
import numpy as np
import scipy.stats
from statsmodels.stats.proportion import proportion_confint
mu = 24
mu_alt = 24.2
sigma = 5
size = 5000000
population = np.random.default_rng().normal(mu, sigma, size)
population_alt = np.random.default_rng().normal(mu_alt, sigma, size)
size_a = 10000
size_b = 10000
alpha = 0.05
trials = 50000
good_ttest_count = 0
for i in range(trials):
a = np.random.choice(population, size=size_a)
b = np.random.choice(population_alt, size=size_b)
t_stat, p_value = scipy.stats.ttest_ind(a, b, equal_var=True)
if p_value <= alpha:
good_ttest_count += 1
left_ttest_level, right_ttest_level = proportion_confint(count = good_ttest_count, nobs = trials, alpha=alpha, method='wilson')
print(good_ttest_count/trials)
print(f"T-test significance level: {round(good_ttest_count / trials, 4)}, [{round(left_ttest_level, 4)}, {round(right_ttest_level, 4)}]")
'''
Welch's test
- Нормальные генеральные,
- Разные средние
- Одинаковые дисперсии,
- Oдинаковый размер выборок
Исследуем мощность
'''
import numpy as np
import scipy.stats
from statsmodels.stats.proportion import proportion_confint
mu = 24
mu_alt = 24.2
sigma = 5
size = 5000000
population = np.random.default_rng().normal(mu, sigma, size)
population_alt = np.random.default_rng().normal(mu_alt, sigma, size)
size_a = 10000
size_b = 10000
alpha = 0.05
trials = 50000
good_ttest_count = 0
for i in range(trials):
a = np.random.choice(population, size=size_a)
b = np.random.choice(population_alt, size=size_b)
t_stat, p_value = scipy.stats.ttest_ind(a, b, equal_var=False)
if p_value <= alpha:
good_ttest_count += 1
left_ttest_level, right_ttest_level = proportion_confint(count = good_ttest_count, nobs = trials, alpha=alpha, method='wilson')
print(good_ttest_count/trials)
print(f"Welch-test significance level: {round(good_ttest_count / trials, 4)}, [{round(left_ttest_level, 4)}, {round(right_ttest_level, 4)}]")
Сравнение t-test'a и Welch's test по мощности. T-test упорно показывал результаты получше.
'''
Лучше ли t-test, чем Welch ?
- Нормальные генеральные,
- Разные средние
- Одинаковые дисперсии,
- Oдинаковый размер выборок
Придется подожать.
'''
import numpy as np
import scipy.stats
from statsmodels.stats.proportion import proportion_confint
mu = 24
mu_alt = 24.2
sigma = 5
size = 5000000
population = np.random.default_rng().normal(mu, sigma, size)
population_alt = np.random.default_rng().normal(mu_alt, sigma, size)
size_a = 10000
size_b = 10000
alpha = 0.05
series = 100
trials = 10000
ttest_better = 0
for s in range(series):
good_ttest_count = 0
for i in range(trials):
a = np.random.choice(population, size=size_a)
b = np.random.choice(population_alt, size=size_b)
_, p_value = scipy.stats.ttest_ind(a, b, equal_var=True)
if p_value <= alpha:
good_ttest_count += 1
good_welch_count = 0
for i in range(trials):
a = np.random.choice(population, size=size_a)
b = np.random.choice(population_alt, size=size_b)
_, p_value = scipy.stats.ttest_ind(a, b, equal_var=False)
if p_value <= alpha:
good_welch_count += 1
if good_ttest_count/trials > good_welch_count/trials:
ttest_better += 1
print(f"T-test лучше в {ttest_better/series} случаев")
2.Сдвиг и средней и дисперсии. Результат аналогичный:



Код для воспроизведения
'''
t-test
- Нормальные генеральные,
- Разные средние
- Разные дисперсии,
- Oдинаковый размер выборок
Исследуем мощность
'''
import numpy as np
import scipy.stats
from statsmodels.stats.proportion import proportion_confint
mu = 24
mu_alt = 24.2
sigma = 5
sigma_alt = 10
size = 1000000
population = np.random.default_rng().normal(mu, sigma, size)
population_alt = np.random.default_rng().normal(mu_alt, sigma_alt, size)
size_a = 10000
size_b = 10000
alpha = 0.05
trials = 10000
good_ttest_count = 0
for i in range(trials):
a = np.random.choice(population, size=size_a)
b = np.random.choice(population_alt, size=size_b)
t_stat, p_value = scipy.stats.ttest_ind(a, b, equal_var=True)
if p_value <= alpha:
good_ttest_count += 1
left_ttest_level, right_ttest_level = proportion_confint(count = good_ttest_count, nobs = trials, alpha=alpha, method='wilson')
print(good_ttest_count/trials)
print(f"T-test significance level: {round(good_ttest_count / trials, 4)}, [{round(left_ttest_level, 4)}, {round(right_ttest_level, 4)}]")
'''
Welch's test
- Нормальные генеральные,
- Разные средние
- Разные дисперсии,
- Oдинаковый размер выборок
Исследуем мощность
'''
import numpy as np
import scipy.stats
from statsmodels.stats.proportion import proportion_confint
mu = 24
mu_alt = 24.2
sigma = 5
sigma_alt = 10
size = 1000000
population = np.random.default_rng().normal(mu, sigma, size)
population_alt = np.random.default_rng().normal(mu_alt, sigma_alt, size)
size_a = 10000
size_b = 10000
alpha = 0.05
trials = 10000
good_ttest_count = 0
for i in range(trials):
a = np.random.choice(population, size=size_a)
b = np.random.choice(population_alt, size=size_b)
t_stat, p_value = scipy.stats.ttest_ind(a, b, equal_var=False)
if p_value <= alpha:
good_ttest_count += 1
left_ttest_level, right_ttest_level = proportion_confint(count = good_ttest_count, nobs = trials, alpha=alpha, method='wilson')
print(good_ttest_count/trials)
print(f"Welch-test significance level: {round(good_ttest_count / trials, 4)}, [{round(left_ttest_level, 4)}, {round(right_ttest_level, 4)}]")
Сравнении тестов через серии:
'''
Лучше ли t-test, чем Welch ?
- Нормальные генеральные,
- Разные средние
- Разные дисперсии,
- Oдинаковый размер выборок
Придется подожать.
'''
import numpy as np
import scipy.stats
from statsmodels.stats.proportion import proportion_confint
mu = 24
mu_alt = 24.2
sigma = 5
sigma_alt = 10
size = 5000000
population = np.random.default_rng().normal(mu, sigma, size)
population_alt = np.random.default_rng().normal(mu_alt, sigma_alt, size)
size_a = 10000
size_b = 10000
alpha = 0.05
series = 100
trials = 10000
ttest_better = 0
for s in range(series):
good_ttest_count = 0
for i in range(trials):
a = np.random.choice(population, size=size_a)
b = np.random.choice(population_alt, size=size_b)
_, p_value = scipy.stats.ttest_ind(a, b, equal_var=True)
if p_value <= alpha:
good_ttest_count += 1
good_welch_count = 0
for i in range(trials):
a = np.random.choice(population, size=size_a)
b = np.random.choice(population_alt, size=size_b)
_, p_value = scipy.stats.ttest_ind(a, b, equal_var=False)
if p_value <= alpha:
good_welch_count += 1
if good_ttest_count/trials > good_welch_count/trials:
ttest_better += 1
print(f"T-test лучше в {ttest_better/series} случаев")
Проверим также, что t-test на выборке 10к и разной дисперсии соблюдает ошибку 1-го рода:
#проверка, что соблюдается ошибка 1-го рода
'''
t-test
- Нормальные генеральные,
- Разные средние
- Разные дисперсии,
- Oдинаковый размер выборок
Ошибка 1-го рода
'''
import numpy as np
import scipy.stats
from statsmodels.stats.proportion import proportion_confint
mu = 24
mu_alt = 24
sigma = 5
sigma_alt = 10
size = 1000000
population = np.random.default_rng().normal(mu, sigma, size)
population_alt = np.random.default_rng().normal(mu_alt, sigma_alt, size)
size_a = 10000
size_b = 10000
alpha = 0.05
trials = 10000
bad_ttest_count = 0
for i in range(trials):
a = np.random.choice(population, size=size_a)
b = np.random.choice(population_alt, size=size_b)
t_stat, p_value = scipy.stats.ttest_ind(a, b, equal_var=True)
if p_value <= alpha:
bad_ttest_count += 1
left_ttest_level, right_ttest_level = proportion_confint(count = bad_ttest_count, nobs = trials, alpha=alpha, method='wilson')
print(bad_ttest_count/trials)
print(f"T-test significance level: {round(bad_ttest_count / trials, 4)}, [{round(left_ttest_level, 4)}, {round(right_ttest_level, 4)}]")

То есть в сценарии больших выборок и сплита 50 на 50 менять t-test на теста Welch’a нет необходимости. Отсюда и в методе scipy.stats.ttest_ind параметр equal_val – вполне обоснованно по умолчанию = True.
Если сплит планируется иной, тогда это первая ситуация, где вполне логично стоит задуматься о том, как ваше воздействие скажется на дисперсии.
А что, если… выборки маленькие?
А вот если они маленькие и ваше воздействие изменит дисперсию, но при этом не повлияет на среднее, то использование t-test’a вместо желаемого предела ошибки 1-го рода (допустим, в 0.05), будет давать таких ошибок больше.
Это вторая ситуация, где, казалось бы, стоит начать думать над тритметом относительно дисперсии.

Слева на рисунке, как и до этого, наши генеральные. Сначала (1) будем многократно брать две малые выборки порядка 2 измерений в каждой из синего распределения, проводить A/A тест, собирая t-значения; потом (2) будем брать выборки такого же размера из двух уже разных с точки зрения дисперсии генеральных. Итого справа на рисунке у нас получается два t-распределения.
Код для воспроизведения гистограммы слева
'''
t-test
- Нормальные генеральные,
- Разные дисперсии,
- Маленькие выборки
- Одинаковый размер выборок
Смотрим t-распределения
'''
import numpy as np
import scipy.stats
import matplotlib.pyplot as plt
from statsmodels.stats.proportion import proportion_confint
mu = 24
sigma = 2
sigma_alt = 20
size = 1000000
population = np.random.default_rng().normal(mu, sigma, size)
population_alt_var = np.random.default_rng().normal(mu, sigma_alt, size)
size_a = 2
size_b = 2
alpha = 0.05
trials = 10000
t_stats_h0 = []
for i in range(trials):
a = np.random.choice(population, size=size_a)
b = np.random.choice(population, size=size_b)
t_stat, p_value = scipy.stats.ttest_ind(a, b, equal_var=True)
t_stats_h0.append(t_stat)
t_stats_hA = []
for i in range(trials):
a = np.random.choice(population, size=size_a)
b = np.random.choice(population_alt_var, size=size_b)
t_stat, p_value = scipy.stats.ttest_ind(a, b, equal_var=True)
t_stats_hA.append(t_stat)
plt.hist(t_stats_h0, density=True, bins='auto', label='sigma одинаковая', alpha=0.5);
plt.hist(t_stats_hA, density=True, bins='auto', label='sigma разная', alpha=0.5);
plt.title('Распределение t-статистики')
plt.xlim([-10, 10])
plt.xlabel('t')
plt.legend()
plt.show()
Во втором случае (2) t-распределение (жёлтое) имеет более широкие толстые хвосты, но так как мы думаем, что оперируем синим t-распределением (1) и его критическими значениями, мы и получаем больше ошибок 1-го рода, чем хотели бы. Что логично, так как t распределено согласно (2), то больше значений уходит в критическую область!

Код для воспроизведения
'''
t-test
- Нормальные генеральные,
- Разные дисперсии,
- Маленькие выборки
- Одинаковый размер выборок
Исследуем ошибку 1-го рода
'''
import numpy as np
import scipy.stats
from statsmodels.stats.proportion import proportion_confint
mu = 24
sigma = 2
sigma_alt = 20
size = 1000000
population = np.random.default_rng().normal(mu, sigma, size)
population_alt_var = np.random.default_rng().normal(mu, sigma_alt, size)
size_a = 2
size_b = 2
alpha = 0.05
trials = 10000
alpha = 0.05
trials = 10000
bad_ttest_count = 0
for i in range(trials):
a = np.random.choice(population, size=size_a)
b = np.random.choice(population_alt_var, size=size_b)
t_stat, p_value = scipy.stats.ttest_ind(a, b, equal_var=True)
if p_value <= alpha:
bad_ttest_count += 1
left_ttest_level, right_ttest_level = proportion_confint(count = bad_ttest_count, nobs = trials, alpha=alpha, method='wilson')
print(bad_ttest_count/trials)
print(f"T-test significance level: {round(bad_ttest_count / trials, 4)}, [{round(left_ttest_level, 4)}, {round(right_ttest_level, 4)}]")
Тут бы и пригодился тест Welch’a: ошибка первого рода была бы в нужных нам границах. Но всё равно всё не так просто. И хотя довольно разумно предположить, что ваш тритмент меняет не только среднюю, но и дисперсию, тут есть трудность, что просто разумного предположения мало для того, чтобы использовать тест Welch’a по умолчанию.
Почему? Потому что, как вы могли понять, тест Welch’a сродни поправке на множественное тестирование: он меняет t-распределение с точки зрения степени свободы в меньшую сторону как при разных выборочных дисперсиях, так и при разном размере выборок. В меньшую сторону значит, что (очень-очень условно, исключительно для представления) в рамках t-test’a это могло быть t-распределение c df = 1000, где рукой подать до сходимости с базой ЦПТ – z-распределением. А в рамках Welch’a df ~ 3, то есть как если бы вы делали тест на пределе возможностей, выборки по 2, оперируя t-распределением с очень толстыми хвостами.
То есть новые критические значения будут больше по модулю, чем у классического t-test'a, поэтому чувствительность этого теста Welch'a будет ниже, если ваше воздействие меняет, на самом деле, только среднее. Да, как и в поправках, вы сохраните заданный уровень значимости, если дисперсии генеральных действительно подверглись изменению, но при фиксированной аудитории ценой меньшей мощности (или увеличения MDE), если это не так.
А ведь мощность столь же важна, как и альфа, мы не хотим упустить эффект так же сильно, как хотим не получить ложноположительный результат. В конце концов, ещё большой вопрос в рамкам бизнеса: что хуже – ошибка первого рода или второго? Тем более, что стандарт в индустрии – это мощность = 0.8, что даёт ошибку второго рода = 0.2. На самом деле, не так уж и мало!
То есть об изменении дисперсии, по-хорошему, надо подумать ещё на этапе дизайна и зафиксировать, какой тест будет использоваться – t-test или Welch's test, а то при анализе результатов смена критерия может стоить вам мощности.
Но, может, поступить взвешеннее?
Для начала заложиться в дизайне сразу на возможное применение критерия Welch'a: если размер выборки стоит остро, то ценой увеличенного MDE. А в рамках уже расчётов вместо разумных (но не подкреплённых фактами) предположений о том, изменили мы дисперсию или нет, применить какой-нибудь стат. тест для дисперсий. Действительно, кажется, что мы можем проверить выборочные дисперсии на однородность и уже далее принять решение о том, какой тест в итоге применить: тем более, нам это даже выгодно, ведь если у нас фиксированная аудитория, то при гомогенности дисперсий можно переложиться на t-test, повышая чувствительность.
Но, увы, здесь тоже не всё так просто из-за увеличения ошибки первого рода в серии двух тестов: один на проверку дисперсий, другой из семейства t-test’ов.
Раз столько нюансов, то, пожалуй, теперь самое время разобраться подробнее как в модификации t-test’a, которую предложил Welch, так и в том, делать ли проверки на гомогенность дисперсий, делать ли поправки на множественное тестирование при этом, действительно ли надо по умолчанию предполагать изменение дисперсии и можно ли точно где-то предполагать изменчивость дисперсии?
Welch’s Test
К сожалению, тут нет другого варианта, кроме как не спеша попробовать вывести его, разбирая вывод шаг за шагом.
С чем вообще мы имеем дело? Наша ситуация сравнения средних при знании, что мы изменили дисперсию, следующая:
Наши выборочные дисперсии — это оценки «разных генеральных». И раз обычный Т‑test объединяет (pool) выборочные дисперсии, а точнее усредняет, делая знаменатель меньше, значит t‑статистика будет более размашистой. Но в том‑то и дело, что раз оценки разных генеральных, значит и усреднять мы не можем, а это значит, что t‑статистика должна быть меньше.
Для наглядности: пускай ваши выборочные дисперсии равны [4, 4] (забудем тут о размере выборок, выкинем их из корня). Среднее даст вам 4, квадратный корень из среднего = 2. А если оставить как есть, то тогда мы просто складываем 4-ки = 8. Корень = 2.82. Если одну и ту же разницу (допустим, 10) поделить на 2 против 2.82, то «t» будет 5 и 3.84 соответственно.
Однако про это «должна быть меньше» t‑test ничего не знает: усредняет и всё тут — что и делает t-статистику больше нужной, а это и есть источник ошибки первого рода больше заданного предела альфы. Значит результаты t-test'a нужно как-то корректировать, но как?
Возможны два варианта: либо умножать полученную t-статистику на какой-то коэффициент, либо изменить само t-распределение, на которое будет приземляться полученная t-статистика. По сути, оба варианта про одно и тоже — увидите далее.
Изменить само распределение означает, в сущности, поменять степень свободы у t‑распределения, которое подразумевалось бы у обычного t‑test'a. То есть нам нужна коррекция d — degrees of freedom.
Думаю, Welch, конечно, имел представление о поправках на всякие множественные тестирования, а потому вполне логично было сначала как раз пойти первым путём, но сам вывод вывел, кажется, неожиданно на второй.
Вывод коррекции. Попытка выйти на коэффициент
Для вывода буду использовать ряд классических свойств ожидаемого значения и дисперсии:
И для независимых величин:
Итак, попробуем скорректировать t-значение, умножим обе части на истинные значения дисперсий популяции (которые мы не знаем, конечно, но на уровне неизвестной ей оперировать можно):
Поменяем местами корни в знаменателе:
В такой записи мы свели наше выражение к обычному Т‑тесту с коррекцией на «коэффициент» (другую случайную величину) с тем лишь комментарием, что это случай больших выборок:
разные дисперсии в части классической записи t‑формулы нивелируются большими значениями размера выборки;
«коэффициент» сведётся к единице, так как оценки, по закону больших чисел, сравняются с дисперсиями генеральных.
Значит, нам надо разобраться с коэффициентом (новой статистикой) для малых выборок, так как там он сходиться к единице не будет. Обозначим его как S:
Красным выделены параметры популяций.
Итого у нас есть перемножение двух статистик, далее просто свёрнутая форма (3):
,
где индекс — это указание на статистику Welch’a.
Логично рассудить, что мы, в сущности, корректируем само t-распределение, то есть его форму, умножая t-статистику на , которая распределена неизвестно как. Однако, если мы это узнаем, то сможем понять, какому закону распределения (его параметрам) подчиняется это перемножение.
Исследуем распределение S-статистики
Какие сущности мы наблюдаем в числителе и знаменателе S?
И там и там — сумма дисперсий. Значит в итоге мы делим дисперсию на дисперсию. А отношение (тут внимательно) выборочных дисперсии распределяется согласно распределению Фишера, .
Сделаем вид, что всё в порядке, и продолжим рассуждения.
Далее полагаю, что в целях упрощения расчётов перемножения статистик было удобнее перейти от F-распределения к Хи-Квадрат.
Вспомним, что выборочная дисперсия распределена согласно Хи-Квадрат. У этого распределения есть ряд интересных свойств:
1. Сумма Хи-Квадрат распределений даёт новое Хи-Квадрат распределение с объединёнными степенями свободы:
2. Если нормировать Хи-Квадрат на его степень свободы, то мы получим F-распределение, причём, такое:
И у нас бы всё прекрасно получилось, то есть мы бы поняли, на что конкретно перемножать, если бы не истинные значения в числителе!
Дело как раз в том, что F-распределение (оно же нормированное Хи-Квадрат) получается только при делении выборочных дисперсий, а истинная дисперсия — это параметр.
Хорошо, а что если мы выведем оценку для , степеней свободы? Такую, при которой наша
действительно удовлетворяла бы условию:
Что дало бы в свою очередь:
Вывод оценки степеней свободы нормализованного Хи-Квадрат
Случайная величина Пси
Пускай есть случайная величина Пси, которая распределена как Хи-Квадрат c k=d:
Сам Хи-Квадрат можно представить через классические z-значения:
Ожидаемое значение Пси
Применяя свойства ожидаемого значения, получим следующее:
Что такое ожидаемое значение от Z в квадрате? Воспользуемся классической формулой дисперсии, выраженной через ожидаемое значение — палочкой‑выручалочкой для аналитического вывода дисперсии любой случайной величины, дайте только ожидаемые значения на вход!
Так как мы знаем, что:
То мы легко можем вычислить желаемое:
Возвращаемся к (7):
Здесь коротко поясню, что раз у нас каждое i-ое значение — это 1, то мы складываем d единиц = d*1 = d
Дисперсия Пси
Пускай есть некоторая величина:
Тогда используя всю ту же формулу для дисперсии:
Только что мы уже разобрались с Z в квадрате:
А вот ожидаемое значение Z в четвёртой степени — это самый настоящий четвёртый момент случайной величины, который для нормального распределения с Mu = 0 (а именно такая наша Z) равен:
А так так сигма у нас = 1 для Z, то рассчитать дисперсию квадрата очень легко:
Теперь рассчитаем дисперсию Пси с применением свойств дисперсии:
Так как нам уже известна дисперсия в квадрате, то:
(двойку тут тоже раз складываем, поэтому и
)
Дисперсия S
Применяя очередное свойство дисперсии про скаляр, выразим дисперсию Пси с коэффициентом :
Складываем всё вместе:
Выходит, что:
Возможно, если мы сможем как-то преобразовать/оценить выражение в дроби слева, то и выразим . Что мы видим с вами в скобках? Числитель и знаменатель, а это значит, что здесь нам на помощь приходит Дельта‑Метод — метод приближения функции через ряд Тейлора — с помощью которого в индустрии приближена дисперсия такой коварной метрики как метрика отношений:
Вывод этого приближения заслуживает отдельного материала, но чтобы это не было совсем из воздуха, то просто скажу, что функцию от двух переменных X и Y разложили через ряд Тейлора первого порядка в точке E(X), E(Y), считая производные по X и Y, а после применили n алгебраических операций — и готово.
Возвращаемся к нашему выводу: так как у нас числитель и знаменатель независимы, то , упрощая наше выражение:
у нас ожидаемые значения по X и Y, поэтому:
Вернёмся к нашим значениям по X и Y в пропорции слева части:
Теперь внимательно смотрим на дисперсию по ,
: у нас там совершенно конкретные дисперсии генеральных, совершенно конкретные размеры выборок, то есть, обобщая, это какая-то константа. А дисперсия константы равна нулю, поэтому наше выражение вновь упрощается:
С этим работать гораздо проще, то есть нужно разобраться с парой ожидаемых значений да дисперсий. Звучит «вроде изян».
Универсальная таблица оценки задач

Тут также была константа, то по свойству мат.ожидания получим саму константу.
Далее берёмся за Y:
Наши оценки будут сходиться к теор. значениям, поэтому так.
И, наконец, дисперсия.
Но не тут‑то было! Так просто мы с этим не справимся. Нам нужно оценить дисперсии по A и B.
Что ж, хорошо, пойдём с базы, не смещённой оценкой выборочной дисперсии:
Далее вспоминаем про Z в квадрате, что оно распределено как Хи-Квадрат:
Зная по определению, что:
Мы получим:
Тогда согласно (12):
Следовательно:
Рассчитываем дисперсию для А:
Вспомним дисперсию Хи-Квадрат:
Итого дисперсия по A:
Для дисперсии по B всё то же самое!
Вот теперь изъян без всяких вроде, подставляем в (11.3.3):
Выражаем d
Подставляем всё рассчитанное ранее в (9):
Дальше ничего, кроме обычный алгебры, нас и не ждёт, поэтому задача — просто выразить d, пожонглировав умножением и делением:
Вуаля! Мы выразили коррекцию степени свободы при изменении дисперсии от нашего воздействия. Видно, что d зависит и от дисперсий групп, и от размера выборок.
Единственный нюанс d в том, что оно не будет получаться целым, поэтому его округляют — это и будет вашим скорректированным t‑распределением.
Что мы получаем в случае малых выборок?
Рассмотрим пример, где у нас n_a = n_b = 10. Если дисперсии равны (sigma_a = sigma_b = 2), то и у Т-test’a и Welch’a будет d = 18, но если дисперсия в B изменится и будет равна 1, тогда у Т-test’a будет также d = 18, а вот Welch’a уже d = 13. Посмотрим на t-таблицу:

Заметьте, как сдвинулись критические значения в сторону увеличения. Именно по этой причине в рамках малых выборок мы защитимся от ошибки 1-го рода, но и неизбежно увеличим ошибку 2-го рода!
Две потенциальные ситуации для Welch’a
Итак, у нас будут проблемы с ошибкой первого рода, если:
Во‑первых, если у нас сплит отличается от 50/50 в рамках больших выборок.
Во‑вторых, на малых выборках при изменении дисперсии от нашего воздействия, но не изменении среднего.
Тест Welch'a нас бы от этого защитил, но дал бы больше ошибок 2-го рода, если с дисперсиями, на самом деле, это не так и они равны, а эффект есть.
Что тогда? Может, сравнить дисперсии выборок?
К вопросу о предварительном тесте дисперсии
Короткий ответ: не надо.
Вроде бы вполне логично сделать тогда так называемый preliminary тест, то есть предварительные тесты до нашего целевого, для проверки гомогенности дисперсии двух малых выборок, то есть дисперсионный анализ. Если не можем отклонить гипотезу о том, что дисперсии не отличаются, то проводим Т‑test, а если нет, то тест Welch'a.
Предварительные тесты увеличивают ошибку 1-го рода. По банальной причине: мы делаем два теста — дисперсионный и на эффект (test of effect), а значит увеличивается ошибка первого рода хотя бы один раз.
Вероятен следующий сценарий, когда между А и B, на самом деле, нет никакой разницы: мы можем получить ложноположительный результат в дисперсионном анализе, а в рамках эффекта в средних отсутствие эффекта. Но из‑за теста дисперсий мы будем думать, что отличия всё же есть.
Об этом упоминали следующие исследователи:
Moser, B.K. and G.R. Stevens, 1992, “Homogeneity of Variance in the Two Sample Means Test”
Hayes and Cai, 2007, “Further evaluating the conditional decision rule for comparing two independent means”
Вот что есть в аннотации к статье Zimmermann, 2004, «A note on preliminary tests of equality of variances» (здесь и далее сохраняю оригинальный английский текст):
Preliminary tests of equality of variances used before a test of location are no longer widely recommended by statisticians... Simulations disclosed that the two‑stage procedure (в контексте Levene's) fails to protect the significance level and usually makes the situation worse.
При этом, если предварительный тест дисперсий стат. значим, то есть стоит по методичке применить Welch'a, то последний сам начинает совершать больше ошибок 1-го рода:
Furthermore, the validity of the Welch test deteriorates if it is used only on those occasions where a preliminary test indicates it is needed
В 2019 году вышла статья от Jack Pearce, Ben Derrick «Preliminary Testing: The Devil of Statistics?». И хоть некоторый материал, не имеющий прямого отношения к нашему вопросу, мягко говоря, спорный*, тем не менее, отмечалось следующее:
Комментарий по некоторым спорным тезисам в статье
1) "t-test... assumption that data is normally distributed" - напрямую не сказано, о каких данных идёт речь, кажется, что о выборке. В конце концов, какая data кроме выборочной? Но если это так, то это неверно.
2) Если не t-test, то используйте Mann-Whitney. Тоже такое, так как MW проверяет другую гипотезу, и никакой он не непараметрический аналог. Он просто непараметрический и просто другой. Разобраться в Mann-Whitney может помочь статья Varioqub: за Mann-Whitney замолвите слово
1. Классические стат. пакеты, такие как SPSS и Minitab, содержат процедуру из двух шагов: сначала тест дисперсии Levenе, если незначимо — t‑test, значимо — Welch'a.
Но пакеты используют разные (sic!) версии Levene: один использует средние, другой медианы, что может давать противоположные результаты, если следовать алгоритму (пример в статье есть).
2. Потом шла оценка тестов (обратим внимание только на t‑test и Welch'a) без предварительных проверок, когда малые выборки (5, 10, 20, 30 изм.) генерировались из распределения разной формы. Вполне ожидаемо, что ложных прокрасов у t‑test'a при неравенстве дисперсий нормальных распределений оказалось больше, причём, местами аж зашкаливало (до 0.25). Но интереснее оказалось другое: Welch давал больше ложных на экспоненциальном и логнормальном, чем t-test!
Смотрим на IT (Ind. T‑Test) и W — Welch, прочие обозначения относятся к непараметрическим тестам как Mann-Whitney:


Заключение: никакой тест не контролировал ошибку 1-го рода даже в рамках критерия Bradley's [2.5%, 7.5%], самый плохой сценарий — слишком большое различие в размерах групп.
А вот после предварительного теста дисперсий всё почти прекрасно, практический строгий контроль ошибки 1-го рода:

То есть как минимум можно подобрать такие предварительные тесты при должном уровне значимости, которые смягчат утверждение Zimmermann'a, что Welch тест после preliminary работает хуже.
Но, увы, это не снимает обозначенную проблему ложноположительного теста дисперсий. Проведённые исследования улучшили контроль ошибки 1-го рода тестов, но только и всего. Получается так, что в основном процедуру предварительных тестов стоит пропустить. Что тогда делать?
Использовать Welch по дефолту?
Короткий ответ: нет
В той же статье Zimmermann'a есть ссылки на очередные исследования против предварительных тестов, в которых явно указано следующее — использовать сразу по дефолту тест Welch вместо классического t‑test'a:
Wells and Hintze (2007) and Rasch et al. (2011, The two‑sample t test: pre‑testing its assumptions does not pay off) also question why the Independent t‑test is considered the default two‑sample test and suggested using Welch's test as the default”
И вроде бы другие исследователи, как Marie Delacre, Daniël Lakens, Christophe Leys, 2017, «Why Psychologists Should by Default Use Welch's t‑test Instead of Student's t‑test» (мы ещё вернёмся к этому исследованию) показывают, что Welch тест лишь самую малость уступает в мощности t‑test, а сам при этом делает тестирование средних устойчивее к ошибке 1-го рода в случае разных дисперсий популяций.
Однако выше мы увидели ранее, что не во всех случаях (экспоненциальном и логнормальном). Отсюда нельзя так слепо заменить t‑test на Welch'a. Вам для этого придётся исследовать ошибку 1-го и (это не менее важно) 2-го рода двух этих тестов на базе исторических данных.
Проблема нулевой гипотезы Welch’a
Но есть и другое возражение против теста Welch'a, которое лежит в области определения нулевой гипотезы данного теста: нет различий в средних с различиями в дисперсии. Получается, что в случае, когда у нас нет возможности отклонить нулевую гипотезу, мы всё равно можем (sic!) продолжать думать, что есть различия дисперсий: «не может отклонить H0 о том, что средние не различаются, с учётом различий в дисперсиях». Так ведь? А на каких основаниях?
S.S. Sawilowsky, 2002, «Fermat, Schubert, Einstein, Behrens‑Fisher: The Probable Difference Between Two Means With Different Variances» выделил, условно, 7 гипотез, которые возникают в прикладных исследованиях, от самых редких до самых частых:

Дам пояснение про Behrens-Fisher Problem (пункт 6 на скрине выше), так как именно её мы как раз обсуждаем сейчас: сравнение двух выборочных средних, когда дисперсии распределений, откуда они взяты, возможно разные (или как минимум мы это предполагаем).
Вот что говорит Sawilowsky про эту проблему:
The Behrens-Fisher problem is a classic. Many prestigious mathematical statisticians and applied researchers have addressed this problem. For some, their careers began with this problem; for others, their careers ended with this problem (sic! - прим.). The Behrens-Fisher problem has as much mystique and has received as much fanfare in its discipline.
Далее он говорит в рамках проверяемых гипотез (6c, 6d — проверяем средние, когда известно, что дисперсии не равны; когда не можем предположить, что дисперсии одинаковые, см. картинку выше) следующее:
Now, I discuss two reasons why these situations (6c, 6d) are important, and two reasons why they are irrelevant to applied researchers.
Две причины, которые «irrelevant to applied researches» я пропущу, они не имеют отношения к делу, а вот две про «important» кратко процитирую:
1. Howell and Games (1974) suggested that “Educational and psychological researchers often deal with groups that tend to be heterogeneous in variability” (p. 72). This is mitigated by the fact that, “We have spent many years examining large data sets but have never encountered a treatment or other naturally occurring condition that produces heterogeneous variances while leaving population means exactly equal” (Sawilowsky and Blair, 1992, p. 358). None of Micceri”s (1989) 440 real psychology and education data sets reflected this condition, nor have I seen an example in the literature. Thus, the issue of heterogeneous variances and their impact on Type I errors is moot.
Even if examples can be found, the question remains if the Behrens‑Fisher problem surfaces with such frequency that merits the journal space it has been given”
2. The most prolific treatment outcome in applied studies is known. It is where a change in scale is concomitant with a shift in means. As an intervention is implemented, the means increase or decrease according to the context. Simultaneously, the treatment group may become more homogeneous on the outcome variable due to sharing the same intervention, method, conditions, etc. Alternatively, the group may become more heterogeneous, as some respond to the treatment while others do not respond, or even regress.
То есть, во-первых, в рамках исследований в образовании и психологии, автор никогда не встречался с тем, чтобы дисперсия менялась, а средние не смещались.
Во-вторых, самые плодоносные (prolific) воздействия — это те, что дают сдвиг средних. Более того, дисперсия групп может стать как гетерогенной, так и гомогенной!
Отсюда сложно поверить как раз в то, что могла измениться дисперсия без изменения средних. А с учётом того, что t-test также отловит такие же изменение, что и Welch, ещё и со слегка большей мощностью, что может быть критичнее, то зачем Welch? К тому же, держим этот странный вывод Welch теста при отсутствии стат. значимости, то есть сохранение assumption, что дисперсии не равны…
Однако первому пункту можно попробовать возразить через уже приведённую статью 2017, «Why Psychologists Should by Default Use Welch's t‑test Instead of Student's t‑test», но там есть прям очень важная сноска про то, что они говорят о дисперсии групп, а не популяции:
Like Bryk and Raudenbush (1988), we note that unequal variances between groups does not systematically mean that population variances are different: standard deviation ratios are more or less biased estimates of population variance. Differences can be a consequence of bias in measurement, such as response styles (Baumgartner & Steenkamp, 2001). However, there is no way to determine what part of the variability is due to error rather than the true population value.
Также стоит отметить, что нет упоминаний замеров дисперсии до теста. То есть, в сущности, нам говорят: в группах мы в пост‑хоке наблюдаем различия. Ну и? Они почти никогда и не будут совпадать — именно отсюда ноги у того, почему в scipy.stats.ttest_ind могут и будут ещё не раз менять по неопытности параметр equal_var.
Ещё один аргумент, но в другой плоскости, лежит в области доказательности: когда у нас нет никаких данных (речь в том числе о хоть каких‑то референсах), например, о механизме воздействия в теории, то утверждение, что дисперсия не изменится, предпочтительнее, так как у нас просто нет никаких оснований для обратного высказывания. Обратное же высказывание — «дисперсия изменится» — предполагает наличие хоть каких‑то аргументов, и тут, к сожалению, разумных оснований недостаточно, как бы они ни были соблазнительны. Потому что это не научный метод, а подход, скорее, более близкий к вере. I want to believe, но метод дороже.
Когда дисперсии точно не равны
И всё-таки есть случаи, когда дисперсии различаю. На мой взгляд редкий, но имеющий место случай, когда мы точно не можем предполагать одинаковые дисперсии — и именно тут на малых выборках и/или при диспропорции в выборках имеет смысл тест Welch'a — упоминается в «Preliminary Testing: The Devil of Statistics?»:
Zumbo and Coulombe (1997) warned of at least two scenarios where equal variances cannot be assumed: (1) when the groups of experimental units are assembled based on important differences such as age groups, gender or education level; or (2) when the experimental units differ by an important, maybe unmeasured variable.
1. Отбор в экспериментальную группу тех, кто уже отличается от контрольной можно, просто в этом случае дизайн такой: обеим группам не дают тритмент (или дают сразу двум), тогда сам фактор нагрузки — это различие между группами: возраст — молодые в сравнении со старыми, пол — женщины в сравнении с мужчинами и пр. Да, дисперсия таких групп очень вероятно, что разная. Это к вопросу о разумных предположениях, которые, однако, можно и нужно усилить исследованием предварительных данных. В этом случае это представляется возможным.
2. Слова про «differ by an important, maybe unmeasured variable» о том же, просто определить источник различия между группами сложно, но исследователи согласны, что различие есть. Примеры: представители политических сил в США, республиканцы и демократы, или кто есть кто из главных героев в «Розенкранц и Гильденстерн мертвы».
А может, сохранить предварительные тесты, чтобы потом выбрать Welch или не Welch?
Например, попытавшись решить FWER: family‑wise ошибку 1-го рода? Методы работы с FWER известны: например, та же коррекция Bonferroni. Но вот нужно ли, с учётом замечаний от Sawilowsky? К тому же, поправка должна быть запланирована заранее, вы не можете её сделать после теста (это было бы ошибкой для параметра мощности). То есть вам надо дизайниться с альфой = 0.025, цена этого при сохранении той же мощности известна: размер выборок будет больше. Но если выборка будет больше, то под не скорректированную альфу без preliminar тестов дисперсии может вполне работать уже без сбоев и t‑test. И какой тогда смысл?
Выводы
Вот они:
preliminary test'ы для определения "Welch или не Welch?" не нужны
не использовать Welch's test по дефолту:
Имейте основания считать, что дисперсия изменится (например, у вас разные группы в A/B, и само это различие и есть то, что тестируется) в случае, если у вас разный сплит или/и малые выборки.
Или, как минимум, обратите внимание на ошибку 2-го рода — насколько она для вас может быть критичнее ошибки 1-го рода? Или другими словами: действительно ошибка 1-го рода перевешивает ошибку 2-го рода, которая из без того в стандартных дизайнах составляет 0.2, то в 4 раза больше ошибки 1-го рода!
Поэтому считайте в стандартных ситуациях при всех прочих допущениях t‑test, получайте результат. Но, может, это и хорошо?
В конце концов, меня не покидает давно мысль‑фантазия с учётом постоянных поисков в исследованиях сдвигов среднего, что есть в стат. мире неозвученная нулевая гипотеза: «Нет более базового теста, чем t‑test». Нет способа, в целом, доказать верность этой нулевой гипотезы, но когда раз за разом одни статистики не могут её отклонить, пытаясь придумать замену, а другие собирают, наоборот, данные, наталкивающие их на выводы в духе: «The most prolific treatment outcome in applied studies is known. It is where a change in scale is concomitant with a shift in means» — кажется, что можно быть очень уверенным в верности этой гипотезы. Во всяком случае, ближайшие лет 20–30, как это было с этим тестом предыдущие 100 лет.
Благодарности
Спасибо за ревью Антону Денисову, Егору Мелехину за проверку на понимание, особенно там, где мат. выводы, а также за правки в расчётах.
Также благодарим Анастасию Фёдорову за редакцию материала.
Опорный материал
Кочнев К., 2021, «История одного обмана» или «Требование к распределению в t‑test»e»
Убогоева Е., 2024, Тест Стьюдента и тест Велча
Jack Pearce, Ben Derrick, 2019, “Preliminary Testing: The devil of statistics?”
Moser, B.K. and G.R. Stevens, 1992, “Homogeneity of Variance in the Two Sample Means Test”
Hayes and Cai, 2007, “Further evaluating the conditional decision rule for comparing two independent means”
Zimmermann, 2004, “A note on preliminary tests of equality of variances”
Delacre, 2017, “Why Psychologists Should by Default Use Welch”s t‑test Instead of Student”s t‑test”
S.S. Sawilowsky, 2002, “Fermat, Schubert, Einstein, Behrens‑Fisher: The Probable Difference Between Two Means With Different Variances”