02 분석 — AI 확산 지수, 대안 1(고정 계수), 대안 2(재추정)¶
구성. 1절 총량 지수와 갭 → 2절 산업별 노출 지수 → 3절 기존 산업모형 적합(보고서1 선택 모형) → 4절 대안 1 → 5절 파급 진단 → 6절 대안 2 → 7절 산출물 저장.
공통 규칙. 모든 사양은 2035년 부가가치 가중평균 AI 프리미엄이 Λ = 0.5%p가 되도록 크기를 맞춘다. 따라서 사양 간 차이는 산업 간 배분과 파급에서만 생긴다. 시간 경로는 4장과 같다: 설문 전체 평균 점수의 시점 가중치 r(t)(2025년 0 → 2040년 1)를 분기로 보간한다.
import os, hashlib
import numpy as np, pandas as pd
import config as C
import ai_index as I, ai_varx as X, ai_forecast as F, varx_engine as V, alt_run as R
pd.set_option("display.float_format", lambda v: f"{v:,.3f}")
pd.set_option("display.width", 200)
C.setup()
Python 3.12.10 · pandas 2.2.3 · numpy 2.4.6 · matplotlib 3.11.0 판: 2026-10 정비판 기준 · Λ 0.5 · 드리프트 목표 1.8% · ONLINE=0(스냅샷) · Event Registry 키 없음 설문 통계표(비공개) 있음 data\private\AI수용도조사_통계표_260417.xlsx 설문 원자료(비공개) 있음 data\private\AI수용도조사_원자료_n2297.xlsx
L, gdp, exo, B, _ = X.fit_existing(C.LEVELS_62, C.EXOG_HIST, C.IO_62)
Wio = V.load(C.LEVELS_62, C.EXOG_HIST, C.IO_62)[3]
names = list(L.columns); n = len(names)
base = F.read_base(C.BASE_62)[names] # 산업 순서를 산업모형과 맞춘다
grp = R.survey_groups(names, C.CROSSWALK)
sig = pd.read_csv(os.path.join(C.INTERIM, "survey_signal_21.csv"), index_col=0)
se_tab = pd.read_csv(os.path.join(C.INTERIM, "survey_se_21.csv"), index_col=0)
a = R.survey_shape(sig, grp)
ramp = F.ramp_factory(sig.loc["전체", [f"AI성장_{t}" for t in F.TIME_POINTS]].tolist())
xq = X.quarterly_ramp(ramp)
print(f"산업 {n}개, 표본 {L.index[0]}–{L.index[-1]}({len(L)}분기), 전망 {xq.index[0]}–{xq.index[-1]}")
print(f"시점 가중치 r(t): 2030년 {ramp(2030):.3f}, 2035년 {ramp(2035):.3f}")
산업 62개, 표본 2000Q1–2025Q4(104분기), 전망 2026Q1–2035Q4 시점 가중치 r(t): 2030년 0.495, 2035년 0.793
1. AI 확산 총량 지수(분기)¶
세 자료원의 로그 수준에서 각자의 2015–2024년 평균을 뺀 값(로그 편차)을 분기로 맞추고 평균한다. 연간 자료(특허·논문)는 연 중앙에 로그 수준을 두고 선형보간한 뒤 해마다 분기 합이 연간 값과 같도록 비례 조정한다. AI 확산 갭은 총량 지수에서 HP 추세(λ = 1600)를 뺀 값이다. 추세보다 빨리 퍼진 분기는 양(+), 느린 분기는 음(−)이다. 뉴스 자료가 시작되기 전인 2015년 이전은 0으로 둔다(AI 확산 이전 시기).
comp = R.build_index(C.PATENT_YEAR, C.PAPER_YEAR, C.NEWS_DAILY)
gap = I.gap_series(comp, list(L.index))
comp.to_csv(os.path.join(C.OUTPUT, "ai_index_quarterly.csv"), encoding="utf-8-sig")
display(comp.iloc[::4])
print(f"총량 지수: 2015Q1 {comp['총량지수'].iloc[0]:+.2f} → 2025Q4 {comp['총량지수'].iloc[-1]:+.2f}(로그 편차, 10년간 약 {np.exp(comp['총량지수'].iloc[-1] - comp['총량지수'].iloc[0]):.0f}배)")
print(f"갭 표준편차 {comp['갭'].std():.3f}, 최대 {comp['갭'].max():+.3f}({comp['갭'].idxmax()}), 최소 {comp['갭'].min():+.3f}({comp['갭'].idxmin()})")
print(f"세 자료원 상관(분기 로그 편차): ", comp[["특허", "논문", "뉴스"]].corr().round(2).values[np.triu_indices(3, 1)].tolist())
| 특허 | 논문 | 뉴스 | 총량지수 | 추세 | 갭 | |
|---|---|---|---|---|---|---|
| 분기 | ||||||
| 2015Q1 | -2.119 | -0.299 | -2.183 | -1.534 | -1.465 | -0.069 |
| 2016Q1 | -1.633 | -0.278 | -1.237 | -1.049 | -1.079 | 0.030 |
| 2017Q1 | -1.004 | -0.265 | -0.717 | -0.662 | -0.705 | 0.043 |
| 2018Q1 | -0.423 | -0.183 | -0.305 | -0.304 | -0.362 | 0.059 |
| 2019Q1 | 0.101 | -0.074 | 0.098 | 0.042 | -0.067 | 0.109 |
| 2020Q1 | 0.516 | 0.005 | 0.255 | 0.259 | 0.174 | 0.085 |
| 2021Q1 | 0.767 | 0.084 | 0.369 | 0.407 | 0.368 | 0.039 |
| 2022Q1 | 0.808 | 0.078 | 0.281 | 0.389 | 0.540 | -0.151 |
| 2023Q1 | 0.806 | 0.158 | 0.901 | 0.622 | 0.714 | -0.092 |
| 2024Q1 | 0.982 | 0.462 | 1.645 | 1.030 | 0.899 | 0.130 |
| 2025Q1 | NaN | 0.514 | 1.732 | 1.123 | 1.086 | 0.037 |
총량 지수: 2015Q1 -1.53 → 2025Q4 +1.24(로그 편차, 10년간 약 16배) 갭 표준편차 0.101, 최대 +0.170(2019Q4), 최소 -0.248(2022Q3) 세 자료원 상관(분기 로그 편차): [0.85, 0.94, 0.93]
2. 산업별 AI 노출 지수(설문 21개 업종)¶
자료원마다 지표의 로그값을 업종 간 표준화(z)하고, 쓸 수 있는 자료원의 평균을 노출 지수로 둔다. 특허 지표는 업종 부가가치 1조 원당 AI 특허 동시분류 건수이다. 대응표가 없어 지표를 만들 수 없는 업종·자료원 조합은 빈칸으로 두고 나머지 자료원의 평균을 쓴다(자료원수 열). 62개 산업 가운데 설문 업종이 없는 산업(농림어업·공공행정 등)은 21개 업종의 부가가치 가중평균('전체'), 일부 제조업은 제조 9개 업종의 가중평균('제조업')을 쓴다.
ex, zg = R.build_exposure(C.NEWS_IND, C.PAPER_FIELD, C.MAP_FIELD, C.PATENT_COIPC, C.PATENT_COIPC_SUP, C.MAP_IPC,
base.loc[C.START], grp)
ex.to_csv(os.path.join(C.OUTPUT, "ai_exposure_21.csv"), encoding="utf-8-sig")
display(ex.sort_values("노출지수_z", ascending=False))
a21 = sig.loc[ex.index, "AI성장_2040"]
rho = {"노출 지수": I.spearman(ex["노출지수_z"], a21)} | {k: I.spearman(ex[k], a21) for k in ["뉴스", "논문", "특허"]}
rho_tab = pd.DataFrame({"설문 E4-1과의 순위상관": rho})
rho_tab.to_csv(os.path.join(C.OUTPUT, "exposure_rank_corr.csv"), encoding="utf-8-sig")
display(rho_tab)
| 뉴스 | 논문 | 특허 | 노출지수_z | 자료원수 | |
|---|---|---|---|---|---|
| 설문업종 | |||||
| 13. 정보통신 | 11.576 | 45.679 | 12,851.163 | 2.023 | 3 |
| 02. 정밀기기 | 9.318 | NaN | 1,794.228 | 0.928 | 2 |
| 17. 연구개발업 | 10.515 | 12.470 | NaN | 0.820 | 2 |
| 01. 전기전자 | 25.984 | 12.671 | 100.438 | 0.598 | 3 |
| 08. 자동차 | 7.379 | 18.187 | 472.451 | 0.462 | 3 |
| 10. 에너지 | 7.462 | 6.504 | 899.722 | 0.218 | 3 |
| 18. 사업지원서비스 | 9.316 | 8.266 | 315.767 | 0.153 | 3 |
| 07. 기계장비 | 4.287 | 18.187 | 460.674 | 0.145 | 3 |
| 12. 운수 | 7.091 | NaN | 383.531 | 0.050 | 2 |
| 09. 식료품 | 2.868 | 19.391 | NaN | -0.014 | 2 |
| 20. 보건사회 | 7.451 | 4.298 | 494.368 | -0.123 | 3 |
| 14. 도소매 | 5.003 | NaN | 391.333 | -0.240 | 2 |
| 16. 금융 | 5.829 | 3.976 | 523.925 | -0.279 | 3 |
| 19. 교육 | 4.977 | 4.666 | NaN | -0.436 | 2 |
| 04. 석유화학 | 6.016 | 3.024 | 127.528 | -0.769 | 3 |
| 11. 건설 | 3.423 | NaN | NaN | -0.850 | 1 |
| 05. 비금속광물 | 3.314 | 3.617 | NaN | -0.944 | 2 |
| 06. 금속제품 | 3.067 | 3.617 | NaN | -1.010 | 2 |
| 21. 문화/예술 | 2.745 | 3.833 | NaN | -1.069 | 2 |
| 03. 섬유가죽 | 2.638 | NaN | NaN | -1.295 | 1 |
| 15. 음식숙박 | 2.623 | NaN | NaN | -1.305 | 1 |
| 설문 E4-1과의 순위상관 | |
|---|---|
| 노출 지수 | 0.491 |
| 뉴스 | 0.353 |
| 논문 | 0.546 |
| 특허 | 0.238 |
설문 순위와 객관 지표 순위를 나란히 보면 두 자료가 어디에서 갈리는지 알 수 있다(업종 평균 점수가 드러나므로 출력은 공개 화면에서 숨긴다).
cmp = pd.DataFrame({"설문_순위": a21.rank(ascending=False), "노출_순위": ex["노출지수_z"].rank(ascending=False)})
cmp["차이(설문−노출)"] = cmp["설문_순위"] - cmp["노출_순위"]
display(cmp.sort_values("차이(설문−노출)"))
(비공개 설문 집계를 보여주는 셀이다. 공개 화면에서는 출력을 생략했다. 자료를 가진 경우 직접 실행하면 표시된다.)
한국고용정보원(2017) 혁신 시나리오(대안 1c). 8장 세부 산업의 (혁신 − 기준) 차이를 세 구간 평균해 설문 업종별로 단순평균하고(KIET), 11장 인력수급 산업의 2016~2030년 차이(KEIS)와 평균한다. 이 값은 이미 부가가치 증가율 차이(%p)이므로 척도를 옮기지 않고 그대로 배분 형태로 쓴다. 세 자료(설문·객관 지표·이전 전망)의 업종 순위가 얼마나 일치하는지 함께 본다.
keis_tab, kg, keis_tot = R.build_keis(C.KEIS_R14, C.MAP_KEIS11, C.SHORT_NAMES, base.loc[C.START], grp)
keis_tab.to_csv(os.path.join(C.OUTPUT, "keis_r14_dva_21.csv"), encoding="utf-8-sig")
display(keis_tab)
print("전 산업 혁신 − 기준(8장, 세 구간 평균): %.2f%%p, 구간별 %s, 11장 2016~2030: %.2f%%p"
% (keis_tot["전산업_KIET_3구간평균"], keis_tot["구간별_KIET"], keis_tot["전산업_KEIS_2016_2030"]))
tri = pd.DataFrame({"설문 E4-1": a21, "객관 노출 지수": ex["노출지수_z"], "고용정보원(2017) ΔVA": keis_tab["ΔVA_평균"]})
tri_rho = tri.rank().corr()
tri_rho.to_csv(os.path.join(C.OUTPUT, "triangulation_rank_corr.csv"), encoding="utf-8-sig")
pd.Series(keis_tot | {"구간별_KIET": str(keis_tot["구간별_KIET"])}).to_frame("값").to_csv(os.path.join(C.OUTPUT, "keis_r14_total.csv"), encoding="utf-8-sig")
display(tri_rho.round(2))
k62 = np.array([kg[g] for g in grp])
| ΔVA_KIET | ΔVA_KEIS | ΔVA_평균 | |
|---|---|---|---|
| 설문업종 | |||
| 01. 전기전자 | 0.717 | 0.800 | 0.758 |
| 02. 정밀기기 | 0.300 | 0.280 | 0.290 |
| 03. 섬유가죽 | 0.217 | 0.260 | 0.238 |
| 04. 석유화학 | 0.380 | 0.500 | 0.440 |
| 05. 비금속광물 | 0.267 | 0.270 | 0.268 |
| 06. 금속제품 | 0.183 | NaN | 0.183 |
| 07. 기계장비 | 0.917 | 0.440 | 0.678 |
| 08. 자동차 | 0.567 | 0.840 | 0.703 |
| 09. 식료품 | 0.111 | 0.290 | 0.201 |
| 10. 에너지 | NaN | 0.420 | 0.420 |
| 11. 건설 | NaN | 0.410 | 0.410 |
| 12. 운수 | 0.442 | 0.420 | 0.431 |
| 13. 정보통신 | 0.772 | 0.980 | 0.876 |
| 14. 도소매 | 0.433 | 0.410 | 0.422 |
| 15. 음식숙박 | 0.400 | 0.420 | 0.410 |
| 16. 금융 | 0.433 | 0.420 | 0.427 |
| 17. 연구개발업 | 1.100 | 0.800 | 0.950 |
| 18. 사업지원서비스 | 0.450 | 0.800 | 0.625 |
| 19. 교육 | 0.000 | -0.050 | -0.025 |
| 20. 보건사회 | 0.550 | 0.600 | 0.575 |
| 21. 문화/예술 | 0.433 | 0.420 | 0.427 |
전 산업 혁신 − 기준(8장, 세 구간 평균): 0.47%p, 구간별 {'2017~21': 0.2, '2022~26': 0.5, '2027~30': 0.7}, 11장 2016~2030: 0.47%p
| 설문 E4-1 | 객관 노출 지수 | 고용정보원(2017) ΔVA | |
|---|---|---|---|
| 설문 E4-1 | 1.000 | 0.490 | 0.050 |
| 객관 노출 지수 | 0.490 | 1.000 | 0.610 |
| 고용정보원(2017) ΔVA | 0.050 | 0.610 | 1.000 |
설문 척도로 옮기기(대안 1b). 객관 지표는 업종 간 차이가 설문보다 훨씬 크다(정보통신의 특허 밀도는 다른 업종의 수십 배). 그대로 배분에 쓰면 효과가 한두 산업에 몰리므로, 설문이 말하는 효과의 평균과 산업 간 표준편차(부가가치 가중)는 유지하고 순위·간격만 노출 지수로 바꾼다: $a'_i = \bar a + s_a (z_i - \bar z)/s_z$.
z62 = np.array([zg[g] for g in grp])
a1b = I.survey_scale_shape(z62, a, base.loc[C.START].values)
print(f"62개 산업 순위상관(설문 a, 노출 a'): {R.rank_corr(a, a1b):.3f}")
62개 산업 순위상관(설문 a, 노출 a'): 0.381
3. 기존 산업모형 — 보고서1 선택 모형¶
62분류·로그차분·산업연관표 사전분포·외생 6종의 베이지언 VARX(P = 4, Q = 2, λ = 0.2)를 2000Q1–2025Q4로 적합한다(보고서1 5장 패키지와 같은 계산). 같은 모형으로 기준 시나리오(S1)를 다시 내면 드리프트 재설정 후 바텀업 합계가 보고서1 5장 표의 값(2035년 2,794조 원)과 같아야 한다.
s1 = pd.read_csv(C.EXOG_SCEN, encoding="utf-8-sig"); s1 = s1[s1["시나리오"] == "S1"].set_index("분기")
f_old = X.forecast_s1(L, gdp, exo, B, s1, C.ANCHOR_GROWTH, False)
bu35 = f_old.sum(axis=1).loc[C.END] / 1e3
A = X.lag_blocks(B, n)
comp_mat = np.block([[np.hstack([Al.T for Al in A])], [np.eye(n * (len(A) - 1), n * len(A))]])
eig = max(abs(np.linalg.eigvals(comp_mat)))
S = sum(A); off = ~np.eye(n, dtype=bool)
print(f"바텀업(드리프트 재설정 후) 2035년: {bu35:,.1f}조 원(보고서1 5장 표: 2,794조 원)")
print(f"동반행렬 최대 고유값 절댓값 {eig:.3f}(1보다 작아 안정), 교차 시차계수 합의 음수 비율 {(S[off] < 0).mean():.2f}, 자기 시차계수 합 평균 {np.diag(S).mean():+.3f}")
바텀업(드리프트 재설정 후) 2035년: 2,793.7조 원(보고서1 5장 표: 2,794조 원) 동반행렬 최대 고유값 절댓값 0.781(1보다 작아 안정), 교차 시차계수 합의 음수 비율 0.46, 자기 시차계수 합 평균 -0.057
4. 대안 1 — 기존 계수 고정, AI 외생 항 추가¶
기존 계수 $A_l$은 그대로 두고 AI 항 $\gamma_i x_t$만 더한다. 기준 시나리오에서는 $x_t = 0$이므로 기존 전망은 정의상 바뀌지 않는다. AI 확산 시나리오의 효과는 $\delta_t = \sum_l A_l^\top \delta_{t-l} + \gamma x_t$로 퍼지며, 누적 $D_t$를 기준 경로에 곱한다.
사전 정보를 어디에 두는가. 설문 E4-1은 2040년까지 AI가 매출에 미칠 누적 영향을 묻는다. 그래서 설문 정보는 동시항 $\gamma$가 아니라 모형의 장기 반응 $M\gamma$ ($M = (I - \sum_l A_l^\top)^{-1}$)에 둔다. 장기 반응이 설문 형태가 되도록 동시항을 $\gamma = (I - \sum_l A_l^\top)\,a$로 정하는 것이 중심 사양('장기')이다. 비교를 위해 파급 없는 현행 4장 방식('직접')과, 설문 형태를 동시항에 그대로 넣은 사양('동시항', 5절 진단)도 계산한다.
specs = [("현행(직접)", a, "직접", A), ("대안1a 설문·장기", a, "장기", A), ("대안1b 노출·장기", a1b, "장기", A),
("대안1c 고용정보원·장기", k62, "장기", A), ("참고 노출·직접", a1b, "직접", A), ("진단 설문·동시항", a, "동시항", A)]
rows, prem, paths = [], {}, {}
for lab, shape, mode, AA in specs:
ai, p = R.scenario(base, AA, shape, xq, C.LAMBDA, mode)
rows.append(R.summarize(lab, base, ai, p)); prem[lab] = p; paths[lab] = ai.sum(axis=1) / 1e3
summ = pd.DataFrame(rows).set_index("사양")
display(summ)
| AI_2035_조 | 기준_2035_조 | AI_CAGR | 기준_CAGR | 차이_%p | 수준차이_조 | 프리미엄_최소 | 프리미엄_최대 | 음의_산업수 | |
|---|---|---|---|---|---|---|---|---|---|
| 사양 | |||||||||
| 현행(직접) | 2,692.703 | 2,609.028 | 2.142 | 1.820 | 0.322 | 83.675 | 0.400 | 0.620 | 0 |
| 대안1a 설문·장기 | 2,690.796 | 2,609.028 | 2.135 | 1.820 | 0.315 | 81.768 | 0.393 | 0.624 | 0 |
| 대안1b 노출·장기 | 2,690.588 | 2,609.028 | 2.134 | 1.820 | 0.314 | 81.560 | 0.385 | 0.652 | 0 |
| 대안1c 고용정보원·장기 | 2,690.570 | 2,609.028 | 2.134 | 1.820 | 0.314 | 81.542 | -0.040 | 0.856 | 1 |
| 참고 노출·직접 | 2,692.702 | 2,609.028 | 2.142 | 1.820 | 0.322 | 83.674 | 0.388 | 0.647 | 0 |
| 진단 설문·동시항 | 2,689.780 | 2,609.028 | 2.131 | 1.820 | 0.311 | 80.752 | -0.405 | 0.906 | 9 |
P62 = pd.DataFrame(prem, index=names)
d1b = (P62["대안1b 노출·장기"] - P62["현행(직접)"]).sort_values()
print("대안1a − 현행: 최대 절댓값 %.3f%%p" % (P62["대안1a 설문·장기"] - P62["현행(직접)"]).abs().max())
print("대안1b − 현행(하향 큰 5개):", d1b.head(5).round(2).to_dict())
print("대안1b − 현행(상향 큰 5개):", d1b.tail(5).round(2).to_dict())
d1c = (P62["대안1c 고용정보원·장기"] - P62["현행(직접)"]).sort_values()
print("대안1c − 현행(하향 큰 5개):", d1c.head(5).round(2).to_dict())
print("대안1c − 현행(상향 큰 5개):", d1c.tail(5).round(2).to_dict())
대안1a − 현행: 최대 절댓값 0.052%p
대안1b − 현행(하향 큰 5개): {'56.교육서비스업': -0.14, '21.금속가공제품': -0.09, '10.가죽제품': -0.08, '9.섬유ㆍ의복': -0.08, '17.의료ㆍ의약품': -0.07}
대안1b − 현행(상향 큰 5개): {'38.창고ㆍ운송보조서비스업': 0.06, '37.항공운송업': 0.06, '49.부동산업': 0.06, '51.연구개발업': 0.07, '53.과학기술관련전문서비스업': 0.08}
대안1c − 현행(하향 큰 5개): {'56.교육서비스업': -0.62, '21.금속가공제품': -0.35, '8.담배': -0.33, '7.음료품': -0.33, '6.식료품': -0.33}
대안1c − 현행(상향 큰 5개): {'45.정보서비스업': 0.17, '42.방송업': 0.18, '40.출판업': 0.18, '51.연구개발업': 0.38, '53.과학기술관련전문서비스업': 0.38}
5. 진단 — 설문 형태를 동시항에 그대로 넣으면¶
동시항 사양에서는 효과가 기존 VARX의 교차 시차계수를 따라 퍼진다. 이 계수는 분기 성장률 사이의 단기 공행을 요약한 축약형 계수이며, 공급망 관계를 뜻하지 않는다. 교차계수 합은 산업연관 연계의 강약과 관계없이 거의 절반이 음(−)이다. 장기 배수 $M$으로 산업별 효과를 자기 몫과 다른 산업에서 온 몫으로 나누면, 음(−)의 효과가 어디에서 오는지 보인다. 분해는 현행 프리미엄(%p)과 같은 척도로 맞추었다.
Wt = Wio.values.T
sign =pd.DataFrame([{"산업연관 연계 분위": f"{lo:.0%}–{hi:.0%}", "교차계수 합 평균": S[m].mean(), "음수 비율": (S[m] < 0).mean()}
for lo, hi in [(0, .25), (.25, .5), (.5, .75), (.75, .9), (.9, 1)]
for m in [off & (Wt >= np.quantile(Wio.values, lo)) & (Wt <= np.quantile(Wio.values, hi))]])
display(sign)
scale = float(P62["현행(직접)"].mean() / a.mean())
dec = X.spillover_decomp(A, a * scale, names)
dec.to_csv(os.path.join(C.OUTPUT, "spillover_diag.csv"), encoding="utf-8-sig")
neg = dec[dec["합계_장기"] < 0]
display(dec.sort_values("합계_장기").head(10))
print(f"동시항 사양에서 장기 효과가 음(−)인 산업 {len(neg)}개. 가장 큰 음의 파급원:", neg["가장_큰_음의_파급원"].value_counts().to_dict())
| 산업연관 연계 분위 | 교차계수 합 평균 | 음수 비율 | |
|---|---|---|---|
| 0 | 0%–25% | 0.001 | 0.473 |
| 1 | 25%–50% | 0.001 | 0.469 |
| 2 | 50%–75% | 0.007 | 0.434 |
| 3 | 75%–90% | 0.007 | 0.453 |
| 4 | 90%–100% | -0.006 | 0.468 |
| 직접 | 자기몫_장기 | 파급몫_장기 | 합계_장기 | 가장_큰_음의_파급원 | 그_크기 | 가장_큰_양의_파급원 | |
|---|---|---|---|---|---|---|---|
| 37.항공운송업 | 0.458 | 0.476 | -1.111 | -0.635 | 55.공공행정ㆍ국방 | -0.411 | 38.창고ㆍ운송보조서비스업 |
| 14.석탄ㆍ석유제품 | 0.490 | 0.446 | -1.039 | -0.593 | 55.공공행정ㆍ국방 | -1.206 | 9.섬유ㆍ의복 |
| 38.창고ㆍ운송보조서비스업 | 0.458 | 0.523 | -1.055 | -0.531 | 49.부동산업 | -0.365 | 62.수리ㆍ개인서비스업 |
| 36.수상운송업 | 0.458 | 0.473 | -0.888 | -0.415 | 49.부동산업 | -0.260 | 38.창고ㆍ운송보조서비스업 |
| 35.육상운송업 | 0.458 | 0.508 | -0.873 | -0.365 | 49.부동산업 | -0.341 | 62.수리ㆍ개인서비스업 |
| 6.식료품 | 0.529 | 0.462 | -0.650 | -0.188 | 49.부동산업 | -0.137 | 28.가구ㆍ기타제품 |
| 7.음료품 | 0.529 | 0.521 | -0.663 | -0.142 | 49.부동산업 | -0.132 | 21.금속가공제품 |
| 9.섬유ㆍ의복 | 0.480 | 0.465 | -0.567 | -0.102 | 55.공공행정ㆍ국방 | -0.225 | 46.금융업 |
| 28.가구ㆍ기타제품 | 0.495 | 0.512 | -0.576 | -0.064 | 55.공공행정ㆍ국방 | -0.422 | 54.사업지원서비스업 |
| 10.가죽제품 | 0.480 | 0.477 | -0.481 | -0.004 | 55.공공행정ㆍ국방 | -0.201 | 18.고무ㆍ플라스틱제품 |
동시항 사양에서 장기 효과가 음(−)인 산업 10개. 가장 큰 음의 파급원: {'49.부동산업': 5, '55.공공행정ㆍ국방': 5}
6. 대안 2 — AI 확산 갭을 일곱째 외생으로 넣어 다시 추정¶
6-1. 자료만으로는 얼마나 알 수 있는가. AI 동시항 계수에 정보가 없는 사전(평균 0, 분산 10⁶)을 두고 추정한 계수 $\hat g_i$와 그 정밀도를 본다. 정밀도는 방정식별 사후공분산의 AI 대각원소에서 구하므로 AI 갭과 다른 설명변수의 상관을 반영한다.
6-2. 사전분포. $\gamma_i \sim N(\beta a_i,\ \tau_i^2)$. 공통 척도 $\beta$는 $\hat g_i \approx \beta a_i$의 정밀도 가중 최소제곱(경험적 베이즈)으로 정한다. 폭은 두 가지로 둔다. ① 설문 표본오차만: $\tau_i = |\beta|\,SE_i$. ② 계층: $\tau_i^2 = (\beta SE_i)^2 + \hat\tau^2$, $\hat\tau^2$은 설문으로 설명되지 않는 산업별 차이의 적률 추정치이다. 사후평균에서 자료가 차지하는 비중은 정밀도 / (정밀도 + 1/사전분산)이다.
se_i = np.array([se_tab.loc[g, "se"] for g in grp])
r2 = R.alt2_estimate(L, exo, Wio, gap, a, se_i)
t_i = r2["g_data"] * np.sqrt(r2["prec"])
diag2 = {"자료_표준오차_중앙값": float(np.median(1 / np.sqrt(r2["prec"]))),
"유의(|t|>1.96)_산업수": int((np.abs(t_i) > 1.96).sum()), "우연_기대_산업수": 0.05 * n,
"자료계수_양수_산업수": int((r2["g_data"] > 0).sum()),
"순위상관(자료계수,설문)": R.rank_corr(r2["g_data"], a),
"beta": r2["beta"], "beta_표준오차": r2["beta_se"], "beta_t": r2["beta"] / r2["beta_se"], "tau2_계층": r2["tau2"]}
for nm, sp in r2["specs"].items():
diag2[f"자료비중_최대[{nm}]"] = float(sp["data_weight"].max())
diag2[f"사후/사전_순위상관[{nm}]"] = R.rank_corr(sp["post"], a)
diag2 = pd.Series(diag2)
display(diag2.to_frame("값"))
| 값 | |
|---|---|
| 자료_표준오차_중앙값 | 5.657 |
| 유의(|t|>1.96)_산업수 | 1.000 |
| 우연_기대_산업수 | 3.100 |
| 자료계수_양수_산업수 | 31.000 |
| 순위상관(자료계수,설문) | 0.354 |
| beta | 0.080 |
| beta_표준오차 | 0.089 |
| beta_t | 0.902 |
| tau2_계층 | 0.000 |
| 자료비중_최대[설문 표본오차] | 0.000 |
| 사후/사전_순위상관[설문 표본오차] | 0.998 |
| 자료비중_최대[계층(경험적 베이즈)] | 0.000 |
| 사후/사전_순위상관[계층(경험적 베이즈)] | 0.998 |
coef = pd.DataFrame({"설문업종": grp, "자료계수": r2["g_data"], "자료_표준오차": 1 / np.sqrt(r2["prec"]), "t": t_i,
"사전평균": r2["specs"]["설문 표본오차"]["prior_mean"], "사후평균": r2["specs"]["설문 표본오차"]["post"]}, index=names)
display(coef.sort_values("t"))
(비공개 설문 집계를 보여주는 셀이다. 공개 화면에서는 출력을 생략했다. 자료를 가진 경우 직접 실행하면 표시된다.)
6-3. 기존 전망은 얼마나 바뀌는가. 재추정 모형으로 기준 시나리오(미래 AI 갭 0)를 다시 내고, 보고서1 5장과 같은 비례 벤치마킹(해마다 모든 산업에 같은 배율)을 거친 뒤의 산업별 변화를 본다. 벤치마킹 후 산업별 변화는 2035년 구성비의 변화와 같다.
6-4. AI 확산 시나리오. 사후평균을 장기 효과의 형태로 두고, 재추정 계수의 동학으로 대안 1과 같은 방식('장기')으로 계산한다.
bc_rows, bc_ind = [], {}
for nm, sp in r2["specs"].items():
bc, ch = R.baseline_change(L, gdp, exo, B, sp["B"], gap, s1, C.ANCHOR_GROWTH)
bc_rows.append({"사전분포": nm} | bc); bc_ind[nm] = ch
A2 = X.lag_blocks(sp["B"], n)
ai, p = R.scenario(base, A2, sp["post"], xq, C.LAMBDA, "장기")
lab = f"대안2 {nm}"
rows.append(R.summarize(lab, base, ai, p)); prem[lab] = p; paths[lab] = ai.sum(axis=1) / 1e3
bct = pd.DataFrame(bc_rows).set_index("사전분포")
display(bct)
bci = pd.DataFrame(bc_ind)
display(bci.iloc[:, 0].sort_values().iloc[[0, 1, 2, -3, -2, -1]].to_frame("벤치마킹 후 변화(%)"))
| 바텀업_기존_조 | 바텀업_재추정_조 | 바텀업_변화_% | 벤치마킹후_최대_% | 벤치마킹후_최소_% | 벤치마킹후_절대중앙_% | |
|---|---|---|---|---|---|---|
| 사전분포 | ||||||
| 설문 표본오차 | 2,793.745 | 2,786.618 | -0.255 | 0.864 | -0.298 | 0.120 |
| 계층(경험적 베이즈) | 2,793.745 | 2,786.618 | -0.255 | 0.864 | -0.298 | 0.120 |
| 벤치마킹 후 변화(%) | |
|---|---|
| 4.석탄ㆍ원유ㆍ천연가스 | -0.298 |
| 56.교육서비스업 | -0.263 |
| 43.통신업 | -0.248 |
| 38.창고ㆍ운송보조서비스업 | 0.554 |
| 37.항공운송업 | 0.656 |
| 14.석탄ㆍ석유제품 | 0.864 |
7. 산출물 저장¶
summ = pd.DataFrame(rows).set_index("사양")
summ.to_csv(os.path.join(C.OUTPUT, "summary_variants.csv"), encoding="utf-8-sig")
P62 = pd.DataFrame(prem, index=names)
P62.insert(0, "설문업종", grp)
P62.to_csv(os.path.join(C.OUTPUT, "premium_62_variants.csv"), encoding="utf-8-sig")
pd.DataFrame(paths).to_csv(os.path.join(C.OUTPUT, "paths_total_variants.csv"), encoding="utf-8-sig")
diag2.to_frame("값").to_csv(os.path.join(C.OUTPUT, "alt2_diagnostics.csv"), encoding="utf-8-sig")
bct.to_csv(os.path.join(C.OUTPUT, "alt2_baseline_change.csv"), encoding="utf-8-sig")
bci.to_csv(os.path.join(C.OUTPUT, "alt2_baseline_change_62.csv"), encoding="utf-8-sig")
pd.Series({"바텀업_2035_조": bu35, "최대고유값": eig, "교차계수_음수비율": float((S[off] < 0).mean())}).to_frame("값").to_csv(
os.path.join(C.OUTPUT, "model_check.csv"), encoding="utf-8-sig")
display(summ)
print("저장:", sorted(f for f in os.listdir(C.OUTPUT) if f.endswith(".csv")))
| AI_2035_조 | 기준_2035_조 | AI_CAGR | 기준_CAGR | 차이_%p | 수준차이_조 | 프리미엄_최소 | 프리미엄_최대 | 음의_산업수 | |
|---|---|---|---|---|---|---|---|---|---|
| 사양 | |||||||||
| 현행(직접) | 2,692.703 | 2,609.028 | 2.142 | 1.820 | 0.322 | 83.675 | 0.400 | 0.620 | 0 |
| 대안1a 설문·장기 | 2,690.796 | 2,609.028 | 2.135 | 1.820 | 0.315 | 81.768 | 0.393 | 0.624 | 0 |
| 대안1b 노출·장기 | 2,690.588 | 2,609.028 | 2.134 | 1.820 | 0.314 | 81.560 | 0.385 | 0.652 | 0 |
| 대안1c 고용정보원·장기 | 2,690.570 | 2,609.028 | 2.134 | 1.820 | 0.314 | 81.542 | -0.040 | 0.856 | 1 |
| 참고 노출·직접 | 2,692.702 | 2,609.028 | 2.142 | 1.820 | 0.322 | 83.674 | 0.388 | 0.647 | 0 |
| 진단 설문·동시항 | 2,689.780 | 2,609.028 | 2.131 | 1.820 | 0.311 | 80.752 | -0.405 | 0.906 | 9 |
| 대안2 설문 표본오차 | 2,690.798 | 2,609.028 | 2.135 | 1.820 | 0.315 | 81.770 | 0.393 | 0.624 | 0 |
| 대안2 계층(경험적 베이즈) | 2,690.798 | 2,609.028 | 2.135 | 1.820 | 0.315 | 81.770 | 0.393 | 0.624 | 0 |
저장: ['ai_exposure_21.csv', 'ai_index_quarterly.csv', 'alt2_baseline_change.csv', 'alt2_baseline_change_62.csv', 'alt2_diagnostics.csv', 'exposure_rank_corr.csv', 'keis_r14_dva_21.csv', 'keis_r14_total.csv', 'model_check.csv', 'paths_total_variants.csv', 'premium_62_variants.csv', 'spillover_diag.csv', 'summary_variants.csv', 'table1_variants.csv', 'table2_baseline_change.csv', 'table3_premium_diff.csv', 'triangulation_rank_corr.csv', 'verification.csv']