Некоторые исправления (спасибо моей Ритке :)

This commit is contained in:
2025-06-07 11:23:04 +03:00
parent 2064ae46b0
commit 85fc09ad29
3 changed files with 718 additions and 300 deletions

View File

@@ -541,7 +541,7 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 9,
"id": "72be1710",
"metadata": {},
"outputs": [
@@ -588,7 +588,7 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 23,
"id": "bd170677",
"metadata": {},
"outputs": [
@@ -596,50 +596,179 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Хи-квадрат статистика: 2.7737\n",
"Критическое значение: 13.3882\n",
"p-value: 0.7348\n",
"Не отвергаем H0: распределение нормальное\n"
"Оценка μ (среднее остатков): -0.0000\n",
"Оценка σ (стандартное отклонение отстатков): 2.3980\n",
"[ 5 8 15 8 14] [ 5.312141 8.34056556 11.88152698 11.5684878 12.28662505]\n",
"\n",
"Результаты после объединения интервалов:\n",
"Интервалы\t\tНаблюдаемо\tОжидаемо\tВклад в χ²\n",
"[-5.9095, -2.9020]\t 5 \t5.31\t\t0.0183\n",
"[-2.9020, -1.3982]\t 8 \t8.34\t\t0.0139\n",
"[-1.3982, 0.1055]\t 15 \t11.88\t\t0.8185\n",
"[0.1055, 1.6093]\t 8 \t11.57\t\t1.1008\n",
"[1.6093, 6.1205]\t 14 \t12.29\t\t0.2389\n",
"\n",
"Количество интервалов после объединения: 5\n",
"Степени свободы: 2 (5 интервалов - 1 - 2 оцененных параметра)\n",
"Статистика χ²: 2.1904\n",
"Критическое значение (α=0.02): 7.8240\n",
"p-value: 0.3345\n",
"Не отвергаем H₀: распределение нормальное\n"
]
}
],
"source": [
"# Разбиение на интервалы (используем 6 интервалов для примера)\n",
"import numpy as np\n",
"from scipy.stats import chi2, norm\n",
"# Вычисление параметров нормального распределения\n",
"mu = np.mean(residuals) # Среднее остатков\n",
"std = np.std(residuals, ddof=1) # Стандартное отклонение (несмещенное)\n",
"print(f\"Оценка μ (среднее остатков): {mu:.4f}\")\n",
"print(f\"Оценка σ (стандартное отклонение отстатков): {std:.4f}\")\n",
"\n",
"# Разбиение на интервалы\n",
"observed_freq, bins = np.histogram(residuals, bins=8)\n",
"n = len(residuals)\n",
"n_bins = len(observed_freq)\n",
"\n",
"# Ожидаемые частоты для нормального распределения\n",
"expected_freq = []\n",
"# Вычисление ожидаемых частот\n",
"expected_freq = np.zeros(n_bins)\n",
"for i in range(n_bins):\n",
" bin_start = bins[i]\n",
" bin_end = bins[i+1]\n",
" cdf_start = norm.cdf(bin_start, mu, std)\n",
" cdf_end = norm.cdf(bin_end, mu, std)\n",
" expected_freq.append(len(residuals) * (cdf_end - cdf_start))\n",
" cdf_start = norm.cdf(bins[i], mu, std)\n",
" cdf_end = norm.cdf(bins[i+1], mu, std)\n",
" expected_freq[i] = n * (cdf_end - cdf_start)\n",
"\n",
"# Объединение интервалов с expected_freq < 5\n",
"observed_list = observed_freq.tolist()\n",
"expected_list = expected_freq.tolist()\n",
"bins_list = bins.tolist()\n",
"\n",
"# i = 0\n",
"# while i < len(expected_list):\n",
"# if expected_list[i] < 5:\n",
"# # Если последний интервал, объединить с предыдущим\n",
"# if i == len(expected_list) - 1:\n",
"# if i > 0: # Если есть предыдущий интервал\n",
"# expected_list[i-1] += expected_list[i]\n",
"# observed_list[i-1] += observed_list[i]\n",
"# del expected_list[i]\n",
"# del observed_list[i]\n",
"# del bins_list[i+1]\n",
"# i -= 1 # Вернуться к новому интервалу\n",
"# else:\n",
"# # Объединить с следующим интервалом\n",
"# expected_list[i] += expected_list[i+1]\n",
"# observed_list[i] += observed_list[i+1]\n",
"# del expected_list[i+1]\n",
"# del observed_list[i+1]\n",
"# del bins_list[i+1]\n",
"# else:\n",
"# i += 1\n",
"i = 0\n",
"while i < len(expected_list):\n",
" if expected_list[i] < 5:\n",
" if i == len(expected_list) - 1: # последний интервал\n",
" if i > 0:\n",
" expected_list[i-1] += expected_list[i]\n",
" observed_list[i-1] += observed_list[i]\n",
" del expected_list[i]\n",
" del observed_list[i]\n",
" del bins_list[i] # ← исправлено\n",
" i -= 1\n",
" else: # объединяем с правым\n",
" expected_list[i] += expected_list[i+1]\n",
" observed_list[i] += observed_list[i+1]\n",
" del expected_list[i+1]\n",
" del observed_list[i+1]\n",
" del bins_list[i+1] # граница между i и i+1\n",
" else:\n",
" i += 1\n",
"\n",
"\n",
"# Проверка минимального количества интервалов\n",
"if len(expected_list) < 3:\n",
" # Если интервалов меньше 3, принудительно объединяем все интервалы\n",
" expected_list = [sum(expected_list)]\n",
" observed_list = [sum(observed_list)]\n",
" bins_list = [bins[0], bins[-1]]\n",
" print(\"Внимание: после объединения остался только 1 интервал!\")\n",
"\n",
"# Преобразование в массивы NumPy\n",
"observed_merged = np.array(observed_list)\n",
"expected_merged = np.array(expected_list)\n",
"\n",
"# Расчет статистики хи-квадрат\n",
"chi2_stat = np.sum((observed_merged - expected_merged)**2 / expected_merged)\n",
"\n",
"# Степени свободы\n",
"k = len(observed_merged) # Количество интервалов после объединения\n",
"dof = k - 1 - 2 # k-1 интервалов минус 2 оцененных параметра (μ и σ)\n",
"if dof < 1:\n",
" dof = 1 # Минимум 1 степень свободы\n",
"\n",
"# Критерий хи-квадрат\n",
"chi2_stat = sum((observed_freq - expected_freq)**2 / expected_freq)\n",
"dof = n_bins - 1 - 2 # 2 параметра (mu, std) оценены по данным\n",
"alpha = 0.02\n",
"critical_value = chi2.ppf(1 - alpha, dof)\n",
"p_value = 1 - chi2.cdf(chi2_stat, dof)\n",
"print(observed_merged, expected_merged)\n",
"# Вывод результатов\n",
"print(\"\\nРезультаты после объединения интервалов:\")\n",
"print(\"Интервалы\\t\\tНаблюдаемо\\tОжидаемо\\tВклад в χ²\")\n",
"\n",
"print(f\"Хи-квадрат статистика: {chi2_stat:.4f}\")\n",
"print(f\"Критическое значение: {critical_value:.4f}\")\n",
"for i in range(len(observed_merged)):\n",
" lower = bins_list[i]\n",
" upper = bins_list[i+1]\n",
" contrib = (observed_merged[i] - expected_merged[i])**2 / expected_merged[i]\n",
" print(f\"[{lower:.4f}, {upper:.4f}]\\t{observed_merged[i]:^12}\\t{expected_merged[i]:.2f}\\t\\t{contrib:.4f}\")\n",
"\n",
"print(f\"\\nКоличество интервалов после объединения: {k}\")\n",
"print(f\"Степени свободы: {dof} (5 интервалов - 1 - 2 оцененных параметра)\")\n",
"print(f\"Статистика χ²: {chi2_stat:.4f}\")\n",
"print(f\"Критическое значение (α={alpha}): {critical_value:.4f}\")\n",
"print(f\"p-value: {p_value:.4f}\")\n",
"\n",
"# Визуальная оценка\n",
"# Проверка гипотезы\n",
"if chi2_stat > critical_value:\n",
" print(\"Отвергаем H0: распределение не нормальное\")\n",
" print(\"Отвергаем H: распределение не нормальное\")\n",
"else:\n",
" print(\"Не отвергаем H0: распределение нормальное\")"
" print(\"Не отвергаем H: распределение нормальное\")\n",
"\n",
"\n",
"# # Разбиение на интервалы (используем 6 интервалов для примера)\n",
"# mu = np.mean(residuals) # Среднее остатков\n",
"# std = np.std(residuals, ddof=1) # Стандартное отклонение (несмещенное)\n",
"# observed_freq, bins = np.histogram(residuals, bins=8)\n",
"# n_bins = len(observed_freq)\n",
"\n",
"# # Ожидаемые частоты для нормального распределения\n",
"# expected_freq = []\n",
"# for i in range(n_bins):\n",
"# bin_start = bins[i]\n",
"# bin_end = bins[i+1]\n",
"# cdf_start = norm.cdf(bin_start, mu, std)\n",
"# cdf_end = norm.cdf(bin_end, mu, std)\n",
"# expected_freq.append(len(residuals) * (cdf_end - cdf_start))\n",
"\n",
"# # Критерий хи-квадрат\n",
"# chi2_stat = sum((observed_freq - expected_freq)**2 / expected_freq)\n",
"# dof = n_bins - 1 - 2 # 2 параметра (mu, std) оценены по данным\n",
"# alpha = 0.02\n",
"# critical_value = chi2.ppf(1 - alpha, dof)\n",
"# p_value = 1 - chi2.cdf(chi2_stat, dof)\n",
"# print(observed_freq, expected_freq);\n",
"\n",
"# print(f\"Хи-квадрат статистика: {chi2_stat:.4f}\")\n",
"# print(f\"Критическое значение: {critical_value:.4f}\")\n",
"# print(f\"p-value: {p_value:.4f}\")\n",
"\n",
"# # Визуальная оценка\n",
"# if chi2_stat > critical_value:\n",
"# print(\"Отвергаем H0: распределение не нормальное\")\n",
"# else:\n",
"# print(\"Не отвергаем H0: распределение нормальное\")"
]
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": 11,
"id": "f498c322",
"metadata": {},
"outputs": [],
@@ -731,7 +860,7 @@
},
{
"cell_type": "code",
"execution_count": 69,
"execution_count": 12,
"id": "ca6842f7",
"metadata": {},
"outputs": [
@@ -776,7 +905,7 @@
},
{
"cell_type": "code",
"execution_count": 86,
"execution_count": 13,
"id": "68365ffd",
"metadata": {},
"outputs": [
@@ -836,7 +965,7 @@
},
{
"cell_type": "code",
"execution_count": 90,
"execution_count": 14,
"id": "76e0b82d",
"metadata": {},
"outputs": [],
@@ -868,7 +997,7 @@
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": 15,
"id": "f791c572",
"metadata": {},
"outputs": [
@@ -933,7 +1062,7 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": 16,
"id": "9b48da35",
"metadata": {},
"outputs": [
@@ -965,7 +1094,7 @@
},
{
"cell_type": "code",
"execution_count": 20,
"execution_count": 17,
"id": "b34812e2",
"metadata": {},
"outputs": [],
@@ -1030,13 +1159,13 @@
"- $H_1$: Зависимость нелинейна ($\\beta_3 \\neq 0$).\n",
"\n",
"#### Гипотеза независимости\n",
"- $H_0$: $Y$ не зависит от $X$ линейна ($\\beta_2 = \\beta_3 = 0$).\n",
"- $H_1$: $Y$ зависит от $X$ линейна (хотя бы один из $\\beta_2, \\beta_3 \\neq 0$)."
"- $H_0$: $Y$ не зависит от $X$ линейно ($\\beta_2 = \\beta_3 = 0$).\n",
"- $H_1$: $Y$ зависит от $X$ линейно (хотя бы один из $\\beta_2, \\beta_3 \\neq 0$)."
]
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": 18,
"id": "1fde6d40",
"metadata": {},
"outputs": [],
@@ -1070,7 +1199,7 @@
},
{
"cell_type": "code",
"execution_count": 16,
"execution_count": 19,
"id": "405456a9",
"metadata": {},
"outputs": [
@@ -1080,55 +1209,67 @@
"text": [
"\n",
"Проверка гипотез:\n",
"Проверка гипотезы линейности (H₀: β₃ = 0):\n",
"t-статистика: 0.6775\n",
"p-значение: 0.5014\n",
"Нет оснований отвергать гипотезу о линейности\n",
"\n",
"Проверка гипотезы независимости (H₀: β = 0):\n",
"t-статистика: -0.8509\n",
"p-значение: 0.3991\n",
"Нет оснований отвергать гипотезу о независимости\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"C:\\Users\\margaery\\AppData\\Local\\Temp\\ipykernel_15852\\3529389018.py:4: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`\n",
" print(f\"t-статистика: {model_poly.tvalues[2]:.4f}\")\n",
"C:\\Users\\margaery\\AppData\\Local\\Temp\\ipykernel_15852\\3529389018.py:5: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`\n",
" print(f\"p-значение: {model_poly.pvalues[2]:.4f}\")\n",
"C:\\Users\\margaery\\AppData\\Local\\Temp\\ipykernel_15852\\3529389018.py:6: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`\n",
" if model_poly.pvalues[2] < alpha:\n",
"C:\\Users\\margaery\\AppData\\Local\\Temp\\ipykernel_15852\\3529389018.py:13: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`\n",
" print(f\"t-статистика: {model_poly.tvalues[1]:.4f}\")\n",
"C:\\Users\\margaery\\AppData\\Local\\Temp\\ipykernel_15852\\3529389018.py:14: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`\n",
" print(f\"p-значение: {model_poly.pvalues[1]:.4f}\")\n",
"C:\\Users\\margaery\\AppData\\Local\\Temp\\ipykernel_15852\\3529389018.py:15: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`\n",
" if model_poly.pvalues[1] < alpha:\n"
"Проверка гипотезы линейности (H₀: β = 0):\n",
"F-статистика: 0.4591\n",
"p-значение: 0.5014\n",
"Нет оснований отвергать гипотезу о линейности (alpha=0.02)\n",
"\n",
"Проверка гипотезы независимости (H₀: β₂ = β₃ = 0):\n",
"F-статистика: 0.5770\n",
"p-значение: 0.5655\n",
"Нет оснований отвергать гипотезу о независимости (alpha=0.02)\n"
]
}
],
"source": [
"print(\"\\nПроверка гипотез:\")\n",
"# Тест на линейность (значимость β₃)\n",
"print(\"Проверка гипотезы линейности (H₀: β₃ = 0):\")\n",
"print(f\"t-статистика: {model_poly.tvalues[2]:.4f}\")\n",
"print(f\"p-значение: {model_poly.pvalues[2]:.4f}\")\n",
"if model_poly.pvalues[2] < alpha:\n",
" print(f\"Гипотеза о линейности отвергается\")\n",
"else:\n",
" print(f\"Нет оснований отвергать гипотезу о линейности\")\n",
"model_const = sm.OLS(df['Y'], sm.add_constant(np.ones(len(df)))).fit()\n",
"\n",
"# Тест на независимость (значимость β₂)\n",
"print(\"\\nПроверка гипотезы независимости (H₀: β₂ = 0):\")\n",
"print(f\"t-статистика: {model_poly.tvalues[1]:.4f}\")\n",
"print(f\"p-значение: {model_poly.pvalues[1]:.4f}\")\n",
"if model_poly.pvalues[1] < alpha:\n",
" print(f\"Гипотеза о независимости отвергается\")\n",
"# print(\"\\nПроверка гипотез:\")\n",
"# # Тест на линейность (значимость β₃)\n",
"# print(\"Проверка гипотезы линейности (H₀: β₃ = 0):\")\n",
"# print(f\"t-статистика: {model_poly.tvalues[2]:.4f}\")\n",
"# print(f\"p-значение: {model_poly.pvalues[2]:.4f}\")\n",
"# if model_poly.pvalues[2] < alpha:\n",
"# print(f\"Гипотеза о линейности отвергается\")\n",
"# else:\n",
"# print(f\"Нет оснований отвергать гипотезу о линейности\")\n",
"\n",
"# # Тест на независимость (значимость β₂)\n",
"# print(\"\\nПроверка гипотезы независимости (H₀: β₂ = 0):\")\n",
"# print(f\"t-статистика: {model_poly.tvalues[1]:.4f}\")\n",
"# print(f\"p-значение: {model_poly.pvalues[1]:.4f}\")\n",
"# if model_poly.pvalues[1] < alpha:\n",
"# print(f\"Гипотеза о независимости отвергается\")\n",
"# else:\n",
"# print(f\"Нет оснований отвергать гипотезу о независимости\")\n",
"\n",
"from statsmodels.stats.anova import anova_lm\n",
"\n",
"print(\"\\nПроверка гипотез:\")\n",
"\n",
"# Сравнение моделей для проверки гипотез\n",
"# 1. Сравнение линейной и квадратичной моделей (проверка линейности)\n",
"anova_results_lin = anova_lm(model_lin, model_poly)\n",
"print(\"\\nПроверка гипотезы линейности (H₀: β₃ = 0):\")\n",
"print(f\"F-статистика: {anova_results_lin.F[1]:.4f}\")\n",
"print(f\"p-значение: {anova_results_lin['Pr(>F)'][1]:.4f}\")\n",
"\n",
"if anova_results_lin['Pr(>F)'][1] < alpha:\n",
" print(\"Гипотеза о линейности отвергается (alpha=0.02)\")\n",
"else:\n",
" print(f\"Нет оснований отвергать гипотезу о независимости\")\n"
" print(\"Нет оснований отвергать гипотезу о линейности (alpha=0.02)\")\n",
"\n",
"# 2. Сравнение константной и квадратичной моделей (проверка независимости)\n",
"anova_results_const = anova_lm(model_const, model_poly)\n",
"print(\"\\nПроверка гипотезы независимости (H₀: β₂ = β₃ = 0):\")\n",
"print(f\"F-статистика: {anova_results_const.F[1]:.4f}\")\n",
"print(f\"p-значение: {anova_results_const['Pr(>F)'][1]:.4f}\")\n",
"\n",
"if anova_results_const['Pr(>F)'][1] < alpha:\n",
" print(\"Гипотеза о независимости отвергается (alpha=0.02)\")\n",
"else:\n",
" print(\"Нет оснований отвергать гипотезу о независимости (alpha=0.02)\")"
]
},
{
@@ -1153,7 +1294,7 @@
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": 21,
"id": "c00ff024",
"metadata": {},
"outputs": [
@@ -1166,20 +1307,21 @@
"--------------------------------------\n",
"Модель AIC BIC\n",
"Линейная 232.83 236.66\n",
"Квадратичная 234.35 240.08\n"
"Квадратичная 234.35 240.08\n",
"Константная 231.56 233.47\n"
]
}
],
"source": [
"# f) AIC и BIC\n",
"# Добавляем константную модель для сравнения\n",
"model_const = sm.OLS(df['Y'], sm.add_constant(np.ones(len(df)))).fit()\n",
"\n",
"print(\"\\nСравнение моделей по AIC и BIC:\")\n",
"print(\"--------------------------------------\")\n",
"print(\"Модель AIC BIC\")\n",
"print(f\"Линейная {model_lin.aic:.2f} {model_lin.bic:.2f}\")\n",
"print(f\"Квадратичная {model_poly.aic:.2f} {model_poly.bic:.2f}\")\n"
"print(f\"Квадратичная {model_poly.aic:.2f} {model_poly.bic:.2f}\")\n",
"print(f\"Константная {model_const.aic:.2f} {model_const.bic:.2f}\")\n"
]
},
{
@@ -1187,57 +1329,8 @@
"id": "d66aad56",
"metadata": {},
"source": [
"**AIC/BIC** линейной модели меньше, она лучше описывает данные."
]
},
{
"cell_type": "markdown",
"id": "a6887b63",
"metadata": {},
"source": [
"## Пункт g)\n",
"### Характер зависимости $Y$ от $X$\n",
"- **Линейная модель:**\n",
" $$\n",
" Y = 15.59 - 0.25X,\\ R^2 = 0.014.\n",
" $$\n",
" - Крайне низкий $R^2$ (1.4%) указывает на отсутствие линейной зависимости.\n",
" - Коэффициент $\\beta_2 = -0.25$ статистически незначим (доверительный интервал [4.29, 2.05] включает ноль).\n",
"\n",
"- **Квадратичная модель:**\n",
" $$\n",
" Y = 16.87 - 1.12X + 0.13X^2,\\ R^2 = 0.024.\n",
" $$\n",
" - $R^2 = 2.4\\%$ показывает, что модель объясняет лишь незначительную часть вариации.\n",
" - Коэффициенты:\n",
" - $\\beta_2 = -1.12$ (линейный член): интервал [4.29, 2.05] включает ноль.\n",
" - $\\beta_3 = 0.13$ (квадратичный член): интервал [0.33, 0.59] включает ноль.\n",
"\n",
"### Проверка гипотез\n",
"Остатки близки к нормальному распределению. Критерий $\\chi^2$ не выявил значимых отклонений от нормальности на уровне $\\alpha=0.02$.\n",
"\n",
"*Предположение о нормальности ошибок выполняется.*\n",
"\n",
"### AIC/BIC\n",
"| Модель | AIC | BIC |\n",
"|----------------|--------|--------|\n",
"| Линейная | 232.83 | 236.66 |\n",
"| Квадратичная | 234.35 | 240.08 |\n",
"\n",
"- **Линейная модель** имеет более низкие AIC/BIC, чем квадратичная.\n",
"\n",
"### Аномалии в результатах\n",
"\n",
"**Парадокс низкого $R^2$:**\n",
" - Обе модели объясняют менее 3% вариации, что ставит под сомнение их практическую применимость.\n",
"\n",
"### Итоговый вывод\n",
"- **Отсутствие значимой связи:** Ни линейная, ни квадратичная модели не демонстрируют статистически значимой зависимости $Y$ от $X$ на уровне $\\alpha=0.02$.\n",
"- **Артефакты анализа:** Низкий $R^2$, незначимые коэффициенты и противоречивые результаты тестов указывают на то, что переменная $X$ не является релевантным предиктором для $Y$ в данном наборе данных.\n",
"- **Рекомендации:** \n",
" - Проверить данные на наличие выбросов или ошибок.\n",
" - Рассмотреть другие предикторы или преобразования.\n",
" - Увеличить объем данных для повышения надежности тестов."
"**AIC/BIC** константной модели меньше, она лучше описывает данные. \n",
"Это согласуется с F-тестами: константная модель лучше описывает данные"
]
}
],