Добавлен анализ ANOVA
This commit is contained in:
@@ -128,3 +128,83 @@ def compute_gradient_points(beta, base_levels, step_factor, num_steps, factor_na
|
||||
point["Предсказанный отклик"] = predicted
|
||||
points.append(point)
|
||||
return points
|
||||
|
||||
|
||||
def anova_regression(y, y_pred, X, center_indices=None):
|
||||
"""
|
||||
Выполняет полный дисперсионный анализ (ANOVA) для регрессионной модели.
|
||||
|
||||
Аргументы:
|
||||
y – фактические значения отклика
|
||||
y_pred – предсказанные моделью значения
|
||||
X – матрица регрессоров (с единичным столбцом)
|
||||
center_indices – индексы центральных точек (опционально)
|
||||
|
||||
Возвращает словарь с компонентами ANOVA:
|
||||
SSR, SSE, SST, df_reg, df_res, df_pe, df_lof,
|
||||
MSR, MSE, MS_pe, MS_lof,
|
||||
F_regression, p_regression, F_lof, p_lof
|
||||
"""
|
||||
n = len(y)
|
||||
p = X.shape[1] # число параметров (включая свободный член)
|
||||
df_reg = p - 1 # степени свободы регрессии (без свободного члена)
|
||||
df_res = n - p # степени свободы остатка
|
||||
|
||||
# Общая сумма квадратов (SST)
|
||||
y_mean = np.mean(y)
|
||||
SST = np.sum((y - y_mean)**2)
|
||||
|
||||
# Регрессионная сумма квадратов (SSR)
|
||||
SSR = np.sum((y_pred - y_mean)**2)
|
||||
|
||||
# Остаточная сумма квадратов (SSE)
|
||||
SSE = np.sum((y - y_pred)**2)
|
||||
|
||||
# Средние квадраты
|
||||
MSR = SSR / df_reg if df_reg > 0 else np.nan
|
||||
MSE = SSE / df_res if df_res > 0 else np.nan
|
||||
|
||||
# F-статистика для регрессии (значимость всей модели)
|
||||
F_reg = MSR / MSE if MSE > 0 else np.nan
|
||||
p_reg = 1 - stats.f.cdf(F_reg, df_reg, df_res) if not np.isnan(F_reg) and SCIPY_AVAILABLE else np.nan
|
||||
|
||||
# ----- Разложение остатка на чистую ошибку и неадекватность (если есть центр) -----
|
||||
if center_indices is not None and len(center_indices) >= 2:
|
||||
y_center = y[center_indices]
|
||||
y_pred_center = y_pred[center_indices]
|
||||
n_center = len(center_indices)
|
||||
# Среднее в центре
|
||||
y_center_mean = np.mean(y_center)
|
||||
# Сумма квадратов чистой ошибки (SSPE) = сумма квадратов отклонений от среднего в центре
|
||||
SSPE = np.sum((y_center - y_center_mean)**2)
|
||||
df_pe = n_center - 1
|
||||
MS_pe = SSPE / df_pe if df_pe > 0 else np.nan
|
||||
|
||||
# Сумма квадратов неадекватности (SSLOF) = SSE - SSPE
|
||||
SSLOF = SSE - SSPE
|
||||
df_lof = df_res - df_pe
|
||||
MS_lof = SSLOF / df_lof if df_lof > 0 else np.nan
|
||||
|
||||
# F-статистика для проверки адекватности (lack-of-fit)
|
||||
F_lof = MS_lof / MS_pe if MS_pe > 0 and not np.isnan(MS_lof) else np.nan
|
||||
p_lof = 1 - stats.f.cdf(F_lof, df_lof, df_pe) if not np.isnan(F_lof) and SCIPY_AVAILABLE else np.nan
|
||||
else:
|
||||
SSPE = np.nan
|
||||
df_pe = 0
|
||||
MS_pe = np.nan
|
||||
SSLOF = np.nan
|
||||
df_lof = 0
|
||||
MS_lof = np.nan
|
||||
F_lof = np.nan
|
||||
p_lof = np.nan
|
||||
|
||||
return {
|
||||
"SSR": SSR, "SSE": SSE, "SST": SST,
|
||||
"df_reg": df_reg, "df_res": df_res,
|
||||
"MSR": MSR, "MSE": MSE,
|
||||
"F_reg": F_reg, "p_reg": p_reg,
|
||||
"SSPE": SSPE, "SSLOF": SSLOF,
|
||||
"df_pe": df_pe, "df_lof": df_lof,
|
||||
"MS_pe": MS_pe, "MS_lof": MS_lof,
|
||||
"F_lof": F_lof, "p_lof": p_lof
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user