노트북은 예측 → 계산 → 대조 세 부분으로 고정한다. 새 개념은 도입하지 않는다. 본문에서 이미 유도한 것을 수치로 확인할 뿐이다.
1. 예측 (코드를 쓰기 전에)¶
아래 칸을 먼저 채운다. 계산하지 않는다.
고정, 를 100에서 200으로 2배 하면 는 몇 배가 되는가. 증가인가.
예측: ____
, 을 전방 유한차분()으로 구해 을 만들면 와 얼마나, 어느 방향으로 어긋나는가().
예측: ____
의 수치를 1/1000로 바꾸면(천 단위) , , 중 무엇이 변하는가.
예측: ____
2. 계산¶
패키지 호출로 답을 내지 않는다. 생산함수와 차분과 정규방정식을 직접 쌓는다.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import font_manager
# 한국어 글꼴을 후보 목록에서 있는 것으로 고른다
_cands = ['Apple SD Gothic Neo', 'AppleGothic', 'NanumGothic', 'Noto Sans CJK KR', 'Malgun Gothic']
_have = {f.name for f in font_manager.fontManager.ttflist}
for _f in _cands:
if _f in _have:
plt.rcParams['font.family'] = _f
break
plt.rcParams['axes.unicode_minus'] = False
# 생산함수를 손으로 쌓는다
def F(K, L, A=1.0, a=0.3, b=0.7):
return A * K ** a * L ** b
A0, ALPHA = 1.0, 0.3
print('글꼴:', plt.rcParams['font.family'][0])
print('F(100, 100) =', round(F(100.0, 100.0), 4))글꼴: Apple SD Gothic Neo
F(100, 100) = 100.0
예측 1. 을 고정하고 를 2배 한다. 배율이 의 수준을 아는지도 함께 본다.
# 예측 1 — L을 고정한 채 K를 2배 했을 때의 산출 배율을 쌓는다
L0 = 100.0
K1, K2 = 100.0, 200.0
Y1, Y2 = F(K1, L0), F(K2, L0)
ratio = Y2 / Y1
print(f'Y(K=100) = {Y1:.4f} Y(K=200) = {Y2:.4f}')
print(f'배율 Y2/Y1 = {ratio:.4f} 2^0.3 = {2.0 ** ALPHA:.4f}')
print(f'증가율 = {100 * (ratio - 1):.2f}% (30%가 아니다)')
print(f'Δln Y / Δln K = {(np.log(Y2) - np.log(Y1)) / (np.log(K2) - np.log(K1)):.6f}')Y(K=100) = 100.0000 Y(K=200) = 123.1144
배율 Y2/Y1 = 1.2311 2^0.3 = 1.2311
증가율 = 23.11% (30%가 아니다)
Δln Y / Δln K = 0.300000
# 같은 배율이 K의 수준을 모르는지 여러 자리에서 쌓아 본다
print(f"{'K':>9}{'Y(K)':>13}{'Y(2K)':>13}{'Y(2K)/Y(K)':>14}")
for K in [10.0, 100.0, 1000.0, 10000.0]:
print(f'{K:9.0f}{F(K, L0):13.4f}{F(2 * K, L0):13.4f}{F(2 * K, L0) / F(K, L0):14.6f}')
print()
print('덧셈 충격 K→K+100의 배율 — 수준에 의존한다')
print(f' K=100: {F(200.0, L0) / F(100.0, L0):.6f} K=1000: {F(1100.0, L0) / F(1000.0, L0):.6f}') K Y(K) Y(2K) Y(2K)/Y(K)
10 50.1187 61.7034 1.231144
100 100.0000 123.1144 1.231144
1000 199.5262 245.6456 1.231144
10000 398.1072 490.1274 1.231144
덧셈 충격 K→K+100의 배율 — 수준에 의존한다
K=100: 1.231144 K=1000: 1.029006
예측 2. 한계생산을 전방 유한차분으로 만들어 을 와 겨룬다. 3절 수치 표(, , , )와 같은 자리를 쓴다.
# 전방 유한차분으로 한계생산을 쌓는다 — 미분 패키지를 쓰지 않는다
def FK_fd(K, L, h, A=1.0, a=0.3, b=0.7):
return (F(K + h, L, A, a, b) - F(K, L, A, a, b)) / h
def FL_fd(K, L, h, A=1.0, a=0.3, b=0.7):
return (F(K, L + h, A, a, b) - F(K, L, A, a, b)) / h
K0, Lb = 300.0, 100.0
print(f'F_K 전방차분(h=1e-3) = {FK_fd(K0, Lb, 1e-3):.10f}')
print(f'F_K 정확값 αY/K = {ALPHA * F(K0, Lb) / K0:.10f}')
print(f'F_L 전방차분(h=1e-3) = {FL_fd(K0, Lb, 1e-3):.10f}')
print(f'F_L 정확값 βY/L = {0.7 * F(K0, Lb) / Lb:.10f}')F_K 전방차분(h=1e-3) = 0.1390387548
F_K 정확값 αY/K = 0.1390389170
F_L 전방차분(h=1e-3) = 0.9732709593
F_L 정확값 βY/L = 0.9732724192
# 예측 2 — ν별로 KF_K, LF_L, 합, νY, 잔여를 쌓아 3절 표와 대조한다
h = 1e-3
rows = []
print(f"{'ν':>5}{'β':>6}{'Y':>11}{'K·F_K':>11}{'L·F_L':>11}{'합':>11}{'νY':>11}{'잔여':>9}{'상대어긋남':>14}")
for b in [0.6, 0.7, 0.8]:
nu = ALPHA + b
Y = F(K0, Lb, A0, ALPHA, b)
kfk = K0 * FK_fd(K0, Lb, h, A0, ALPHA, b)
lfl = Lb * FL_fd(K0, Lb, h, A0, ALPHA, b)
tot = kfk + lfl
rel = (tot - nu * Y) / (nu * Y)
rows.append((nu, Y, kfk, lfl, tot, rel))
print(f'{nu:5.1f}{b:6.1f}{Y:11.4f}{kfk:11.4f}{lfl:11.4f}{tot:11.4f}'
f'{nu * Y:11.4f}{(1 - nu) * Y:9.2f}{rel:14.3e}')
print()
print('자본의 몫 K·F_K/Y :', [round(r[2] / r[1], 6) for r in rows]) ν β Y K·F_K L·F_L 합 νY 잔여 상대어긋남
0.9 0.6 87.7276 26.3183 52.6365 78.9547 78.9549 8.77 -1.722e-06
1.0 0.7 139.0389 41.7116 97.3271 139.0387 139.0389 0.00 -1.400e-06
1.1 0.8 220.3618 66.1085 176.2893 242.3978 242.3980 -22.04 -1.045e-06
자본의 몫 K·F_K/Y : [0.3, 0.3, 0.3]
# h를 10배씩 줄이며 어긋남이 어떻게 주는지 쌓는다 (ν=1)
hs, rels = [1e-1, 1e-2, 1e-3, 1e-4], []
print(f"{'h':>9}{'합 - νY':>15}{'상대어긋남':>17}{'직전 대비':>13}")
for h_ in hs:
Y = F(K0, Lb)
tot = K0 * FK_fd(K0, Lb, h_) + Lb * FL_fd(K0, Lb, h_)
rel = (tot - Y) / Y
tail = '' if not rels else f'{rel / rels[-1]:13.3f}'
rels.append(rel)
print(f'{h_:9.0e}{tot - Y:15.3e}{rel:17.3e}{tail}') h 합 - νY 상대어긋남 직전 대비
1e-01 -1.946e-02 -1.399e-04
1e-02 -1.946e-03 -1.400e-05 0.100
1e-03 -1.947e-04 -1.400e-06 0.100
1e-04 -1.946e-05 -1.400e-07 0.100
# 생산물 대비 요소지급을 쌓아 그린다
sk = [r[2] / r[1] for r in rows]
sl = [r[3] / r[1] for r in rows]
x = np.arange(3)
fig, ax = plt.subplots(figsize=(5.4, 3.4))
ax.bar(x, sk, 0.5, color='#3b6ea5', label='자본 몫 $KF_K/Y$')
ax.bar(x, sl, 0.5, bottom=sk, color='#d98c3f', label='노동 몫 $LF_L/Y$')
ax.axhline(1.0, ls='--', lw=1.0, color='k')
for i, (u, v) in enumerate(zip(sk, sl)):
ax.text(i, u + v + 0.03, f'{u + v:.2f}', ha='center', fontsize=9)
ax.set_xticks(x)
ax.set_xticklabels([f'ν={r[0]:.1f}' for r in rows])
ax.set_ylabel('생산물 대비 요소지급')
ax.set_ylim(0, 1.35)
ax.legend(loc='lower right', fontsize=8)
ax.set_title('합이 생산물과 만나는 것은 ν=1뿐이다')
plt.tight_layout()
plt.show()
예측 3. 아홉 점 격자 , 에서 의 정규방정식을 직접 세운다. 을 하나로 고정하면 열이 절편 열과 겹쳐 풀리지 않으므로 도 세 값을 쓴다.
# 예측 3 — 아홉 점 격자 자료와 정규방정식을 직접 세운다
Ks, Ls = np.array([100.0, 300.0, 1000.0]), np.array([50.0, 100.0, 200.0])
KK, LL = np.meshgrid(Ks, Ls, indexing='ij')
Kg, Lg = KK.ravel(), LL.ravel()
Yg = F(Kg, Lg)
def ols(K_col, L_col, y):
X = np.column_stack([np.ones_like(K_col), np.log(K_col), np.log(L_col)])
return np.linalg.solve(X.T @ X, X.T @ np.log(y))
c1, a1, b1 = ols(Kg, Lg, Yg)
print('격자 아홉 점 (K, L, Y)')
for K, L, Y in zip(Kg, Lg, Yg):
print(f' {K:7.0f}{L:7.0f}{Y:11.4f}')
print(f'원 단위: ĉ = {c1:+.6f} α̂ = {a1:.12f} β̂ = {b1:.12f} Â = {np.exp(c1):.6f}')격자 아홉 점 (K, L, Y)
100 50 61.5572
100 100 100.0000
100 200 162.4505
300 50 85.5885
300 100 139.0389
300 200 225.8694
1000 50 122.8228
1000 100 199.5262
1000 200 324.1313
원 단위: ĉ = -0.000000 α̂ = 0.300000000000 β̂ = 0.700000000000 Â = 1.000000
# 같은 자료를 K/1000으로 다시 재서 추정한다
c2, a2, b2 = ols(Kg / 1000.0, Lg, Yg)
print(f'천 단위: ĉ = {c2:+.6f} α̂ = {a2:.12f} β̂ = {b2:.12f} Â = {np.exp(c2):.6f}')
print(f'ĉ 이동량 = {c2 - c1:.6f} α·ln1000 = {ALPHA * np.log(1000.0):.6f}')
print(f'Â 배율 = {np.exp(c2) / np.exp(c1):.4f} 1000^0.3 = {1000.0 ** ALPHA:.4f}')
print(f'α̂ 변화 = {a2 - a1:+.3e} β̂ 변화 = {b2 - b1:+.3e}')
# 분배율은 단위에 비례하는 증분으로 쌓는다
sK = {}
for nm, K_, A_ in [('원 단위', 300.0, 1.0), ('천 단위', 0.3, 1000.0 ** ALPHA)]:
sK[nm] = K_ * FK_fd(K_, Lb, 1e-6 * K_, A_) / F(K_, Lb, A_)
print(f'{nm}: K = {K_:8.4f} Y = {F(K_, Lb, A_):.4f} s_K = {sK[nm]:.6f}')천 단위: ĉ = +2.072327 α̂ = 0.300000000000 β̂ = 0.700000000000 Â = 7.943282
ĉ 이동량 = 2.072327 α·ln1000 = 2.072327
 배율 = 7.9433 1000^0.3 = 7.9433
