mirosh111000

Прикладна_економетрика_ЛР№6_Мірошниченко

Nov 19th, 2025
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.35 KB | None | 0 0
  1. import math
  2. import numpy as np
  3. import pandas as pd
  4.  
  5.  
  6. y  = [1.55, 3.80, 5.40, 2.60, 5.60, 8.30, 7.30, 8.40, 4.20, 5.60]
  7. x1 = [0.30, 0.60, 1.10, 0.20, 0.80, 1.60, 1.50, 0.90, 0.90, 0.80]
  8. x2 = [0.80, 1.90, 2.70, 1.30, 2.80, 4.10, 3.60, 4.20, 2.10, 2.80]
  9.  
  10.  
  11. def _col(v):
  12.     v = np.asarray(v).reshape(-1)
  13.     return v[:, None]
  14.  
  15. def design_matrix(x1, x2, intercept=True):
  16.     x1c = _col(x1)
  17.     x2c = _col(x2)
  18.     if intercept:
  19.         ones = np.ones_like(x1c)
  20.         X = np.hstack([ones, x1c, x2c])
  21.     else:
  22.         X = np.hstack([x1c, x2c])
  23.     return X
  24.  
  25. def safe_inv(M):
  26.     try:
  27.         return np.linalg.inv(M)
  28.     except np.linalg.LinAlgError:
  29.         return np.linalg.pinv(M)
  30.  
  31. def _log_beta(a, b):
  32.     return math.lgamma(a) + math.lgamma(b) - math.lgamma(a + b)
  33.  
  34. def _betacf(a, b, x, max_iter=200, eps=3e-14):
  35.     am, bm = 1.0, 1.0
  36.     az = 1.0
  37.     qab = a + b
  38.     qap = a + 1.0
  39.     qam = a - 1.0
  40.  
  41.     bz = 1.0 - qab * x / qap
  42.     if abs(bz) < 1e-300:
  43.         bz = 1e-300
  44.     em, tem = 0.0, 0.0
  45.     d = 0.0
  46.     ap, bp = 0.0, 0.0
  47.  
  48.     for m in range(1, max_iter + 1):
  49.         em = float(m)
  50.         tem = em + em
  51.        
  52.         d = em * (b - em) * x / ((qam + tem) * (a + tem))
  53.         ap = az + d * am
  54.         bp = bz + d * bm
  55.         if abs(bp) < 1e-300:
  56.             bp = 1e-300
  57.        
  58.         d = -(a + em) * (qab + em) * x / ((a + tem) * (qap + tem))
  59.         app = ap + d * az
  60.         bpp = bp + d * bz
  61.         if abs(bpp) < 1e-300:
  62.             bpp = 1e-300
  63.  
  64.         am, bm = ap / bpp, bp / bpp
  65.         az, bz = app / bpp, 1.0
  66.         if abs(app - ap) < eps * abs(app):
  67.             return az
  68.     return az
  69.  
  70. def betainc_regularized(a, b, x):
  71.     if x <= 0.0:
  72.         return 0.0
  73.     if x >= 1.0:
  74.         return 1.0
  75.    
  76.     ln_bt = a * math.log(x) + b * math.log(1.0 - x) - _log_beta(a, b)
  77.     if x < (a + 1.0) / (a + b + 2.0):
  78.         cf = _betacf(a, b, x)
  79.         return math.exp(ln_bt) * cf / a
  80.     else:
  81.         cf = _betacf(b, a, 1.0 - x)
  82.         return 1.0 - math.exp((b * math.log(x) + a * math.log(1.0 - x)) - _log_beta(b, a)) * cf / b
  83.  
  84.  
  85. def t_cdf(t, v):
  86.     if v <= 0:
  87.         return float("nan")
  88.     if t == 0.0:
  89.         return 0.5
  90.     x = v / (v + t * t)
  91.     ib = betainc_regularized(v / 2.0, 0.5, x)
  92.     if t > 0:
  93.         return 1.0 - 0.5 * ib
  94.     else:
  95.         return 0.5 * ib
  96.  
  97.  
  98. def t_ppf(p, v, tol=1e-10, max_iter=200):
  99.     if not (0.0 < p < 1.0):
  100.         return float("nan")
  101.    
  102.     if p == 0.5:
  103.         return 0.0
  104.    
  105.     lo, hi = -50.0, 50.0
  106.    
  107.     for _ in range(max_iter):
  108.         mid = (lo + hi) / 2.0
  109.         c = t_cdf(mid, v)
  110.         if abs(c - p) < tol:
  111.             return mid
  112.         if c < p:
  113.             lo = mid
  114.         else:
  115.             hi = mid
  116.     return (lo + hi) / 2.0
  117.  
  118.  
  119. def f_cdf(x, df1, df2):
  120.     if x <= 0.0:
  121.         return 0.0
  122.     z = (df1 * x) / (df1 * x + df2)
  123.     return betainc_regularized(df1 / 2.0, df2 / 2.0, z)
  124.  
  125.  
  126. def f_ppf(p, df1, df2, tol=1e-10, max_iter=200):
  127.     if not (0.0 < p < 1.0):
  128.         return float("nan")
  129.     lo, hi = 0.0, 1.0
  130.    
  131.     while f_cdf(hi, df1, df2) < p and hi < 1e8:
  132.         hi *= 2.0
  133.     for _ in range(max_iter):
  134.         mid = (lo + hi) / 2.0
  135.         c = f_cdf(mid, df1, df2)
  136.         if abs(c - p) < tol:
  137.             return mid
  138.         if c < p:
  139.             lo = mid
  140.         else:
  141.             hi = mid
  142.     return (lo + hi) / 2.0
  143.  
  144.  
  145. def ols_fit(X, y):
  146.  
  147.     y = _col(y)
  148.     n, p = X.shape
  149.  
  150.     XtX = X.T @ X
  151.     XtX_inv = safe_inv(XtX)
  152.     Xty = X.T @ y
  153.     beta = XtX_inv @ Xty
  154.  
  155.     yhat = X @ beta
  156.     e = y - yhat
  157.  
  158.     RSS = float((e.T @ e).ravel()[0])
  159.     ybar = float(np.mean(y))
  160.     TSS = float(((y - ybar) ** 2).sum())
  161.  
  162.     df = n - p
  163.     if df <= 0:
  164.         raise ValueError("Недостатньо ступенів вільності (n - p має бути > 0).")
  165.  
  166.     s2 = RSS / df
  167.     cov_beta = s2 * XtX_inv
  168.     se = np.sqrt(np.diag(cov_beta)).reshape(-1, 1)
  169.  
  170.     with np.errstate(divide="ignore", invalid="ignore"):
  171.         tvals = beta / se
  172.     tvals = np.where(np.isfinite(tvals), tvals, np.nan)
  173.     pvals = np.empty_like(tvals)
  174.     for i in range(tvals.size):
  175.         ti = float(abs(tvals[i, 0]))
  176.         pvals[i, 0] = 2.0 * (1.0 - t_cdf(ti, df))
  177.  
  178.     tcrit = t_ppf(0.975, df)
  179.     ci_low = beta - tcrit * se
  180.     ci_high = beta + tcrit * se
  181.  
  182.     R2 = 1.0 - RSS / TSS if TSS > 0 else float("nan")
  183.     k = p - 1
  184.     denom = (1.0 - R2) / (n - p) if (n - p) > 0 else float("nan")
  185.     numer = R2 / k if k > 0 else float("nan")
  186.     F = numer / denom if denom not in (None, 0.0) else float("nan")
  187.     F_pvalue = 1.0 - f_cdf(F, k, n - p) if math.isfinite(F) else float("nan")
  188.     F_crit = f_ppf(0.95, k, n - p) if k > 0 else float("nan")
  189.  
  190.     return dict(
  191.         beta=beta, yhat=yhat, e=e, RSS=RSS, TSS=TSS, s2=s2, se=se,
  192.         tvals=tvals, pvals=pvals, ci_low=ci_low, ci_high=ci_high,
  193.         XtX=XtX, XtX_inv=XtX_inv, cov_beta=cov_beta,
  194.         R2=R2, F=F, F_pvalue=F_pvalue, F_crit=F_crit,
  195.         df_resid=df, k=k, p=p, n=n, tcrit=tcrit
  196.     )
  197.  
  198.  
  199. def standardized_betas(y, x1, x2, beta):
  200.     y = np.asarray(y).reshape(-1)
  201.     x1 = np.asarray(x1).reshape(-1)
  202.     x2 = np.asarray(x2).reshape(-1)
  203.     sy  = np.std(y,  ddof=1)
  204.     sx1 = np.std(x1, ddof=1)
  205.     sx2 = np.std(x2, ddof=1)
  206.     b1, b2 = float(beta[1, 0]), float(beta[2, 0])
  207.     beta1_std = b1 * (sx1 / sy) if sy > 0 else float("nan")
  208.     beta2_std = b2 * (sx2 / sy) if sy > 0 else float("nan")
  209.     return beta1_std, beta2_std
  210.  
  211. def elasticities(y, x1, x2, beta):
  212.     y  = np.asarray(y).reshape(-1)
  213.     x1 = np.asarray(x1).reshape(-1)
  214.     x2 = np.asarray(x2).reshape(-1)
  215.     my  = float(np.mean(y))
  216.     mx1 = float(np.mean(x1))
  217.     mx2 = float(np.mean(x2))
  218.     b1, b2 = float(beta[1, 0]), float(beta[2, 0])
  219.     E1 = b1 * (mx1 / my) if my != 0 else float("nan")
  220.     E2 = b2 * (mx2 / my) if my != 0 else float("nan")
  221.     return E1, E2
  222.  
  223. def prediction_intervals(x_new, fit):
  224.  
  225.     x_new = np.asarray(x_new).reshape(-1, 1)
  226.     beta = fit["beta"]
  227.     XtX_inv = fit["XtX_inv"]
  228.     s2 = float(fit["s2"])
  229.     s  = math.sqrt(s2)
  230.     tcrit = fit["tcrit"]
  231.     df = int(fit["df_resid"])
  232.  
  233.     yhat_new = float((x_new.T @ beta).ravel()[0])
  234.     leverage = float((x_new.T @ XtX_inv @ x_new).ravel()[0])
  235.  
  236.     stderr_mean = float(s * math.sqrt(leverage))
  237.     CI_low  = yhat_new - tcrit * stderr_mean
  238.     CI_high = yhat_new + tcrit * stderr_mean
  239.  
  240.     stderr_pred = float(s * math.sqrt(1.0 + leverage))
  241.     PI_low  = yhat_new - tcrit * stderr_pred
  242.     PI_high = yhat_new + tcrit * stderr_pred
  243.  
  244.     return dict(
  245.         yhat=yhat_new,
  246.         CI95_low=CI_low, CI95_high=CI_high,
  247.         PI95_low=PI_low, PI95_high=PI_high,
  248.         df=df, tcrit=float(tcrit)
  249.     )
  250.  
  251.  
  252. def fit_and_report(y, x1, x2):
  253.     src_df = pd.DataFrame({"y": y, "x1": x1, "x2": x2})
  254.     print("=== Вихідні дані (Варіант 2) ===")
  255.     print(src_df.round(4).to_string(index=True))
  256.     print(f"n = {len(y)} спостережень")
  257.  
  258.     X = design_matrix(x1, x2, intercept=True)
  259.     fit = ols_fit(X, y)
  260.  
  261.     print("\n--- Матриця X'X ---")
  262.     print(pd.DataFrame(fit["XtX"], index=["1","x1","x2"], columns=["1","x1","x2"]).round(6).to_string())
  263.     print("\n--- (X'X)^(-1) ---")
  264.     print(pd.DataFrame(fit["XtX_inv"], index=["a0","a1","a2"], columns=["a0","a1","a2"]).round(6).to_string())
  265.  
  266.  
  267.     a0, a1, a2 = (float(fit["beta"][0,0]), float(fit["beta"][1,0]), float(fit["beta"][2,0]))
  268.     print("\n=== (1) Вибіркове рівняння множинної регресії ===")
  269.     print(f"ŷ = {a0:.6f} + {a1:.6f}·x1 + {a2:.6f}·x2")
  270.  
  271.  
  272.     print("\n=== (2) Дисперсія збурень та коваріаційна матриця ===")
  273.     print(f"s_e^2 = {fit['s2']:.6f}  (df = {fit['df_resid']})")
  274.     print("Cov(a) = s_e^2 · (X'X)^(-1):")
  275.     print(pd.DataFrame(fit["cov_beta"], index=["a0","a1","a2"], columns=["a0","a1","a2"]).round(6).to_string())
  276.  
  277.     print("\n=== (3) t-тести для коефіцієнтів (α=0.05) та 95% ДІ ===")
  278.     coef_tbl = pd.DataFrame({
  279.         "coef":[a0, a1, a2],
  280.         "SE":  fit["se"].reshape(-1),
  281.         "t":   fit["tvals"].reshape(-1),
  282.         "p":   fit["pvals"].reshape(-1),
  283.         "CI95_low":  fit["ci_low"].reshape(-1),
  284.         "CI95_high": fit["ci_high"].reshape(-1),
  285.     }, index=["a0","a1","a2"])
  286.     print(coef_tbl.round(6).to_string())
  287.  
  288.     R2 = float(fit["R2"])
  289.     R  = float(math.sqrt(R2)) if R2 >= 0 else float("nan")
  290.     print("\n=== (4) Дисперсія та значущість моделі ===")
  291.     print(f"R^2 = {R2:.6f},  R = {R:.6f}")
  292.     print(f"F = {fit['F']:.6f} (df1 = {fit['k']}, df2 = {fit['df_resid']}),  p-value = {fit['F_pvalue']:.6g}")
  293.     print(f"F_crit (α=0.05) = {fit['F_crit']:.6f}")
  294.  
  295.     b1_std, b2_std = standardized_betas(y, x1, x2, fit["beta"])
  296.     E1, E2 = elasticities(y, x1, x2, fit["beta"])
  297.     comp_df = pd.DataFrame({"std_beta":[b1_std, b2_std], "elasticity":[E1, E2]},
  298.                            index=["x1 (тис. м²)", "x2 (тис. люд/день)"])
  299.     print("\n=== (5) Порівняння роздільного впливу факторів ===")
  300.     print(comp_df.round(6).to_string())
  301.     stronger_std = "x1" if abs(b1_std) > abs(b2_std) else "x2"
  302.     stronger_el  = "x1" if abs(E1)    > abs(E2)    else "x2"
  303.     print(f"→ За |std_beta| сильніший вплив: {stronger_std};  за |elasticity|: {stronger_el}.")
  304.  
  305.     x_new = np.array([1.0, 1.2, 15.0])
  306.     pred = prediction_intervals(x_new, fit)
  307.     print("\n=== (6) Прогноз у точці x1=1.2, x2=15 з 95% інтервалами ===")
  308.     print(f"ŷ_new = {pred['yhat']:.6f}")
  309.     print(f"95% CI (середній відгук):    [{pred['CI95_low']:.6f}; {pred['CI95_high']:.6f}]")
  310.     print(f"95% PI (нове спостереження): [{pred['PI95_low']:.6f}; {pred['PI95_high']:.6f}]")
  311.     print(f"(t_crit = {pred['tcrit']:.4f}, df = {pred['df']})")
  312.  
  313.     print("\n=== ПІДСУМОК ===")
  314.     print(f"Модель: ŷ = {a0:.4f} + {a1:.4f}·x1 + {a2:.4f}·x2")
  315.     print(f"R^2 = {R2:.4f},  F({fit['k']},{fit['df_resid']}) = {fit['F']:.4f}  (F_crit={fit['F_crit']:.4f})")
  316.     print(f"Прогноз у (1.2; 15): ŷ = {pred['yhat']:.4f}, 95% PI = [{pred['PI95_low']:.4f}; {pred['PI95_high']:.4f}]")
  317.     print("x1 — тис. м², x2 — тис. людей/день; y — млн грн.")
  318.  
  319.  
  320. if __name__ == "__main__":
  321.     fit_and_report(y, x1, x2)
  322.  
Advertisement
Add Comment
Please, Sign In to add comment