모형은 하나인데 파라미터가 다르니 답이 세 가지다. 그렇다면 이 중 어느 것이 “좋은” 파라미터인가? 이 질문에 답하려면 먼저 “좋다”의 기준이 있어야 한다. 그 기준을 세우고, 기준에 맞는 파라미터를 찾는 일이 다음 절의 학습이다.
모형의 학습 (Learning)
“데이터를 잘 나타낸다”는 것은 무엇인가
모형은 \(X\)와 \(y\)의 관계에 대한 가설이고, 파라미터를 정하면 그 가설은 구체적인 식이 된다고 했다. 그 식이 데이터를 “잘 나타낸다”는 말의 뜻을 정확히 해 두자. 절차는 세 단계다.
파라미터가 정해진 모형에 데이터 포인트 하나의 \(x\)를 넣는다. 모형이 내놓는 값이 예측값 \(\hat{y}\)다.
그 데이터 포인트에 실제로 기록된 \(y\)와 비교한다. 둘의 차이 \(e = y - \hat{y}\)가 오차(잔차)다.
모든 데이터 포인트에 대해 1~2를 반복해 오차를 모은다. 오차가 전체적으로 작을수록 “잘 나타내는” 파라미터다.
후보 A(\(w_0 = 20000,\ w_1 = 5000\))에 사원 8명의 경력을 하나씩 넣어 보자.
코드
import pandas as pdsal_x = [1.5, 2.5, 4.2, 5.1, 6.7, 8.3, 9.5, 13.0]sal_y = [31000, 39000, 43000, 49000, 54000, 67000, 92000, 129000]b0, b1 =20000, 5000rows = []for i, (x, y) inenumerate(zip(sal_x, sal_y), start=1): y_hat = b0 + b1 * x e = y - y_hat rows.append({'사원': i,'경력 $x$': x,'실제 연봉 $y$': f'{y:,}','예측 ŷ = 20000 + 5000x': f'{y_hat:,.0f}','오차 e = y − ŷ': f'{e:+,.0f}','e²': f'{e*e/1e6:,.1f}M', })rows.append({'사원': '합', '경력 $x$': '', '실제 연봉 $y$': '','예측 ŷ = 20000 + 5000x': '','오차 e = y − ŷ': f'{sum(y - (b0 + b1*x) for x, y inzip(sal_x, sal_y)):+,.0f}','e²': f'{sum((y - (b0 + b1*x))**2for x, y inzip(sal_x, sal_y))/1e6:,.1f}M'})pd.DataFrame(rows).to_html(index=False, border=0, escape=False)
표 5: 후보 A (ŷ = 20000 + 5000x)를 사원 8명에게 적용한 결과
사원
경력 \(x\)
실제 연봉 \(y\)
예측 ŷ = 20000 + 5000x
오차 e = y − ŷ
e²
1
1.5
31,000
27,500
+3,500
12.2M
2
2.5
39,000
32,500
+6,500
42.2M
3
4.2
43,000
41,000
+2,000
4.0M
4
5.1
49,000
45,500
+3,500
12.2M
5
6.7
54,000
53,500
+500
0.2M
6
8.3
67,000
61,500
+5,500
30.2M
7
9.5
92,000
67,500
+24,500
600.2M
8
13.0
129,000
85,000
+44,000
1,936.0M
합
+90,000
2,637.5M
사원 3(경력 4.2년): 예측 41,000 vs 실제 43,000. 거의 맞았다.
사원 8(경력 13년): 예측 85,000 vs 실제 129,000. 44,000이나 모자란다.
후보 A는 오차가 전부 \(+\)다. 직선이 모든 점 아래에 있다는 뜻이니, 이 직선은 전체적으로 너무 낮다. 다른 파라미터에서는 오차에 \(+\)와 \(-\)가 섞이고(아래 보드에서 확인할 수 있다), 그대로 더하면 서로 상쇄되어 얼마나 틀렸는지 보이지 않는다. 그래서 부호를 없애기 위해 제곱해서 더한다.
잔차 제곱합 (Sum of Squared Errors)
\[L = \sum_{i=1}^{n} (y_i - \hat{y}_i)^2\]
파라미터가 데이터를 얼마나 못 맞히는지를 숫자 하나로 요약한 값. 작을수록 잘 맞는다. Ch03에서 손실함수(loss function)라는 이름으로 일반화한다.
Plot.plot({width:500,height:400,marginLeft:70,style: { fontFamily:"Pretendard, sans-serif",fontSize:"12px" },x: { label:"경력 (년)",domain: [0,15],grid:true },y: { label:"연봉 ($)",domain: [-20000,160000],grid:true,tickFormat: d => (d/1000) +"k" },marks: [ Plot.ruleY([0], { stroke:"#999" }),// 잔차 점선: 실제 y 와 예측 ŷ 사이 Plot.ruleX(sal_rows, {x:"x",y1:"yhat",y2:"y",stroke: r =>Math.abs(r.e) >10000?"#E65100":"#BDBDBD",strokeWidth: r =>Math.min(3,1+Math.abs(r.e) /20000),strokeDasharray:"5,3" }),// 현재 파라미터의 직선 ŷ = w₀ + w₁·x Plot.line(sal_line, { x:"x",y:"y",stroke: sal_clr,strokeWidth:2.5 }),// 예측값 ŷᵢ (직선 위의 점) Plot.dot(sal_rows, { x:"x",y:"yhat",fill:"white",stroke: sal_clr,strokeWidth:1.5,r:4 }),// 실제 데이터 포인트 (x, y) Plot.dot(sal_rows, { x:"x",y:"y",fill:"#1F3F7A",r:6,opacity:0.9 }), Plot.text([`ŷ = ${sal_b0e.toFixed(0)} + ${sal_b1e.toFixed(0)}·x`], {frameAnchor:"bottom-right",fill: sal_clr,fontSize:11,fontWeight:"700",dx:-8,dy:-10 }) ]})
직선으로 충분한가? 슬라이더를 아무리 조절해도 이 데이터의 모든 점을 지나는 직선은 없다. 실제로 이 사원 데이터는 경력이 길어질수록 연봉이 가팔라지는 모양이라, 직선보다 곡선이 더 잘 맞는다. 그렇다면 2차식, 3차식으로 차수를 계속 올리면 항상 좋아질까? — 이 질문의 답은 Ch04의 과적합에서 만난다.
학습이 정하지 않는 것: 하이퍼파라미터
방금 보드에서 우리가 찾은 것은 \(w_0\)와 \(w_1\)이었다. 그런데 “직선으로 하자”, 즉 차수를 1로 하자는 결정은 누가 했는가? 데이터가 아니라 우리가 했다. 학습은 이미 정해진 모형 안에서 파라미터를 찾을 뿐, 모형의 형태 자체를 바꾸지는 않는다. 이렇게 학습이 시작되기 전에 사람이 정해 두어야 하는 값이 따로 있다.
하이퍼파라미터 (Hyperparameter)
학습으로 정해지지 않고, 학습을 시작하기 전에 사람이 미리 정해 주어야 하는 값.
누가 정하는가
예
파라미터
데이터가 정한다 (= 학습)
절편 \(w_0\), 기울기 \(w_1\)
하이퍼파라미터
사람이 정한다
다항식의 차수, 은닉층의 노드 수(Ch02), 학습률·배치 크기(Ch04)
\(y = w_0 + w_1 x + w_2 x^2\)에서 “2차식으로 하자”는 사람의 결정(하이퍼파라미터)이고, \(w_0, w_1, w_2\)의 값은 데이터가 정한다(파라미터). 하이퍼파라미터를 잘못 고르면 학습을 아무리 잘해도 좋은 모형이 나오지 않는다 — Ch04에서 확인한다.
모형의 이용: 예측과 추론
예측 (Prediction)
예측 (Prediction)
새로운 데이터의 \(x\)값이 주어질 때, 학습된 파라미터를 이용하여 \(y\)값을 예측하는 것.
학습된 모형이 \(y = 15000 + 8000x\)라면:
코드
import pandas as pdrows = []for x_new in [4, 6, 8, 10]: y_pred =15000+8000* x_new rows.append({'경력 (년)': x_new,'예측식': f'15000 + 8000 × {x_new}','예측 연봉 ($)': f'{y_pred:,}', })pd.DataFrame(rows).to_html(index=False, border=0, escape=False)
표 7: 학습된 모형을 이용한 예측
경력 (년)
예측식
예측 연봉 ($)
4
15000 + 8000 × 4
47,000
6
15000 + 8000 × 6
63,000
8
15000 + 8000 × 8
79,000
10
15000 + 8000 × 10
95,000
추론 (Inference)
추론 (Inference)
\(y\)를 예측하는 데 있어 \(X\)의 중요한 특성(feature)이 무엇인지, 그리고 그 방향성에 대하여 설명하는 것.
모든 모형에서 추론이 가능하지는 않다
명확한 수학적 형태를 가진 모형에서만 가능
\(y = 15000 + 8000x\)에서 추론할 수 있는 것:
파라미터
값
추론 내용
\(w_0 = 15000\)
절편
회사에 처음 입사 시 연봉이 약 $15,000
\(w_1 = 8000\)
기울기
1년 경력이 늘 때마다 연봉이 약 $8,000씩 인상
주의 — 추론은 인과가 아니다
위 문장은 “이 데이터에서 경력과 연봉이 함께 움직였다”는 관찰이다. 경력이 연봉을 올린 원인이라는 뜻이 아니다.
경력이 긴 사람이 애초에 능력이 좋았을 수도 있고, 두 변수 모두 나이의 영향을 받았을 수도 있다. 인과를 주장하려면 실험 설계가 필요하다 — 데이터를 관찰하는 것만으로는 알 수 없다. 모형이 알려주는 것은 언제나 연관성이지 인과가 아니다.
변수의 종류
숫자형 변수 (Numerical Variable)
숫자형 변수
실수나 정수로 표현할 수 있으며, 값의 차이가 의미를 가지는 변수.
예: 나이(56, 24, …), 온도(27.2, 24.0, …), 연봉(40000, …)
범주형 변수 (Categorical Variable)
범주형 변수
실수로 표현할 수 없으며, 분절된 서로 다른 값을 가지는 변수.
예: 성별 {남자, 여자}, 브랜드 {삼성, 애플}, 결혼여부 {yes, no}
서로 다른 값에 숫자를 부여하더라도(남=1, 여=2) 숫자 간의 차이는 무의미
순서형 변수 (Ordinal Variable)
범주형과 숫자형 사이에 하나가 더 있다. 실무에서 매우 자주 나오는데, 놓치기 쉽다.
순서형 변수
범주형이지만 순서가 있는 변수. 크기 비교는 되지만, 간격은 의미가 없다.
예: 학점 {A, B, C}, 만족도 {매우 불만 … 매우 만족}, 제품 등급 {1등급, 2등급, 3등급}
“A는 B보다 위”는 말이 되지만, “A − B 와 B − C 가 같다”는 보장되지 않는다
세 종류를 가르는 두 개의 질문
질문
숫자형
순서형
범주형
값을 빼면 의미가 있는가?
✅
❌
❌
값에 순서가 있는가?
✅
✅
❌
나이 40 − 24 = 16년 → 뺄 수 있다 → 숫자형
학점 A − B = ? → 뺄 수 없다. 하지만 A > B → 순서형
부서 ‘영업’ − ‘개발’ = ? → 뺄 수도, 순서를 매길 수도 없다 → 범주형
이 구분이 Ch04에서 실제로 쓰인다. 신경망에 넣을 때 범주형은 원-핫 인코딩을 해야 하지만, 순서형은 순서를 살려 숫자로 넣는 편이 나은 경우가 많다 (A=3, B=2, C=1). 순서 정보를 버리지 않기 위해서다.