지난 포스트에서 경사 하강법의 개념을 알아봤습니다.
이번엔 실제 코드로 직접 구현하며 개념을 확인해보겠습니다.
전체 코드
1. Cost 함수 직접 구현 vs TensorFlow 비교
import numpy as np
import tensorflow as tf
X = np.array([1, 2, 3])
Y = np.array([1, 2, 3])
# 직접 구현 : (가설 - 정답) 제곱 후 다 더해 평균 내기
def cost_func(W, X, Y):
c = 0
for i in range(len(X)):
c += (W * X[i] - Y[i]) ** 2
return c / len(X)
# TensorFlow로 구현
def costTF_func(W, X, Y):
hypothesis = X * W
return tf.reduce_mean(tf.square(hypothesis - Y))
# W를 -3 ~ 5 사이를 15단계로 쪼개기
W_values = np.linspace(-3, 5, num=15)
print("---cost_func---")
for feed_W in W_values:
curr_cost = cost_func(feed_W, X, Y)
print("{:6.3f} | {:10.5f}".format(feed_W, curr_cost))
print("---costTF_func---")
for feed_W in W_values:
curr_cost = costTF_func(feed_W, X, Y)
print("{:6.3f} | {:10.5f}".format(feed_W, curr_cost))
2. 경사 하강법으로 W 업데이트
import tensorflow as tf
tf.random.set_seed(0) # 재현성을 위해 시드 고정
x_data = [1., 2., 3., 4.]
y_data = [1., 3., 5., 7.]
W = tf.Variable(tf.random.normal([1], -100, 100))
for step in range(300):
hypothesis = W * x_data
cost = tf.reduce_mean(tf.square(hypothesis - y_data))
alpha = 0.01 # 학습률
# 그레디언트 : cost 함수를 W로 편미분한 값
gradient = tf.reduce_mean(tf.multiply(tf.multiply(W, x_data) - y_data, x_data))
# tf.multiply(W, x_data) - y_data → (Wx - y)
# tf.multiply(..., x_data) → (Wx - y) * x
# tf.reduce_mean(...) → 1/m * ∑(Wx - y) * x
# W 업데이트
descent = W - tf.multiply(alpha, gradient) # W - α * gradient
W.assign(descent) # 새로운 값을 W에 저장
if step % 10 == 0:
print("{:5} | {:10.4f} | {:10.6f}".format(step, cost.numpy(), W.numpy()[0]))
코드 1 : Cost 함수, 두 가지 방법으로 구현
직접 구현 vs TensorFlow
지난 포스트에서 배운 비용 함수 수식입니다.
cost(W) = 1/m * ∑(Wx - y)²
이걸 파이썬으로 직접 구현하면:
def cost_func(W, X, Y):
c = 0
for i in range(len(X)):
c += (W * X[i] - Y[i]) ** 2 # (Wx - y)² 누적
return c / len(X) # 전체 개수로 나눠 평균
TensorFlow로 구현하면:
def costTF_func(W, X, Y):
hypothesis = X * W # Wx
return tf.reduce_mean(tf.square(hypothesis - Y)) # 평균((Wx-y)²)
---cost_func---
-3.000 | 74.66667
-2.429 | 54.85714
-1.857 | 38.09524
-1.286 | 24.38095
-0.714 | 13.71429
-0.143 | 6.09524
0.429 | 1.52381
1.000 | 0.00000
1.571 | 1.52381
2.143 | 6.09524
2.714 | 13.71429
3.286 | 24.38095
3.857 | 38.09524
4.429 | 54.85714
5.000 | 74.66667
---costTF_func---
-3.000 | 74.66667
-2.429 | 54.85714
-1.857 | 38.09524
-1.286 | 24.38095
-0.714 | 13.71429
-0.143 | 6.09524
0.429 | 1.52381
1.000 | 0.00000
1.571 | 1.52381
2.143 | 6.09524
2.714 | 13.71429
3.286 | 24.38095
3.857 | 38.09524
4.429 | 54.85714
5.000 | 74.66667
두 함수는 완전히 동일한 계산을 합니다. TensorFlow를 쓰면 훨씬 간결하게 표현할 수 있다는 것을 알 수 있습니다.
W 값에 따른 Cost 변화 확인
W_values = np.linspace(-3, 5, num=15)
np.linspace(-3, 5, num=15) 는 -3부터 5까지를 15단계로 균등하게 나눈 값입니다.
W를 바꿔가며 cost를 출력해보면, W=1 근처에서 cost가 가장 작아지는 것을 직접 눈으로 확인할 수 있습니다.
지난 포스트에서 설명한 U자(바구니) 그래프가 데이터로 나타나는 것입니다.
코드 2 : 경사 하강법으로 W 자동으로 찾기
랜덤한 초기값에서 시작
tf.random.set_seed(0) # 코드를 다시 수행해도 동일하게 재현될 수 있게 시드 고정
W = tf.Variable(tf.random.normal([1], -100, 100))
W를 -100 ~ 100 사이의 랜덤한 값으로 초기화합니다.
어디서 시작하든 경사 하강법이 최적의 W를 찾아가는지 확인하는 것이 목표입니다.
그레디언트(기울기) 계산 및 W 업데이트
지난 포스트에서 배운 경사 하강법 수식입니다.
W := W - α * 1/m * ∑(Wx - y) * x
코드로 표현하면:
alpha = 0.01 # 학습률
# 그레디언트 : cost 함수를 W로 편미분한 값
gradient = tf.reduce_mean(tf.multiply(tf.multiply(W, x_data) - y_data, x_data))
# tf.multiply(W, x_data) - y_data → (Wx - y)
# tf.multiply(..., x_data) → (Wx - y) * x
# tf.reduce_mean(...) → 1/m * ∑(Wx - y) * x
# W 업데이트
descent = W - tf.multiply(alpha, gradient) # W - α * gradient
W.assign(descent) # 새로운 값을 W에 저장
- tf.multiply : 곱셈 연산
- W.assign : W 값을 새로운 값으로 업데이트
학습 결과 확인
300번 반복하면서 10번마다 결과를 출력합니다.
step | cost | W
0 | 18332.2188 | 47.398293
10 | 3855.3564 | 22.638384
20 | 810.9046 | 11.283927
30 | 170.6631 | 6.076973
40 | 36.0217 | 3.689155
50 | 7.7069 | 2.594144
60 | 1.7524 | 2.091991
70 | 0.5001 | 1.861713
80 | 0.2368 | 1.756112
90 | 0.1814 | 1.707684
100 | 0.1698 | 1.685477
110 | 0.1673 | 1.675292
120 | 0.1668 | 1.670622
130 | 0.1667 | 1.668481
140 | 0.1667 | 1.667498
150 | 0.1667 | 1.667048
160 | 0.1667 | 1.666842
170 | 0.1667 | 1.666747
180 | 0.1667 | 1.666703
190 | 0.1667 | 1.666684
200 | 0.1667 | 1.666674
210 | 0.1667 | 1.666670
220 | 0.1667 | 1.666668
230 | 0.1667 | 1.666667
240 | 0.1667 | 1.666667
250 | 0.1667 | 1.666667
260 | 0.1667 | 1.666667
270 | 0.1667 | 1.666667
280 | 0.1667 | 1.666667
290 | 0.1667 | 1.666667 ← W가 1.6에 수렴!
처음엔 W가 엉뚱한 값이지만, 학습을 거듭할수록 W가 점점 2에 가까워지고 cost는 0에 가까워집니다.
x_data = [1, 2, 3, 4], y_data = [1, 3, 5, 7] 에서 1.666~ 으로 설정한 상태에서 hypothesis 값은 1.6666675 3.333335 5.0000024 6.66667 으로 나오니까 얼추 y_data 와 비슷하다고 할 수 있다.
정리
개념 수식 코드
| 비용 함수 | 1/m * ∑(Wx - y)² | tf.reduce_mean(tf.square(hypothesis - Y)) |
| 그레디언트 | 1/m * ∑(Wx - y) * x | tf.reduce_mean(tf.multiply(tf.multiply(W, x_data) - y_data, x_data)) |
| W 업데이트 | W := W - α * gradient | W.assign(W - tf.multiply(alpha, gradient)) |
어떤 랜덤한 초기값에서 시작하더라도 경사 하강법을 반복하면 결국 최적의 W를 찾아낸다는 것을 직접 확인했습니다. 🚀
'AI > ML' 카테고리의 다른 글
| Multi-variable Linear Regression 코드로 구현해보기 (TensorFlow) (0) | 2026.03.07 |
|---|---|
| Multi-variable Linear Regression : 여러 변수로 예측 정확도 높이기 (0) | 2026.03.06 |
| 경사 하강법(Gradient Descent) 으로 최적의 W 찾기 (0) | 2026.03.04 |
| 선형 회귀 코드로 구현해보기 (TensorFlow) (0) | 2026.03.03 |
| 머신러닝 : 선형 회귀(Linear Regression) (0) | 2026.03.02 |