Python

[Python] NumPy를 이용한 간단한 행렬 연산 및 TensorFlow로 선형 회귀 모델 구축

teamnova 2025. 7. 2. 23:36
728x90

오늘은 딥러닝의 가장 기본적인 개념인 "선형회귀(Linear Regression)"를 이해하고자 파이썬 데이터 처리 라이브러리 NumPy 와 딥러닝 프레임워크 TensorFlow 를 사용해 간단한 딥러닝 학습 예제를 만들어보겠습니다. 

 

딥러닝 프로젝트에서 Python은 거의 필수적이라고 할 수 있을 정도로 광범위하게 사용됩니다.

딥러닝의 핵심 라이브러리들이 대부분 Python을 기반으로 하고 있기 때문입니다!

 

 

선형회귀 (Linear Regression) 란 

- 선형 회귀는 데이터들 사이의 "선형적인 관계"를 가장 잘 나타내는 "직선"을 찾아내는 통계/머신러닝 기법.  여기서 선형적인 관계란 변수들(X와 Y)이 직선 형태로 증가하거나 감소하는 경향을 보이는 관계를 말합니다. 

예시

1) 공부 시간에 따른 시험 점수 예측: 공부 시간을 X축, 시험 점수를 Y축으로 두면, 일반적으로 공부를 많이 할수록 점수가 오르는 선형적인 경향을 보임. 선형회귀를 사용하면 이 관계를 가장 잘 설명하는 직선을 찾아낼 수 있습니다. 

2) 집 크기에 따른 집값 예측: 집 크기가 커질수록 집값이 비싸지는 경향을 나타낼 수 있습니다. 

 

 

이 게시글에서는 딥러닝 모델이 데이터를 통해 '규칙'을 학습하는 과정을 코드를 통해 직접 살펴보겠습니다.

 

 

1. 데이터 생성 

# 1. NumPy를 이용한 데이터 생성
print("1. NumPy를 이용한 데이터 생성 시작...")
np.random.seed(42) # 재현성을 위한 시드 설정

X = np.random.rand(100, 1).astype(np.float32) * 10 # 0부터 10까지의 무작위 X 값 100개
y_true = 2 * X + 1 + np.random.randn(100, 1).astype(np.float32) * 1.5 # 실제 y 값 (노이즈 포함)

 

(입력 데이터 / 독립 변수) : 우리가 알고자 하는 정보, 즉 모델이 예측하는 결과에 "영향을 미치는 원인"이 되는 정보입니다. 예를 들어 "공부 시간에 따른 시험점수를 예측"하고자 했을때 "공부시간" 에 해당하는 선행 데이터가 X 값입니다. 

- y_true (실제 정답 데이터 / 종속 변수) : (입력 데이터)에 따라 실제로 나타난 '결과' 또는 '정답' 값입니다. 모델이 예측해야 할 목표입니다. 

 

 

용어 정리 

가중치 (Weight, ) : 입력 가 결과 얼마나 큰 '영향력'이나 '민감도'를 미치는지를 나타내는 값입니다. 선 그래프에서는 '기울기'를 결정합니다. 

ex) 자동차의 '엑셀 페달 민감도'. 가 클수록 의 변화에 따라 가 더 크게 변합니다. / 모의고사 점수 기반 수능 점수 예측 시, 6월/9월 모의고사 점수가 상대적으로 중요하므로 해당 모의고사 점수에 "가중치"를 줄 수 있습니다. 

편향 (Bias, ) :  입력 X가 0일 때의 '기본값' 또는 '시작점'을 나타내는 값입니다. 선 그래프에서는 'y절편'을 결정하며, 선을 위아래로 평행 이동시키는 역할을 합니다. 

딥러닝 모델의 목표는 손실(Loss)을 최소화하는 가중치()와 편향()을 찾는 것이라고 할 수 있습니다. 

 

2. 모델 정의 

# 모델 정의 (간단한 선형 모델: y = Wx + b)
model = tf.keras.Sequential([
    tf.keras.layers.Dense(units=1, input_shape=[1]) # 입력 뉴런 1개, 출력 뉴런 1개
])

# 모델 컴파일 (최적화 함수, 손실 함수 지정)
# optimizer: Adam 옵티마이저를 명시적으로 정의하고 학습률을 지정 (기본 0.001도 괜찮지만, 명시적 설정)
optimizer = tf.keras.optimizers.Adam(learning_rate=0.01) # 학습률을 0.01로 설정 (보통 일반적으로 0.01, 0.001)

# loss: MSE (평균 제곱 오차 - 선형 회귀에서 주로 사용)
model.compile(optimizer=optimizer, loss='mse')

 

 

- 모델 정의: 형태의 선을 그릴 수 있는 가장 기본적인 '계산기'(모델)를 만드는 단계

   -> 직선을 표현하는 가장 기본적인 방정식

 

- 모델 컴파일: 모델을 본격적인 학습 과정에 들어가기 전에, 학습에 필요한 "환경 설정" 또는 "전략 설정"을 해주는 단계

즉, 모델에게 어떻게 학습(최적화)할지, 얼마나 잘했는지(손실 함수)를 알려주는 과정입니다.

