-
[3월 4주차-3/28]경사하강법을 사용한 선형 회귀 학습 및 예측 평가Why Not SW CAMP 5기/수업 기록 2025. 3. 31. 17:01
📌 경사하강법 (Gradient Descent)
✅ 경사하강법이란?
경사하강법은 함수의 최솟값을 찾기 위해 사용하는 최적화 알고리즘
보통 손실 함수(Loss Function) 의 값을 최소화하는 파라미터(값)
현재 위치에서 기울기를 계산하여 반대 방향으로 이동하는 방식
💡 경사하강법의 작동 원리
- 초기값 설정: 무작위로 파라미터 값을 설정
- 기울기 계산 (Gradient Calculation): 현재 위치에서의 기울기를 계산
- 업데이트 (Update): 기울기의 값을 조정
- 반복 (Iterate): 원하는 최소값에 도달할 때까지 위의 과정을 반복
📊 경사하강법 종류
- 배치 경사하강법 (Batch Gradient Descent):
- 모든 데이터를 사용하여 기울기를 계산
- 정확하지만 데이터가 많을 경우 계산 비용이 큼.
- 확률적 경사하강법 (Stochastic Gradient Descent, SGD):
- 데이터 하나씩 사용하여 기울기를 계산
- 계산 속도가 빠르지만 경로가 불안정할 수 있음
- 미니 배치 경사하강법 (Mini-Batch Gradient Descent):
- 일부 데이터를 묶어 기울기를 계산
- 속도와 정확도 간의 균형이 좋음.
- 적절한 미니 배치 크기를 알아내기 위한 튜닝 작업 필요
❌ 문제점:
- 지역 최솟값 (Local Minimum): 전체 최솟값이 아닌 부분적으로 낮은 값에 갇힐 수 있음
- 학습률 설정 (Learning Rate): 너무 크면 목표를 넘겨버리고, 너무 작으면 학습 속도가 느려짐.
✅ 해결책:
- 학습률 조정 (Learning Rate Adjustment): 점점 작게 줄여가며 최적값을 찾는 방식 (Learning Rate Decay).
- 모멘텀 (Momentum): 이전 업데이트의 방향을 유지하여 빠르고 안정적으로 학습.
- Adam (Adaptive Moment Estimation): 학습률을 자동으로 조정하며 학습하는 방법.
📌 경사하강법을 사용한 선형 회귀 학습 및 예측 평가
경사하강법(Stochastic Gradient Descent, SGD) 를 사용하여 학습 데이터를 기반으로 선형 회귀 모델을 학습하고 예측값을 평가하는 코드 입니다.
✅ 1. 데이터 준비 (train, test)
dataset = [ [25, 100], [52, 256], [38, 152], [32, 140], [25, 150], [45, 183], [40, 175], [55, 203], [28, 152], [42, 198] ] train = dataset[:5] # 학습 데이터 (앞의 5개) test = dataset[5:] # 테스트 데이터 (뒤의 5개)
✅ 2. 회귀계수 초기화 (coef)
coef = [0.0 for i in range(len(train[0]))]- coef = [0.0, 0.0] 로 초기화.
- coef[0]: 절편 (Intercept)
- coef[1]: 기울기 (Slope)
✅ 3. 예측 함수 (predict())
def predict(row, coef): yhat = coef[0] # 절편 (Intercept) for i in range(len(row) - 1): yhat += coef[i+1] * row[i] return yhat- 입력값 row 와 학습된 회귀계수 coef 를 이용하여 예측값 (yhat) 을 계산합니다.
✅ 4. 학습 함수 (coefficients_sgd())
def coefficients_sgd(train, l_rate, n_epoch): coef = [0.0 for i in range(len(train[0]))] for epoch in range(n_epoch): sum_error = 0 for row in train: yhat = predict(row, coef) error = row[-1] - yhat sum_error += error ** 2 # 회귀계수 업데이트 coef[0] = coef[0] + l_rate * error # 절편 업데이트 for i in range(len(row) - 1): coef[i+1] = coef[i+1] + l_rate * error * row[i] # 기울기 업데이트 return coef, math.sqrt(sum_error / len(train)) # 학습 후 회귀계수와 RMSE 반환🔍 코드 설명: coefficients_sgd() 함수
✅ 함수 정의
def coefficients_sgd(train, l_rate, n_epoch):- train: 학습 데이터. (X 값, Y 값) 쌍으로 구성된 리스트.
예) [[X1, Y1], [X2, Y2], ...] - l_rate: 학습률 (Learning Rate).
- 값이 크면 학습이 빠르지만 정확도가 떨어질 수 있음.
- 값이 작으면 학습이 느리지만 정확하게 수렴할 가능성이 높음.
- n_epoch: 학습 반복 횟수 (Epoch).
- 학습 데이터를 몇 번 반복하여 학습할 것인지 설정.
✅ 회귀계수 초기화
coef = [0.0 for i in range(len(train[0]))]- coef: 학습할 회귀계수 리스트.
- train[0]: 학습 데이터의 첫 번째 샘플. 예) [25, 100]
- len(train[0]): 입력값(X) 과 출력값(Y) 를 포함한 데이터의 길이.
(이 예제에서는 2개) - 예를 들어, coef = [0.0, 0.0] 은 초기값으로 모두 0.0으로 설정합니다.
- coef[0]: 절편 (Intercept)
- coef[1]: 기울기 (Slope)
✅ 학습 반복 (에포크 반복)
for epoch in range(n_epoch): sum_error = 0 # 오차 제곱합 초기화- 전체 학습 데이터를 반복해서 학습하는 과정.
- sum_error: 한 에포크 당 모든 학습 데이터의 오차 제곱합 (SSE, Sum of Squared Errors)
✅ 학습 데이터 사용 (SGD 방식)
for row in train: yhat = predict(row, coef) error = row[-1] - yhat sum_error += error ** 2- yhat: 예측값 (현재 모델의 회귀계수로 예측된 값)
- error: 실제값과 예측값의 차이
- sum_error: 오차를 제곱해서 계속 더함.
✅ 회귀계수 업데이트 (경사하강법)
🔍 절편 업데이트 (Intercept)
coef[0] = coef[0] + l_rate * error- 절편은 입력값 X 의 영향을 받지 않고, 오차의 크기만을 고려하여 업데이트.
- error 값이 크면 더 큰 변화량이 적용됩니다.
🔍 기울기 업데이트 (Slope)
for i in range(len(row) - 1): coef[i+1] = coef[i+1] + l_rate * error * row[i]- 각 입력값(X) 에 대한 기울기를 업데이트합니다.
- 입력값(row[i]) 과 오차(error) 의 곱을 학습률(l_rate) 로 조정하여 기존 기울기에 더합니다.
- 여러 입력값이 있는 경우에도 동일하게 적용됩니다.
✅ 학습 결과 반환 (에포크 종료 후)
return coef, math.sqrt(sum_error / len(train))- coef: 학습된 최종 회귀계수 (coef[0]: 절편, coef[1]: 기울기)
- math.sqrt(sum_error / len(train)): 평균 오차의 제곱근 (RMSE, Root Mean Squared Error)
- RMSE 는 모델의 예측 정확도를 나타내는 지표.
- 값이 낮을수록 모델의 예측 성능이 좋음을 의미합니다.
✅ 5. 학습된 모델로 예측 (predicted())
def predicted(train, test, alpha, beta): predictions = [] for i in test: yhat = alpha + beta * i[0] # 단순 선형 회귀식 적용 predictions.append(yhat) return predictions🔍 코드 설명:
- 학습된 모델(alpha, beta) 을 사용하여 테스트 데이터의 예측값을 계산합니다.
- 예측 값(yhat) 은 선형 회귀 공식에 의해 계산됩니다.
✅ 6. 예측값 평가 (RMSE())
def RMSE(actual, predicted): sum_error = 0.0 for i in range(len(actual)): prediction_error = predicted[i] - actual[i] sum_error += (prediction_error ** 2) mean_error = sum_error / float(len(actual)) return math.sqrt(mean_error)🔍 코드 설명:
- 실제값(actual) 과 예측값(predicted) 사이의 오차를 계산합니다.
- RMSE 값이 작을수록 모델의 예측 정확도가 높은 것을 의미합니다.
✅ 7. 결과 확인
l_rate = 0.0001 n_epoch = 10 # 학습 alpha, beta = coefficients_sgd(train, l_rate, n_epoch)[0][0], \ coefficients_sgd(train, l_rate, n_epoch)[0][1] # 예측 pred = predicted(train, test, alpha, beta) # 실제값 actual = [j[1] for j in test] # 예측 정확도 평가 rmse_value = RMSE(actual, pred) print("예측값:", pred) print("RMSE:", rmse_value)
📊 코드 출력 결과 (예시)
예측값: [210.00907613781257, 186.68812120780515, 256.6509859978274, 130.71782937578732, 196.0165031798081] RMSE: 28.987568769523886- 예측값은 실제값과 비교했을 때 일부 차이가 존재합니다.
- RMSE 값이 약 28.99 이므로 모델의 예측 정확도를 개선할 필요가 있습니다.
🔑 코드가 하는 일 요약
- 학습 데이터(train) 를 사용하여 경사하강법으로 모델 학습.
- 학습된 모델로 테스트 데이터(test) 에 대한 예측 수행.
- 예측값과 실제값을 비교하여 RMSE 계산.
코드를 더 개선하고 싶다면 알려주세요! 또는 코드의 동작 방식에 대해 더 궁금한 게 있나요? 😊
'Why Not SW CAMP 5기 > 수업 기록' 카테고리의 다른 글
[4월 1주차-4/1]🧠 Flask로 나만의 Q&A 게시판 만들기 (SQLAlchemy & Migrate 활용) (1) 2025.04.01 [3월 5주차-3/31]🐍 Flask로 로그인 시스템 만들기 - 기초부터 실습까지! (0) 2025.03.31 [3월 4주차-3/27(3)]통계 용어 정리+ 최소자승법을 이용한 회귀 분석 (OLS) (0) 2025.03.27 [3월 4주차-3/27(1)]Titanic 생존 예측 모델 분석 (의사결정나무 & 로지스틱 회귀) (0) 2025.03.27 [3월 4주차-3/27(2)]다양한 모델 정리 (0) 2025.03.27