α̂ 변화 = -7.938e-15 β̂ 변화 = +3.442e-15
원 단위: K = 300.0000 Y = 139.0389 s_K = 0.300000
천 단위: K = 0.3000 Y = 139.0389 s_K = 0.300000
# 같은 자료를 semi-log와 log-log 두 축에 찍는다
Kc = np.logspace(1, 3, 200)
m = Lg == 100.0
fig, axes = plt.subplots(1, 2, figsize=(9.6, 3.6))
axes[0].plot(Kc, np.log(F(Kc, 100.0)), color='k')
axes[0].scatter(Kg[m], np.log(Yg[m]), s=20, color='k', zorder=3)
axes[0].set_xlabel('자본 $K$')
axes[0].set_ylabel('$\\ln Y$')
axes[0].set_title('(a) semi-log — 오목 곡선')
axes[1].plot(np.log(Kc), np.log(F(Kc, 100.0)), color='#3b6ea5', label='원 단위')
axes[1].plot(np.log(Kc / 1000.0), np.log(F(Kc, 100.0)), ls='--', color='#c0392b', label='천 단위')
axes[1].scatter(np.log(Kg[m]), np.log(Yg[m]), s=20, color='k', zorder=3)
axes[1].annotate('', xy=(np.log(100.0), np.log(F(100.0, 100.0))),
xytext=(np.log(0.1), np.log(F(100.0, 100.0))),
arrowprops=dict(arrowstyle='<->', lw=0.9))
axes[1].text(np.log(3.0), np.log(F(100.0, 100.0)) + 0.08, 'ln1000 = 6.91', ha='center', fontsize=8)
axes[1].set_xlabel('$\\ln K$')
axes[1].set_ylabel('$\\ln Y$')
axes[1].set_title('(b) log-log — 기울기 0.3, 단위 변경은 평행이동')
axes[1].legend(loc='lower right', fontsize=8)
plt.tight_layout()
plt.show()
# 예측 항목 세 개에 대응하는 수치를 한자리에 모은다
d_ln = (np.log(Y2) - np.log(Y1)) / (np.log(K2) - np.log(K1))
print(f'[예측 1] Y 배율 {ratio:.4f} (= 2^0.3), 증가율 {100 * (ratio - 1):.2f}%, Δln Y/Δln K = {d_ln:.6f}')
print('[예측 2] h=1e-3 상대 어긋남 ' + ', '.join(f'ν={r[0]:.1f}: {r[5]:+.3e}' for r in rows))
print(f' h 10배 축소 시 오차 비 {rels[1] / rels[0]:.3f}, {rels[2] / rels[1]:.3f}, '
f'{rels[3] / rels[2]:.3f}')
print(f'[예측 3] Â {np.exp(c1):.4f} → {np.exp(c2):.4f} ({np.exp(c2) / np.exp(c1):.4f}배), '
f'α̂ 변화 {a2 - a1:+.2e}, s_K {sK["원 단위"]:.6f} → {sK["천 단위"]:.6f}')[예측 1] Y 배율 1.2311 (= 2^0.3), 증가율 23.11%, Δln Y/Δln K = 0.300000
[예측 2] h=1e-3 상대 어긋남 ν=0.9: -1.722e-06, ν=1.0: -1.400e-06, ν=1.1: -1.045e-06
h 10배 축소 시 오차 비 0.100, 0.100, 0.100
[예측 3] Â 1.0000 → 7.9433 (7.9433배), α̂ 변화 -7.94e-15, s_K 0.300000 → 0.300000
3. 대조¶
예측과 계산이 어긋난 지점을 적는다. 어느 쪽이 틀렸는지 판정한다.
| 예측 | 결과 | 어긋남 | 원인 |
|---|---|---|---|
본문 확인: 어긋났으면 (eq-w02-6)·(eq-w02-11)·(eq-w02-7)로 돌아간다.