Coding Test/Machine Learning (NeetCode)

Linear Regression (Forward): 선형 회귀 (모델 구현)

hyunkookim 2025. 4. 24. 13:25

Linear Regression (Forward)

 

📘 문제 설명: 선형 회귀 (Linear Regression) 모델 구현

🎯 목표

  • 선형 회귀 모델을 통해 입력 데이터 에 대해 예측값을 구하고,
  • 예측값과 실제 정답 간의 오차(error) 를 계산하는 함수를 구현하는 것입니다.

🔢 주어진 입력

1. get_model_prediction(X, weights) 함수의 입력:

  • X: 입력 데이터셋.
    n×3 행렬 형태이며, 각 행은 3개의 특성(피처)을 가집니다. 예:
X = [
  [x1_1, x1_2, x1_3],  # 첫 번째 샘플
  [x2_1, x2_2, x2_3],  # 두 번째 샘플
  ...
]
  • weights: 모델의 가중치 벡터, 길이 3인 리스트로 구성됨.
    예: [w1, w2, w3]

2. get_error(model_prediction, ground_truth) 함수의 입력:

  • model_prediction: 위 함수에서 예측한 결과값 리스트
  • ground_truth: 정답값 리스트


🔍 요약

함수 이름 기능 설명
get_model_prediction(X, weights) 각 샘플에 대해 선형식을 적용해 예측값을 계산
get_error(model_prediction, ground_truth) 예측값과 실제값 간 평균 제곱 오차(MSE)를 계산

 

class Solution:
    def get_minimizer(self, iterations: int, learning_rate: float, init: int) -> float:
        # 초기값 x 설정 (초기 추정값)
        x = init

        # 설정한 반복 횟수만큼 경사 하강법을 수행
        for _ in range(iterations):
            # 함수 f(x) = x^2의 도함수는 f'(x) = 2x 이므로, 현재 x에서의 기울기(gradient)는 2x
            gradient = 2 * x

            # 경사 하강법 공식: x = x - learning_rate * gradient
            # 기울기 방향의 반대 방향으로 learning_rate 만큼 이동
            x -= learning_rate * gradient

        # 최종적으로 얻어진 x 값을 소수점 5자리까지 반올림하여 반환
        return round(x, 5)

    def get_model_prediction(self, X, weights):
        # 예측 결과를 저장할 리스트 초기화
        predictions = []

        # 각 샘플에 대해 계산
        for sample in X:
            # sample = [x1, x2, x3], weights = [w1, w2, w3] 일 때
            # 예측값 = w1*x1 + w2*x2 + w3*x3 (내적 계산)
            prediction = sum(x * w for x, w in zip(sample, weights))
            predictions.append(prediction)

        # 모든 샘플에 대한 예측값 리스트 반환
        return predictions

    def get_error(self, model_prediction, ground_truth):
        # 샘플 수
        n = len(model_prediction)

        # 오차의 제곱을 모두 더함
        total_squared_error = 0
        for pred, actual in zip(model_prediction, ground_truth):
            total_squared_error += (pred - actual) ** 2

        # 평균 제곱 오차 (Mean Squared Error)를 반환
        return total_squared_error / n

 

코드에 상세한 한글 주석을 추가했습니다. 주요 포인트는 다음과 같습니다:

  • get_model_prediction: 각 샘플에 대해 가중치와 입력의 내적(dot product)을 계산하여 예측값 리스트를 반환합니다.
  • get_error: 예측값과 실제값 사이의 평균 제곱 오차(Mean Squared Error, MSE)를 계산합니다.
import numpy as np
from numpy.typing import NDArray


# Helpful functions:
# https://numpy.org/doc/stable/reference/generated/numpy.matmul.html
# https://numpy.org/doc/stable/reference/generated/numpy.mean.html
# https://numpy.org/doc/stable/reference/generated/numpy.square.html