먼저 최적화 함수(Optimizer) 로 Adam 를 선택합니다. 모델이 어떤 방향으로, 얼마나 움직여야 정답 선에 가장 가까워질지 알려주는 함수입니다. 학습률은 0.01 로 지정합니다. 

 

손실함수(loss) : 

손실함수란 모델이 그린 선(예측)이 실제 정답 선이랑 "얼마나 틀렸는지"를 점수 매기는 기준입니다. MSE 손실함수 (Mean Squared Error, 평균 제곱 오차)를 선택했습니다. 

이 손실 함수의 목표는 점수를 가장 낮추는 것이며, 모델은 이 MSE 값을 최소화하는 방향으로 학습하게 됩니다.

 

 

3.  모델 학습 

실제로 모델에게 학습 데이터()를 보여주며 W와 b 값을 조정해 나가는 핵심 과정입니다 ! 

# epochs: 전체 데이터셋을 몇 번 반복하여 학습할 것인지 (100 -> 500 또는 1000으로 증가)
# verbose: 학습 과정 출력 레벨 (1은 진행 막대 표시)
print("모델 학습 중...")
history = model.fit(X, y_true, epochs=500, verbose=0) # epochs =  500(충분히 학습되도록)

print("모델 학습 완료!")
print("-" * 30)

 

- model.fit(X, y_true, ...) : 모델을 학습시키는 명령어

- y_true: X에 대한 실제 정답 데이터

- epochs=500: 학습 반복 횟수를 의미합니다.  모델은 전체 X와 y_true 데이터를 500번 반복해서 보면서 를 업데이트 합니다. 이 반복을 통해 모델은 점점 더 파란색 점들의 패턴(규칙 )을 정확하게 찾아내게 됩니다. 

 

 

전체 코드 

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt

# 1. NumPy를 이용한 데이터 생성
print("1. NumPy를 이용한 데이터 생성 시작...")
np.random.seed(42) # 재현성을 위한 시드 설정

X = np.random.rand(100, 1).astype(np.float32) * 10 # 0부터 10까지의 무작위 X 값 100개
y_true = 2 * X + 1 + np.random.randn(100, 1).astype(np.float32) * 1.5 # 실제 y 값 (노이즈 포함)

print(f"X shape: {X.shape}, y_true shape: {y_true.shape}")
print("X 예시:\n", X[:5].flatten())
print("y_true 예시:\n", y_true[:5].flatten())
print("-" * 30)

# 2. TensorFlow를 이용한 선형 회귀 모델 구축 및 학습
print("2. TensorFlow를 이용한 선형 회귀 모델 구축 및 학습 시작...")

# 모델 정의 (간단한 선형 모델: y = Wx + b)
model = tf.keras.Sequential([
    tf.keras.layers.Dense(units=1, input_shape=[1]) # 입력 뉴런 1개, 출력 뉴런 1개
])

# 모델 컴파일 (최적화 함수, 손실 함수 지정)
# optimizer: Adam 옵티마이저를 명시적으로 정의하고 학습률을 지정 (기본 0.001도 괜찮지만, 명시적 설정)
optimizer = tf.keras.optimizers.Adam(learning_rate=0.01) # 학습률을 0.01로 설정 (보통 일반적으로 0.01, 0.001)

# loss: MSE (평균 제곱 오차 - 선형 회귀에서 주로 사용)
model.compile(optimizer=optimizer, loss='mse')

# 모델 학습
# epochs: 전체 데이터셋을 몇 번 반복하여 학습할 것인지 (100 -> 500 또는 1000으로 증가)
# verbose: 학습 과정 출력 레벨 (1은 진행 막대 표시)
print("모델 학습 중...")
history = model.fit(X, y_true, epochs=500, verbose=0) # epochs =  500(충분히 학습되도록)

print("모델 학습 완료!")
print("-" * 30)

# 3. 학습된 모델의 가중치(W)와 편향(b) 확인
print("3. 학습된 모델의 가중치(W)와 편향(b) 확인...")
weights, bias = model.layers[0].get_weights()
print(f"학습된 가중치 (W): {weights.flatten()[0]:.4f}")
print(f"학습된 편향 (b): {bias.flatten()[0]:.4f}")
print("(참고: 실제 값 W=2, b=1)")
print("-" * 30)

# 4. 예측 및 시각화
print("4. 예측 및 시각화...")
y_pred = model.predict(X)

plt.figure(figsize=(8, 6))
plt.scatter(X, y_true, label='Actual Data', alpha=0.7)
plt.plot(X, y_pred, color='red', label='Predicted Line', linewidth=2)
plt.title('Linear Regression with TensorFlow')
plt.xlabel('X')
plt.ylabel('y')
plt.legend()
plt.grid(True)
plt.show()

print("예제 완료!")

 

 

 

4. 결과 

 

그래프 결과:

  • 파란색 점들 (Actual Data): 우리가 미리 생성한 실제 정답 데이터
  • 빨간색 선 (Predicted Line): 모델이 학습을 통해 찾아낸 최적의 값을 바탕으로 그린 예측 선

성공적으로 학습이 잘되어 파란색 점이 모인 곳(정답 데이터) 위로 빨간 선이 그어진 (추론/예측값) 것을 확인할 수 있습니다. 

 

 

감사합니다.