import numpy as np
import scipy.stats as stats
import matplotlib.pyplot as plt
from collections import Counter
from sklearn.model_selection import train_test_split
from IPython.core.display import HTML
HTML("""
<style>
.output_png {
display: table-cell;
text-align: center;
vertical-align: middle;
}
</style>
""")
data = np.sort(np.array([119, 105, 85, 69, 103, 111, 92, 151, 34, 69,
122, 157, 91, 69, 147, 65, 100, 155, 92, 162,
100, 94, 95, 128, 59, 130, 122, 154, 70, 105,
87, 126, 83, 82, 112, 84, 69, 138, 31, 128,
107, 127, 111, 107, 86, 108, 103, 118, 73, 98,
148, 106, 142, 148, 118, 44, 92, 121, 41, 144,
67, 74, 61, 34, 161, 142, 113, 133, 86, 74,
87, 106, 69, 95, 89, 128, 123, 85, 120, 114,
69, 83, 102, 125, 92, 136, 110, 86, 77, 140,
105, 76, 54, 62, 92, 100, 74, 97, 96, 107,
64, 101, 103, 94, 131, 112, 85, 160, 130, 68,
74, 137, 109, 114, 92, 144, 64, 81, 165, 144,
97, 68, 60, 74, 94, 141, 162, 109, 76, 76,
121, 86, 98, 60, 109, 150, 55, 79, 87, 128,
106, 84, 57, 120, 101, 106, 90, 74, 70, 76,
105, 95, 101, 117, 82, 110, 118, 137, 103, 114,
93, 106, 110, 130, 93, 117, 139, 83, 63, 98,
97, 120, 101, 104, 88, 79, 108, 129, 122, 118,
104, 95, 110, 75, 57, 186, 97, 84, 109, 11,
60, 82, 100, 47, 74, 110, 149, 113, 158, 122,
103, 89, 64, 82, 115, 186, 200, 41, 139, 112,
121, 79, 129, 115, 131, 139, 135, 108, 125, 100,
99, 98, 160, 68, 149, 67, 94, 108, 100, 88,
116, 123, 100, 121, 154, 109, 103, 31, 74, 105,
124, 131, 125, 70, 77, 86, 79, 76, 86, 93,
104, 66, 45, 115, 71, 69, 66, 141, 93, 117,
138, 58, 58, 119, 137, 110, 140, 103, 60, 45,
123, 101, 75, 136, 91, 157, 107, 149, 139, 164,
55, 83, 63, 57, 69, 122, 62, 121, 145, 69,
71, 81, 119, 47, 87, 107, 107, 23, 117, 132,
117, 120, 75, 84, 119, 41, 78, 59, 127, 99,
121, 152, 92, 74, 50, 109, 108, 111, 100, 89,]))
n = len(data)
print(f"Количество элементов в выборке =", n)
Количество элементов в выборке = 320
Среднее значение — числовая характеристика множества чисел или функций (в математике); — некоторое число, заключённое между наименьшим и наибольшим из их значений. Среднее, как абстрактная характеристика совокупности, отражает типичный уровень (размер) признака, типичные черты и cвойства всех единиц изучаемой совокупности, поэтому среднее отвлекается (абстрагируется) от индивидуальных особенностей отдельных единиц.
О разновидностях среднего можно прочитать по ссылке.
mean = data.mean()
print(f"Среднее арифметическое = {mean:.2f}")
Среднее арифметическое = 100.86
def harmonic_mean(data: np.ndarray) -> float:
return np.size(data) / np.sum(1.0 / data)
print(f"Среднее гармоническое = {harmonic_mean(data):.2f}")
Среднее гармоническое = 88.37
def geometric_mean(data: np.ndarray) -> float:
return np.exp(np.log(data).mean())
print(f"Среднее геометрическое = {geometric_mean(data):.2f}")
Среднее геометрическое = 95.48
В основе среднего значения лежит закон больших чисел и допущение, что исходая величина распределена нормально. Это подразумевает, что возможные значения сконцентрированы вокруг некоторого наиболее частого значения, а отклонения и в большую, и в меньшую сторону относительно невелики и равновероятны.
В случае отклонения распределения от нормального среднее значение использовать некорректно, так как оно является слишком чувствительным параметром к «выбросам» – нехарактерным для изучаемой выборки, слишком большим или слишком малым значением, поэтому в таких случаях используется медиана.
Медиана – это значение признака, справа и слева от которого находится равное число наблюдений (по 50%). Этот параметр в отличие от среднего значения устойчив к «выбросам». Заметим также, что медиана может использоваться и в случае нормального распределения – в этом случае медиана совпадает со средним значением.
Пусть выборка отсортирована, и размер выборки равен n, тогда:
• Если n - нечетное, то медиана Мe=xMe=xp+1, где p=n−12
• Если n - четное, то медиана Мe=xMe=xp+xp+12, где p=n2
def median(data: np.ndarray) -> float:
return np.median(data)
print(f"Медиана выборки = {median(data)}")
Медиана выборки = 101.0
Мода — значение во множестве наблюдений, которое встречается наиболее часто. (Мода = типичность.)
Иногда в совокупности встречается более чем одна мода (например: 6,2,6,6,8,9,9,9,0; мода — 6 и 9). В этом случае можно сказать, что совокупность мультимодальна. Из структурных средних величин только мода обладает таким уникальным свойством. Как правило, мультимодальность указывает на то, что набор данных не подчиняется нормальному распределению.
Мода как средняя величина употребляется чаще для данных, имеющих нечисловую природу. Среди перечисленных цветов автомобилей — белый, чёрный, синий металлик, белый, синий металлик, белый — мода будет равна белому цвету. При экспертной оценке с её помощью определяют наиболее популярные типы продукта, что учитывается при прогнозе продаж или планировании их производства.
Определяется по формуле: Mo=xi|mi=maxj=¯1,n{mj}
Функция, вычисляющая моду выборки:
def mode(data: np.ndarray) -> np.ndarray:
vals, counts = np.unique(data, return_counts=True)
return vals[np.where(counts == np.max(counts))]
print(f"Мода выборки = {mode(data)}")
Мода выборки = [69 74]
Проверим функцию на корректность. Для этого подсчитаем количество значений в выборке:
Counter(data).most_common(5)
[(69, 9), (74, 9), (100, 8), (92, 7), (103, 7)]
α-квантиль (квантиль порядка α) — это значение уровня, ниже которого лежит определенное число наблюдений, соответствующих выбранной частоте α. Таким образом, α-квантиль — это статистика, равная элементу вариационного ряда с номером [nα+1], где квадратные скобки означают целую часть.
Выделяют следующие квантили:
Квартили — это квантили, кратные 25%.
Выделяют следующие квартили:
Интерквартильный размах — отражает среднюю половину (50%) данных. Вычисляется по формуле:
IQR=Q3−Q1Пример:
Для выборки имеем следующие статистики:
def quantile(data: np.ndarray, quantile: float) -> float:
return int(np.quantile(data, quantile))
Q1 = quantile(data, 0.25)
Q3 = quantile(data, 0.75)
IQR = Q3 - Q1
print(f"Нижний 0.05-квантиль = {quantile(data, 0.05)}",
f"Верхний 0.05-квантиль = {quantile(data, 1 - 0.05)}",
f"Q1 = {Q1}",
f"Q2 = {quantile(data, 0.5)}",
f"Q3 = {Q3}",
f"Интерквартильный размах = {IQR}", sep="\n")
Нижний 0.05-квантиль = 54 Верхний 0.05-квантиль = 152 Q1 = 78 Q2 = 101 Q3 = 121 Интерквартильный размах = 43
Дисперсия случайной величины — мера разброса значений случайной величины относительно её математического ожидания.
Выборочная дисперсия — это оценка теоретической дисперсии распределения, рассчитанная на основе данных выборки.
Дисперсия имеет размерность, равную квадрату размерности признака. Это значит, к примеру, что если признак x измеряется в рублях, то размерность дисперсии - [руб2], что является её недостатком.
Под выборочной дисперсией часто понимают неисправленную (смещенную) выборочную дисперсию. Её формула равна:
S2=1nn∑i=1(xi−¯x)2Однако чаще используется формула: S2=1nn∑i=1x2i−(n∑i=1xi)2=¯x2−¯x2
var = np.var(data) # var == variance
print(f"Выборочная неисправленная дисперсия = {var:.2f}")
Выборочная неисправленная дисперсия = 944.74
Если в качестве оценки генеральной дисперсии принять выборочную дисперсию Dв, то эта оценка будет приводить в систематическим ошибкам, давая заниженное значение генеральной дисперсии Dг. Объясняется это тем, что, как можно доказать, выборочная дисперсия является смещенной оценкой, другими словами, математическое ожидание выборочной дисперсии не равно оцениваемой генеральной дисперсии, а равно:
M[Dв]=nn−1DгЛегко исправить выборочную дисперсию так, чтобы ее математическое ожидание было равно генеральной дисперсии. Достаточно для этого умножить Dв на дробь nn−1. Получим формулу исправленной выборочной дисперсии: ˆS2=nn−1S2=1n−1n∑i=1(xi−¯x)2
Исправленная дисперсия является несмещенной оценкой генеральной дисперсии. Действительно:
M[ˆS2]=M[nn−1Dг]=nn−1M[Dв]=nn−1⋅n−1nDг=Dгunbiased_var = np.var(data, ddof=1)
print(f"Выборочная исправленная дисперсия = {unbiased_var:.2f}")
Выборочная исправленная дисперсия = 947.71
Чтобы избавиться от квадрата размерности признака в дисперсии, была введена такая статистическая характеристика, как стандартное (среднее квадратическое) отклонение. Формула имеет вид: S=√S2
Стандартное отклонение, подобно дисперсии, также может быть смещенным и несмещенным. Вычислим смещенное стандартное отклонение:
std = np.std(data) # == np.sqrt(var)
print(f"Смещенное стандартное отклонение = {std:.2f}")
Смещенное стандартное отклонение = 30.74
А также несмещенное стандартное отклонение:
unbiased_std = np.std(data, ddof=1)
print(f"Несмещенное стандартное отклонение = {unbiased_std:.2f}")
Несмещенное стандартное отклонение = 30.78
Стандартная ошибка — величина, которая характеризует стандартное (среднеквадратическое) отклонение выборочного среднего. Другими словами, эту величину можно использовать для оценки точности выборочного среднего. Цель этой метрики — помочь определить границы в которых может варьироваться истинное среднее для всей генеральной совокупности на основе некоторой выборки.
Чем больше разброс данных, тем больше стандартная ошибка средней – прямо пропорциональная зависимость.
Стандартная ошибка среднего рассчитывается по формуле: SEM=S√n
def sem(data):
return np.std(data) / np.sqrt(np.size(data))
print(f"Стандартная ошибка среднего = {sem(data):.2f}")
Стандартная ошибка среднего = 1.72
Коэффициент вариации (относительное стандартное отклонение) — мера относительного разброса случайной величины. Показывает, какую долю среднего значения этой величины составляет её средний разброс. Он применяется для сравнения вариативности одного и того же признака в нескольких совокупностях с различным средним арифметическим.
Формула коэффициента вариации: VS=S¯x
Однако чаще используется представление в процентах: VS=S¯x⋅100%
def variation(data: np.ndarray, in_percents=False) -> float:
cv = np.std(data) / np.mean(data)
return cv * 100 if in_percents else cv
print(f"Коэффициент вариации = {variation(data, True):.2f}%")
Коэффициент вариации = 30.47%
Момент k-го порядка — среднее арифметическое k-й степени отклонения наблюдаемых значений xi=(i=1,2,…,n) от некоторой постоянной c, то есть: μ(c)k=n∑i=1(xi−c)k
Центральные моменты третьего и четвертого порядков обычно используются не сами по себе, а для расчета коэффициентов асимметрии и эксцесса.
Коэффициет ассиметрии — величина, характеризующая асимметрию (скошенности) распределения случайной величины.
Определяется по формуле: Ac=μ3S3
Если |Ac|>0.5, то ассиметрия существенна.
skewness = stats.skew(data, bias=False)
print(f"Коэффициент ассиметрии = {skewness:.2f}")
Коэффициент ассиметрии = 0.10
Коэффициент эксцесса — мера остроты пика распределения случайной величины.
Определяется по формуле: Ek=μ4S4−3
kurtosis = stats.kurtosis(data, bias=False)
print(f"Коэффициент эксцесса = {kurtosis:.4f}")
Коэффициент эксцесса = 0.0227
Ящик с усами, диаграмма размаха (англ. box-and-whiskers diagram or plot, box plot) — график, использующийся в описательной статистике, компактно изображающий одномерное распределение вероятностей.
Такой вид диаграммы в удобной форме показывает медиану (или, если нужно, среднее), нижний и верхний квартили, минимальное и максимальное значение выборки и выбросы. Несколько таких ящиков можно нарисовать бок о бок, чтобы визуально сравнивать одно распределение с другим; их можно располагать как горизонтально, так и вертикально. Расстояния между различными частями ящика позволяют определить степень разброса (дисперсии) и асимметрии данных и выявить выбросы.
Сравнение плотности распределения и ящика с усами:
Сопоставление нормального распределения и ящика с усами:
Построим ящик с усами для исходной выборки:
box_plt = plt.boxplot(data, vert=False)
plt.show()
Выброс (англ. outlier) — резко отклоняющееся значение наблюдаемой величины. Выбросом считается наблюдение, которое лежит аномально далеко от остальных из серии параллельных наблюдений.
Поскольку множество статистических методов «буксуют» на выборках с выбросами, выбросы приходится обнаруживать (желательно — автоматически) и исключать из выборки. Простейшие способы основаны на межквартильном расстоянии — например, считать выбросами всё, что не попадает в диапазон: [Q1−1.5⋅IQR,Q3+1.5⋅IQR]
Более тонкие критерии — критерий Шовене, критерий Граббса, критерий Пирса, критерий Диксона.
Получим выбросы исходной выборки, используя межквартильное расстояние:
print("Выбросы исходной выборки =",
data[(data < Q1 - 1.5 * IQR) | (data > Q3 + 1.5 * IQR)])
Выбросы исходной выборки = [ 11 186 186 200]
Также можно получить выбросы, используя объект boxplot
:
outliers = box_plt["fliers"][0].get_data()[0]
print("Выбросы исходной выборки =",
outliers)
Выбросы исходной выборки = [ 11 186 186 200]
del box_plt, outliers
Сгруппированным интервальным (непрерывным) вариационным рядом называют ранжированные по значению признака интервалы (ai≤x<bi), где i=1,2,⋯,k, указанные вместе с соответствующими частотами mi числа наблюдений, попавших в i-й интервал или относительными частотами min.
Построение интервального вариационного ряда начинают с определения числа k, обозначающее количество интервалов. Оно должно быть оптимальным. Если оно будет малым, то гистограмма получется слишком сглаженной (oversmoothed) и потеряет все особенности изменчивости данных. Если будет большим, то мы не сможем оценить плотность распределения изучаемых данных по числовой оси: гистограмма получится недосглаженная (undersmoothed), с незаполненными интервалами, неравномерная.
Чаще всего для определения числа k используется формула Стёрджеса:
k=1+⌊log2n⌋=1+⌊3,22lgn⌋где ⌊…⌋ — округление вниз до целого;
Алгоритм построения интервального ряда получается следующим:
# Правило Стёрджеса -> оптимальное число бинов в гистограмме
def sturges(arr: np.ndarray) -> int:
return int(1 + np.floor(np.log2(len(arr))))
occur, intervals = np.histogram(data, bins=sturges(data))
print(f"Оптимальное количество интервалов = {sturges(data)}",
f"Получившийся интервальный ряд = {intervals}", sep="\n")
Оптимальное количество интервалов = 9 Получившийся интервальный ряд = [ 11. 32. 53. 74. 95. 116. 137. 158. 179. 200.]
Эмпирическая функция распределения (функция распределения выборки) — функция, которая определяет для каждого значения x частоту событий X<x и предназначена для оценки теоретической функции распределения генеральной совокупности в математической статистике.
Эмпирическая функция распределения находится по формуле: Fn=nxn
Функция распределения Fx генеральной совокупности называется теоретической функцией распределения. Отличие эмпирической функции от теоретической состоит в том, что теоретическая функция определяет вероятность события X<x, а эмпирическая стремится к ней при большом количестве испытаний.
Несколько примеров плотностей вероятности и функций распределения:
Вычислим эмпирическую функцию распределения для исходной выборки:
# Эмпирическая функция распределения
def ecdf(X: np.ndarray, size: int = None) -> np.ndarray:
return np.arange(1, len(X) + 1) / len(X) if size is None else np.arange(1, len(X) + 1) / size
plt.step(data, ecdf(data))
plt.ylabel('$F_n$', fontsize=20)
plt.xlabel('$x$', fontsize=20)
plt.show()
# Гистограмма
plt.hist(data, bins=sturges(data), density=True)
# Нормальное распределение
x_pdf = np.linspace(np.min(data), np.max(data), 1000)
y_pdf = stats.norm.pdf(x_pdf, loc=mean, scale=std)
plt.plot(x_pdf, y_pdf, lw=4, c='r')
plt.show()
Заметим, что данные исходной выборки распределены нормально
QQ-plot (график квантиль-квантиль) — графический метод определения принадлежности выборки определенному распределению, дополнительно позволяющий:
stats.probplot(data, dist="norm", plot=plt)
plt.show()
Критерий ассиметрии и эксцесса мы уже рассчитывали выше. Они получились достаточно близки к нулю:
print(f"Коэффициент ассиметрии = {skewness:.2f}",
f"Коэффициент эксцесса = {kurtosis:.2f}", sep="\n")
Коэффициент ассиметрии = 0.10 Коэффициент эксцесса = 0.02
Так как критерии ассиметрии и эксцесса могут иметь место и для распределений, отличных от нормального, то этот критерий следует воспринимать как критерий установления отклонения от нормальности распределения, но не установления нормальности.
del skewness, kurtosis
Критерием согласия называется метод проверки гипотезы о предполагаемом законе неизвестного распределения.
Критерий согласия — алгоритм, предназначенный для проверки гипотезы H0 о том, что ряд наблюдений x1,x2,⋯xn образует случайную выборку, извлеченную из генеральной совокупности X с функцией распределение F(x)=F(x,θ):
H0:Fn(x)=F(x,θ)где Fn(x) эмпирическая функция распределения, θ=(θ1,θ2,⋯,θk) — вектор параметров. Общий вид функции F(x,θ) считается известным, а параметры θ1,θ2,⋯,θk могут быть как известными, так и неизвестными.
Большинство критериев согласия основаны на использовании различных мер расстояний между анализируемой эмпирическое функцией Fn(x) распределения, определенной по выборке, и функцией распределения F(x,θ) генеральной совокупности X
α-уровень (уровень значимости) — пороговый уровень статистической значимости; вероятность ошибочно отклонить нулевую гипотезу. Чем меньше α-уровень, тем меньше риск совершения этой ошибки. Устанавливается исследователем произвольно (обычно принимается равным 0.05, 0.01 или 0.001). Примем уровень значимости равным 0.05:
confidence = 0.05
Данный критерий служит для проверки гипотезы о том, что генеральная совокупность, из которой извлечена выборка, имеет заданный закон распределения. Применяется при объемах выборки n≥50.
Пусть имеется выборка {xi}ni=1 объема n. Необходимо проверить гипотезу о том, что выборка была извлечена из генеральной совокупности, распределенной по закону с функцией распределения F(x,θ): H0:Fn(x)=F(x,θ)
где θ — известный вектор параметров теоретического закона
По выборке {xi}ni=1 получим эмпирическое распределение в виде дискретного или интервального вариационного ряда:
где mi - количество наблюдений в i-м интервале.
Обозначим через pi вероятности попадания i-й интервал (i=¯1,k), соответствующие теоретическому закону с функцией распределения F(x,θ):
pi=P(ai<x<bi)=F(bi,θ)−F(ai,θ)Вероятности pi можно рассматривать как теоретические частости: pi=m′in
Величины m′i можно рассматривать как теоретические частоты, т.е. количества элементов выборки, которые должны были попасть в каждый интервал, если бы случайная величина имела выбранный закон распределения F(x,θ), параметры которого совпадают с их то тчечными оценками по выборке.
Каждая из величин mi−m′i√m′i
представляет собой относительное отклонение частоты от теоретической частоты и имеет стандартное нормальное распределение. Соответственно, сумма квадратов этих величин имеет распределение хи-квадрат.
Справедлива следующая теорема.
Теорема. Величина χ2n=k∑i=1(mi−npi)2npi=k∑i=1(mi−m′i)2m′i
является случайной и, если верна проверяемая гипотеза H0:Fn(x)=F(x,θ), распределена по закону χ2 с числом степеней свободы v=k−1−r, где k — число частичных интервалов выборки, r — число параметров преполагаемого распределения.
Далее вычисляем теоретическое (истинное) χ2v;α для заданной вероятности α:
χ2v;α|P(χ2>χ2v;α)=αТо есть χ2v;α — α-квантиль распределения хи-квадрат. Его также называют критическим значением и находят по таблицам распределения χ2.
Гипотеза H0 отвергается на уровне значимости α, если вычисленное значение χ2n окажется больше критического χ2v;α:
χ2n>χ2v;αГеометрически это означает, что χ2n попадает в правостороннюю критическую область, граница которой при заданном уровне значимости α равна χ2v;α
Иногда оценивается вероятность получить значение статистики χ2n:
p_value=P(χ2>χ2n)Если p_value<α, то гипотеза H0 отвергается.
Для проверки гипотезы о нормальном законе распределения находим вероятности по формуле: pi=p(xi<x<xi+1)=Φ(xi+1−¯xS)−Φ(xi−¯xS)
Поскольку нормальное распределение характеризуется 2 параметрами μ и σ, то r=2 и число степеней свободы v=n−3.
Вычислим теоретические частоты m′i для исходной выборки:
cdf = stats.norm.cdf
m_t = [(cdf(intervals[i+1], mean, std) - cdf(intervals[i], mean, std)) * n
for i in range(len(intervals) - 1)]
print(f"Теоретические частоты = {m_t}")
Теоретические частоты = [3.4568097474664263, 15.098115892487069, 42.03427772166201, 74.65478800282929, 84.62272793942867, 61.226142268367205, 28.267755294164374, 8.32308541501277, 1.5614375004549785]
Затем вычислим значение χ2n по формуле:
chi_sq = np.sum((occur - m_t) ** 2 / m_t)
print(f"Хи-квадрат = {chi_sq:.3f}")
Хи-квадрат = 4.011
Получим критическое значение χ2v;α, используя функцию chi2.ppf
из модуля scipy.stats
:
crit_val = stats.chi2.ppf(1 - confidence, sturges(data) - 3)
print(f"Критическое значение = {crit_val:.3f}")
Критическое значение = 12.592
Таким образом, неравенство χ2n>χ2v;α не выполняется. Следовательно, гипотеза H0 о нормальности распределения не отвергается.
Если невозможно эффективно применять хи-квадрат на маленьких выборках, то в таких случаях часто используется критерий Колмогорова. Данный критерий также предназначен для проверки простых гипотез о принадлежности анализируемой выборки некоторому полностью известному параметрическому закону распределения.
Применяется критерий Колмогора по следующей схеме:
Строится эмпирическая функция Fn(x):
Определяется мера расхождения между теоретическим и эмпирическим распределением по формуле Dn=maxi|Fn(xi)−F(xi)| и вычисляется величина: kn=√nDn
Находится критическое значение kα. Значение можно найти в соответствующих таблицах или приблизительно рассчитать по формуле:
Реализуем функции, необходимые для проверки нулевой гипотезы о принадлежности выборки нормальному распределнию критерием Колмогорова:
# Теоретическая функция нормального распределения
def tcdf(X: np.ndarray) -> np.ndarray:
return np.array([cdf(x, loc=X.mean(), scale=X.std()) for x in X])
# Мера расхождения между теоретической и эмпирической функцией
def Dn(Ft: np.ndarray, Fx: np.ndarray) -> float:
return np.max(np.abs(Ft - Fx))
# Статистика критерия Колмогорова
def kn(Dn: float, n: int) -> float:
return np.sqrt(n) * Dn
# Критическое значение для статистики критерия Колмогорова
def k_conf(confidence: float) -> float:
return np.sqrt(0.5 * np.log(2 / confidence))
# Конвертация в стандартное нормальное распределение
def to_std_norm_dist(X: np.ndarray) -> np.ndarray:
return (X - X.mean()) / X.std()
В соответствии со схемой последовательно воспользуемся ими. Вычислим Dn:
print(f"Мера расхождения Dn = {Dn(tcdf(data), ecdf(data)):.3f}")
Мера расхождения Dn = 0.031
Вычислим статистику критерия Колмогорова kn и критическое значение kα:
print(f"Статистика Колмогорова kn = {kn(Dn(tcdf(data), ecdf(data)), n):.3f}")
print(f"Критическое значение k_confidence = {k_conf(0.05):.3f}")
Статистика Колмогорова kn = 0.561 Критическое значение k_confidence = 1.358
Таким образом, неравенство kn>kα не выполняется. Следовательно, гипотеза нормальности нормальности распределения не отвергается.
Проверим правильность вычислений с помощью функции kstest
из scipy.stats
:
print("Мера расхождения Dn = {:.3f} \np_value = {:.3f}".format(*stats.kstest(to_std_norm_dist(data), 'norm')))
Мера расхождения Dn = 0.031 p_value = 0.902
Меры расхождения Dn равны и p_value>α=0.05. Таким образом, гипотеза о нормальности распределения также не отвергается.
Критерий Шапиро-Уилка предназначен для проверки на нормальность распределения выборок, численностью от 3 до 50. В отличии от критериев Пирсона и Колмогорова, критерий Шапиро–Уилка может быть использовал лишь для проверки распределения на нормальность.
Пусть имеется выборка (x1,x2,⋯,xn), где 3≤n≤50. Вычисления производятся по формуле:
W=b2S2где S2=n∑i=1(xi−¯x)2 — квадрат оценки среднеквадратического отклонения Ллойда; b=k∑i=1an−i+1(xn−i+1−xi); k=n2, eсли n - четное, иначе k=n−12; an−i+1(i=1,⋯,k) — известные константы, которые вычисляются, либо берутся из заданных таблиц:
Если W<W(α), то нулевая гипотеза нормальности распределения отклоняется на уровне значимости α. Значения W(α) также приводятся в таблицах:
Полные таблицы приведены в книге Кобзарь А.И. — Прикладная математическая статистика. Для инженеров и научных работников.
Вычислим W для первых десяти значений в отсортированной исходной выборке:
N = 10
a = np.array([0.5739, 0.3291, 0.2141, 0.1224, 0.0399])
b = np.sum([a[i] * (data[N-i-1] - data[i]) for i in range(N // 2)])
W = b**2 / (N * np.var(data[:N]))
print(f"W = {W:.3f}")
W = 0.879
Если принять уровень значимости α равным 0.05, то, используя прикрепленную выше таблицу, можно найти значение W(α). Видим, что при n=10 и α=0.05: W(α)=0.842
Таким образом, неравенство W<W(α) не выполняется. Следовательно, гипотеза нормальности распределения принимается.
Посчитаем также критерий Шапиро-Уилка с использованием функции shapiro
из scipy.stats
:
stats.shapiro(data[:10])
ShapiroResult(statistic=0.8784602880477905, pvalue=0.12528105080127716)
Заметим, что функция возвращает ещё один параметр p_value. Если p_value<α, то гипотеза отвергается.
В нашем случае 0.125≮0.05, что также подтвержает гипотезу нормальности распределения.
del a, b, N
Доверительный интервал для неизвестной генеральной дисперсии имеет следующий вид:
((n−1)⋅S2χ2l(α);(n−1)⋅S2χ2r(α))где S2 — исправленная выборочная дисперсия, χ2 — распределения с n−1 степенью свободы, причем в таблице ищем α2 и 1−α2 соответственно.
chi_l = stats.chi2.ppf(confidence / 2, n - 1)
chi_r = stats.chi2.ppf(1 - confidence / 2, n - 1)
D_conf_interval = ((n - 1) * unbiased_var / chi_r, (n - 1) * unbiased_var / chi_l)
print("Доверительный интервал для дисперсии:",
"({:.2f}, {:.2f})".format(*D_conf_interval))
Доверительный интервал для дисперсии: (816.25, 1113.86)
Использовать данные, полученные в пункте 7
Доверительный интервал для среднего с известной дисперсией имеет вид:
(¯x−σ√n⋅zα;¯x+σ√n⋅zα)где σ — выборочное несмещенное стандартное отклонение, zα — квантиль нормального распределения уровеня 1−α2
или
(¯x−Δ;¯x+Δ)где Δ=σ√n⋅zα;
Чтобы вычислить выборочное несмещенное стандартное отклонение, извлечем корень из уже вычисленной исправленной (несмещенной) дисперсии:
unbiased_std = np.sqrt(unbiased_var)
Вычислим Δ и получим доверительные интервалы для неизвестного генерального среднего:
delta = stats.distributions.norm.ppf(1 - confidence / 2) * unbiased_std / np.sqrt(n)
E_conf_interval = mean - delta, mean + delta
print("Доверительный интервал для неизвестного генерального среднего:",
"({:.2f}, {:.2f})".format(*E_conf_interval))
Доверительный интервал для неизвестного генерального среднего: (97.49, 104.24)
Проверим полученные результаты с использованием встроенных функций:
def confidence_interval(data: np.ndarray, conf: float = 0.95) -> tuple[float, float]:
return stats.t.interval(conf, len(data)-1, data.mean(), stats.sem(data))
print("Доверительный интервал для неизвестного генерального среднего:",
"({:.2f}, {:.2f})".format(*confidence_interval(data)))
Доверительный интервал для неизвестного генерального среднего: (97.48, 104.25)
Если выборка больше 30, но стандартное отклонение нам неизвестно, то вместо σ мы будем использовать выборочное стандартное отклонение:
s=√1n−1n∑i=1(xi−¯x)2Таким образом, доверительный интервал для среднего при неизвестной дисперсии, но большой выборке (n>30), имеет вид:
(¯x−s√nzα;¯x+s√nzα)s = np.sqrt(np.sum((data - mean) ** 2) / (n - 1))
delta = stats.norm.ppf(1 - confidence / 2) * s / (n ** 0.5)
E_conf_interval = (mean - delta, mean + delta)
print("Доверительный интервал для неизвестного генерального среднего:",
"({:.2f}, {:.2f})".format(*E_conf_interval))
Доверительный интервал для неизвестного генерального среднего: (97.49, 104.24)
sample_1, sample_2 = train_test_split(data, train_size=0.55, random_state=0)
n1, n2 = len(sample_1), len(sample_2)
print(f"Размерность выборок = {(n1, n2)}")
Размерность выборок = (176, 144)
Критерий Колмогорова-Смирнова используется для проверки гипотезы об однородности выборок, то есть гипотезу о том, что рассматриваемые выборки извлечены из одной и той же генеральной совокупности:
H0:F1(x)=F2(x)Статистика критерия Колмогорова-Смирнова имеет вид:
kn,m=√nmn+m⋅Dn,m=√nmn+m⋅supx|Fn(x)−Fm(x)|где Fn(x) и Fm(x) — эмпирические функции распределения, построенные по двум выборкам с объемами n и m.
Если kn,m>kα, то нулевая гипотеза однородности выборок отклоняется на уровне значимости α.
Напишем ряд функций, позволяющих вычислить статистику критерия Колмогорова-Смирнова:
# Частотности
def freq(data: np.ndarray, ranges: np.ndarray) -> np.ndarray:
return np.unique(np.digitize(data, ranges), return_counts=True)[1]
# Выборочная эмпирическая функция распределения
def samp_ecdf(data: np.ndarray, ranges: np.ndarray) -> np.ndarray:
return np.cumsum(freq(data, ranges)) / len(data)
# Статистика критерия Колмогорова-Смирнова
def k_stat(data1: np.ndarray, data2: np.ndarray, ranges: np.ndarray) -> float:
n, m = len(data1), len(data2)
F1, F2 = samp_ecdf(data1, ranges), samp_ecdf(data2, ranges)
return Dn(F1, F2) * np.sqrt(n * m) / (n + m)
Вычислим статистику критерия Колмогорова-Смирнова:
print(f"Статистика критерия Колмогорова-Смирнова = {k_stat(sample_1, sample_2, intervals):.3f}")
Статистика критерия Колмогорова-Смирнова = 0.024
Вычислим критическое значение kα, воспользовавшись уже реализованной в критерии Колмогорова функцией:
print(f"Критическое значение k_alpha = {k_conf(confidence):.3f}")
Критическое значение k_alpha = 1.358
Таким образом, неравенство kn,m>kα не выполняется. Следовательно, нулевая гипотеза однородности двух выборок принимается.
Для проверки выборок на равенство дисперсий воспользуемся критерием Фишера.
Критерий Фишера (F-test): Нулевая гипотеза H0:σ21=σ22 принимается на уровне значимости α, если выполняется неравенство:
F(1−α2;k1;k2)≤F≤F(α2;k1;k2)где k1=n1−1; k2=n2−1; n1, n2 — объем первой и второй выборки соответственно; α — уровень значимости; F=S21S22 — отношение несмещенных выборочных дисперсий; F(1−α2;k1;k2) — верхний квантиль уровня 1−α2 распределения Фишера-Снедекора (т.е. соответствует нижнему квантилю уровня α2); F(α2;k1;k2) — верхний квантиль уровня α2 распределения Фишера-Снедекора.
Вычислим статистику F-теста:
F = np.var(sample_1, ddof=1) / np.var(sample_2, ddof=1)
print(f"F = {F:.3f}")
F = 1.052
Рассчитаем число степеней свобод k1 и k2:
k1 = n1 - 1
k2 = n2 - 1
Вычислим квантили распределения Фишера-Снедекора, используя встроенную в scipy.stats
функцию f.ppf
:
F1 = stats.f.ppf(confidence / 2, k1, k2)
F2 = stats.f.ppf(1 - confidence / 2, k1, k2)
print(f"F1 = {F1:.3f}", f"F = {F:.3f}", f"F2 = {F2:.3f}", sep='\n')
F1 = 0.733 F = 1.052 F2 = 1.372
Таким образом, неравенство F(1−α2;k1;k2)≤F≤F(α2;k1;k2) выполняется. Следовательно, гипотеза о равенстве дисперсий двух выборок принимается.
Дисперсии неизвестны, но равны
Выполним проверку гипотезы о равенстве средних, используя t-критерий Стьюдента при условии, что дисперсии двух величин неизвестны, но равны.
Объединим две выборки в одну и определим для неё смешанную выборочную дисперсию по формуле:
S2=(n1−1)⋅S21+(n2−1)⋅S22(n1−1)+(n2−1)=(n1−1)⋅S21+(n2−1)⋅S22n1+n2−2где S21 и S22 — несмещенные оценки дисперсий двух величин.
mixed_var = ((n1 - 1)*np.var(sample_1, ddof=1) + (n2 - 1)*np.var(sample_2, ddof=1)) / (n1 + n2 - 2)
print(f"Смешанная выборочная дисперсия S2 = {mixed_var:.3f}")
Смешанная выборочная дисперсия S2 = 950.326
Для проверки гипотезы H0 вычислим значение статистики Стьюдента:
tn1+n2−2=¯x−¯y√S2n1+S2n2=¯x−¯yS√1n1+1n2t = (np.mean(sample_1) - np.mean(sample_2)) / np.sqrt(mixed_var / n1 + mixed_var / n2)
print(f't = {t:.4f}')
t = 0.3470
Далее вычислим p_value для полученного значения:
p_value = 2 * (1 - stats.t.cdf(t, n1 + n2 - 2))
print(f"p_value = {p_value:.3f}")
p_value = 0.729
Таким образом, неравенство p_value>α выполняется. Следовательно, нулевая гипотеза о равенстве средних двух выборок не отвергается.
Проверим вычисления с использованием встроенной в scipy.stats
функции ttest_ind
:
_, p_value = stats.ttest_ind(sample_1, sample_2)
print(f"p_value = {p_value:.3f}")
p_value = 0.729