class Solution:
    
    def get_model_prediction(self, X: NDArray[np.float64], weights: NDArray[np.float64]) -> NDArray[np.float64]:
        # X is an Nx3 NumPy array [[x1_1, x1_2, x1_3], [x2_1, x2_2, x2_3], ... [xN_1, xN_2, xN_3] ]
        # weights is a 3x1 NumPy array [w1, w2, w4]T
        # HINT: np.matmul() will be useful
        # return np.round(your_answer, 5)


    def get_error(self, model_prediction: NDArray[np.float64], ground_truth: NDArray[np.float64]) -> float:
        # model_prediction is an Nx1 NumPy array
        # ground_truth is an Nx1 NumPy array
        # HINT: np.mean(), np.square() will be useful
        # return round(your_answer, 5)
import numpy as np
from numpy.typing import NDArray

class Solution:
    
    def get_model_prediction(self, X: NDArray[np.float64], weights: NDArray[np.float64]) -> NDArray[np.float64]:
        # X는 (N, 3) 형태의 2차원 배열, 각 행은 하나의 샘플이고 3개의 특성값을 가짐
        # weights는 (3,) 또는 (3,1) 형태의 1차원 또는 2차원 가중치 벡터
        # np.matmul(X, weights): X와 weights의 행렬 곱 => (N,) 또는 (N,1) 벡터로 예측값 생성
        prediction = np.matmul(X, weights)
        
        # 결과를 소수점 다섯째 자리까지 반올림하여 반환
        return np.round(prediction, 5)

    def get_error(self, model_prediction: NDArray[np.float64], ground_truth: NDArray[np.float64]) -> float:
        # 평균 제곱 오차(MSE): mean((예측값 - 실제값)^2)
        squared_error = np.square(model_prediction - ground_truth)  # 제곱 오차 계산
        mean_squared_error = np.mean(squared_error)  # 평균 계산
        
        # 결과를 소수점 다섯째 자리까지 반올림하여 반환
        return round(mean_squared_error, 5)
import numpy as np
from numpy.typing import NDArray


# Helpful functions:
# https://numpy.org/doc/stable/reference/generated/numpy.matmul.html
# https://numpy.org/doc/stable/reference/generated/numpy.mean.html
# https://numpy.org/doc/stable/reference/generated/numpy.square.html

class Solution:

    def get_model_prediction(self, X: NDArray[np.float64], weights: NDArray[np.float64]) -> NDArray[np.float64]:
        # X is an Nx3 NumPy array [[x1_1, x1_2, x1_3], [x2_1, x2_2, x2_3], ... [xN_1, xN_2, xN_3] ]
        # weights is a 3x1 NumPy array [w1, w2, w4]T
        # HINT: np.matmul() will be useful
        # return np.round(your_answer, 5)

        preds = []
        for sample in X:
            # 각 sample (1x3 벡터)와 weights (3x1 벡터)의 내적을 수동으로 계산
            # zip을 통해 (x1, w1), (x2, w2), (x3, w3) 식으로 묶어서 곱한 후 모두 더함
            preds.append(sum([x * w for x, w in zip(sample, weights)]))

        # 예측값 리스트를 넘파이 배열로 변환 후, 소수점 다섯째 자리까지 반올림하여 반환
        return np.round(np.array(preds), 5)

    def get_error(self, model_prediction: NDArray[np.float64], ground_truth: NDArray[np.float64]) -> float:
        # model_prediction is an Nx1 NumPy array
        # ground_truth is an Nx1 NumPy array
        # HINT: np.mean(), np.square() will be useful
        # return round(your_answer, 5)

        n = len(model_prediction)
        mse = 0

        # flatten: (n, 1) → (n,)로 평탄화하여 각 값이 float이 되도록 처리
        # 그렇지 않으면 zip에서 각 원소가 배열로 묶여 연산 시 오류 발생 가능
        for gt, pred in zip(ground_truth.flatten(), model_prediction.flatten()):
            # 정답값(gt)과 예측값(pred)의 차이를 제곱하여 누적합
            mse += (gt - pred) ** 2

        # 평균 제곱 오차(MSE)를 계산하고, 소수점 다섯째 자리까지 반올림하여 반환
        return round(mse / n, 5)