선형회귀는 과거 데이터에서 입력(특성)과 숫자로 나타나는 결과(정답) 사이의 직선 관계를 학습해, 새로운 입력의 결과값을 예측하는 지도학습 모델입니다. 예를 들어 자동차 무게로 연비를 예측하거나, 주택 특성으로 가격을 추정하는 데 활용됩니다.
현실 적용 사례
| 부동산 | 아파트·주택 가격 | 면적, 방 개수, 층수, 건축연도, 역과의 거리 | 비슷한 조건의 주택 가격을 추정해 매매·임대 의사결정에 활용 |
| 유통·외식 | 하루 판매량 | 기온, 요일, 공휴일, 프로모션 여부 | 예상 판매량에 맞춰 재료 발주와 재고를 관리 |
| 교통 | 통근 시간 | 출발 시간, 날씨, 강수량, 경로, 교통량 | 비가 오거나 퇴근 시간일 때 소요 시간이 늘어나는 경향을 반영해 예측 |
| 에너지 | 다음 날 전력 수요 | 과거 전력 사용량, 기온, 날씨 예보, 요일 | 전력망 운영자가 발전량과 자원 배분을 계획하는 데 참고 |
| 교육 | 예상 시험 점수 | 학습 시간, 출석률, 이전 시험 점수, 과제 수행률 | 학습 시간과 성적의 대체적 경향을 파악해 학습 상담 자료로 활용 |
| 자동차 | 연비 | 차량 무게, 엔진 배기량, 마력 | 무게가 커질수록 연비가 낮아지는 경향을 직선 모델로 표현 |
가장 이해하기 쉬운 예: 기온과 빵 판매량
어느 베이커리가 과거 데이터를 다음처럼 가지고 있다고 합시다.
| 15°C | 120개 |
| 20°C | 150개 |
| 25°C | 180개 |
| 30°C | 210개 |
선형회귀는 “기온이 1도 오를 때 판매량이 대략 얼마나 늘어나는가”를 나타내는 직선을 찾습니다. 예를 들어 모델이 다음과 같다면,
내일 최고기온이 28°C라면 6×28+30=1986 \times 28 + 30 = 198개를 예측할 수 있습니다. 이 예측값을 바탕으로 반죽량과 재료 발주를 조절하는 것이 실제 활용 방식입니다.
학생 프로젝트로 만들기 좋은 주제
- 학습 시간으로 수능 모의고사 점수 예측하기: 주간 학습 시간, 문제 풀이 수, 이전 점수를 입력으로 사용
- 기온으로 카페 음료 판매량 예측하기: 여름에는 아이스 음료, 겨울에는 따뜻한 음료 판매 경향 확인
- 집 크기로 월세 예측하기: 공공데이터포털의 주택 임대료·전세 자료 활용
- 자전거 대여량 예측하기: 기온, 강수량, 요일, 시간대 데이터를 활용
- 운동 시간으로 체중 변화 예측하기: 개인별 기록을 모아 경향성을 분석
주의할 점
선형회귀는 관계가 대체로 직선적일 때 잘 작동합니다. 따라서 “학습 시간이 늘면 성적도 항상 비례해서 오른다”고 단정할 수는 없고, 과도한 학습으로 피로가 쌓이면 성적이 떨어질 수도 있습니다. 또한 예측값은 어디까지나 데이터 경향에 기반한 추정이므로, 이상치나 누락된 변수의 영향을 함께 검토해야 합니다.
학습 시간으로 수능 모의고사 점수 예측하기 로 만든 파이썬 코드를 보여줘
아래는 학습 시간과 이전 모의고사 점수를 입력으로 받아, 다음 수능 모의고사 점수를 선형회귀로 예측하는 기본 파이썬 코드입니다. 실제 데이터가 없어도 실행되도록 가상 데이터를 생성했고, 실제 데이터가 있으면 CSV 부분만 바꾸면 됩니다.
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, r2_score
# 1. 가상 데이터 만들기
# 실제 사용 시에는 이 부분을 삭제하고
# df = pd.read_csv("모의고사_데이터.csv") 처럼 불러오면 됩니다.
np.random.seed(42)
n = 100
study_hours = np.random.uniform(2, 40, n) # 주간 학습 시간
previous_score = np.random.uniform(30, 90, n) # 이전 모의고사 점수
# 예시 규칙: 학습시간과 이전 점수가 클수록 점수가 높아진다고 가정
score = (
30
+ 0.8 * study_hours
+ 0.35 * previous_score
+ np.random.normal(0, 5, n) # 현실적인 오차
)
# 0~100점 범위로 제한
score = np.clip(score, 0, 100)
df = pd.DataFrame({
"study_hours": study_hours,
"previous_score": previous_score,
"score": score
})
print(df.head())
# 2. 입력 특성과 정답 분리
X = df[["study_hours", "previous_score"]] # 입력: 학습 시간, 이전 점수
y = df["score"] # 정답: 다음 모의고사 점수
# 3. 학습 데이터와 시험 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 4. 선형회귀 모델 학습
model = LinearRegression()
model.fit(X_train, y_train)
# 5. 예측 및 성능 평가
y_pred = model.predict(X_test)
print("학습 시간 계수:", model.coef_[0])
print("이전 점수 계수:", model.coef_[1])
print("절편:", model.intercept_)
print("평균 절대 오차(MAE):", mean_absolute_error(y_test, y_pred))
print("결정계수(R²):", r2_score(y_test, y_pred))
# 6. 새 학생의 점수 예측
new_student = pd.DataFrame({
"study_hours": [25], # 주 25시간 학습
"previous_score": [70] # 이전 모의고사 70점
})
predicted_score = model.predict(new_student)[0]
print(f"예상 다음 모의고사 점수: {predicted_score:.1f}점")
실행 결과 예시
이 코드를 실행하면 대략 다음과 같은 결과가 나옵니다.
- 학습 시간 계수: 약 0.77
- 이전 점수 계수: 약 0.42
- 절편: 약 27.06
- 평균 절대 오차: 약 3.67점
- 결정계수 R2R^2: 약 0.89
- 주 25시간 학습, 이전 점수 70점인 학생의 예상 점수: 약 75.3점
코드 해석
선형회귀 모델은 대략 다음 형태가 됩니다.
즉, 이 가상 데이터에서는 학습 시간이 1시간 늘면 약 0.77점, 이전 모의고사 점수가 1점 높으면 약 0.42점 올라가는 경향을 학습했다는 뜻입니다.
실제 데이터로 바꾸는 방법
엑셀이나 CSV 파일에 다음처럼 데이터를 만들면 됩니다.
| 12 | 55 | 61 |
| 20 | 68 | 74 |
| 30 | 75 | 88 |
| 8 | 40 | 47 |
그다음 코드에서 가상 데이터 생성 부분을 지우고 아래 한 줄로 바꾸면 됩니다.
python
단, 열 이름이 위 표와 동일해야 하며, 실제 데이터에서는 학습 시간만으로 점수를 설명하기 어렵기 때문에 출결, 문제 풀이 수, 과목별 이전 점수 등을 함께 넣으면 더 현실적인 모델이 될 수 있습니다.
이것을 그래프로 그릴 수 있는 코드를 추가해서, 시각적으로 보이게 해줘
아래 코드를 기존 선형회귀 코드 뒤에 추가하면, 학습 시간과 점수의 관계와 실제 점수 대비 예측 점수를 한 화면에서 볼 수 있습니다. 한글이 깨질 수 있으므로 Windows에서는 Malgun Gothic, macOS에서는 AppleGothic 글꼴을 지정했습니다.
import matplotlib.pyplot as plt
# 한글 글꼴 설정
# Windows: Malgun Gothic / macOS: AppleGothic
plt.rcParams["font.family"] = "Malgun Gothic"
plt.rcParams["axes.unicode_minus"] = False
# 1. 학습 시간에 따른 실제 점수와 예측 점수 비교
plt.figure(figsize=(10, 6))
# 실제 점수 산점도
plt.scatter(
X_test["study_hours"],
y_test,
color="steelblue",
alpha=0.7,
label="실제 점수"
)
# 모델의 예측 점수 산점도
plt.scatter(
X_test["study_hours"],
y_pred,
color="orange",
alpha=0.7,
label="예측 점수"
)
# 회귀선 그리기
# 이전 점수는 전체 평균값으로 고정하고, 학습 시간만 변화시킴
study_hours_range = np.linspace(
X["study_hours"].min(),
X["study_hours"].max(),
100
)
previous_score_mean = X["previous_score"].mean()
regression_line = model.predict(
pd.DataFrame({
"study_hours": study_hours_range,
"previous_score": [previous_score_mean] * len(study_hours_range)
})
)
plt.plot(
study_hours_range,
regression_line,
color="red",
linewidth=2,
label="선형회귀 예측선"
)
plt.title("주간 학습 시간과 수능 모의고사 점수의 관계")
plt.xlabel("주간 학습 시간 (시간)")
plt.ylabel("모의고사 점수")
plt.legend()
plt.grid(alpha=0.3)
plt.show()
실제 점수와 예측 점수 비교 그래프
아래 코드는 모델이 얼마나 정확하게 예측했는지 확인하는 그래프입니다. 점들이 빨간 점선에 가까울수록 예측이 정확하다는 의미입니다.
plt.figure(figsize=(7, 7))
plt.scatter(
y_test,
y_pred,
color="seagreen",
alpha=0.7,
label="학생별 예측 결과"
)
# 완벽하게 예측했을 때의 기준선
# 실제 점수 = 예측 점수인 경우
limit_min = min(y_test.min(), y_pred.min())
limit_max = max(y_test.max(), y_pred.max())
plt.plot(
[limit_min, limit_max],
[limit_min, limit_max],
color="red",
linestyle="--",
linewidth=2,
label="완벽한 예측선"
)
plt.title("실제 모의고사 점수와 예측 점수 비교")
plt.xlabel("실제 점수")
plt.ylabel("예측 점수")
plt.legend()
plt.grid(alpha=0.3)
plt.show()
그래프 해석
- 첫 번째 그래프: 파란 점은 실제 점수, 주황 점은 모델이 예측한 점수입니다. 빨간 선은 “이전 점수가 평균일 때, 학습 시간이 늘어날수록 예상 점수가 어떻게 변하는지”를 보여줍니다.
- 두 번째 그래프: 점이 빨간 점선 위에 가까울수록 모델의 예측이 실제 점수와 비슷합니다. 점이 위나 아래로 많이 흩어질수록 예측 오차가 큽니다.
- 이번 가상 데이터에서는 결정계수 R2R^2가 약 0.89로, 모델이 점수 변화의 상당 부분을 설명한다고 볼 수 있습니다.
전체 코드에 추가하는 위치
기존 코드에서 아래 부분 다음에 위 그래프 코드를 붙이면 됩니다.
y_pred = model.predict(X_test)
즉, 모델 학습과 예측이 끝난 뒤에 그래프 코드를 실행하면 됩니다. 실제 데이터 파일을 사용할 때도 동일하게 작동하며, 그래프를 파일로 저장하려면 plt.show() 대신 아래 코드를 사용하면 됩니다.
plt.savefig("모의고사_점수_예측_그래프.png", dpi=300, bbox_inches="tight")
Traceback (most recent call last):
File "C:/Users/user/AppData/Local/Programs/Python/Python314/study_hours.py", line 13, in <module>
X_test["study_hours"],
NameError: name 'X_test' is not defined
이런 오류가 나는데
이 오류는 그래프 코드에서 X_test를 사용하는데, 그 앞에서 train_test_split()으로 X_test를 만드는 코드가 실행되지 않았기 때문입니다. 즉, 그래프 코드만 따로 실행했거나, 데이터 분리 코드보다 먼저 붙여 넣은 경우에 발생합니다.
오류 원인
X_test는 아래 코드가 실행된 뒤에만 존재합니다.
python
따라서 그래프 코드는 반드시 이 코드 뒤에, 그리고 모델 예측 코드인 다음 줄 뒤에 있어야 합니다.
python
해결된 전체 코드
아래 코드를 study_hours.py 파일 전체에 그대로 붙여 넣으면 오류 없이 실행됩니다.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, r2_score
# 한글 글꼴 설정
plt.rcParams["font.family"] = "Malgun Gothic"
plt.rcParams["axes.unicode_minus"] = False
# 1. 가상 데이터 생성
np.random.seed(42)
n = 100
study_hours = np.random.uniform(2, 40, n)
previous_score = np.random.uniform(30, 90, n)
score = (
30
+ 0.8 * study_hours
+ 0.35 * previous_score
+ np.random.normal(0, 5, n)
)
score = np.clip(score, 0, 100)
df = pd.DataFrame({
"study_hours": study_hours,
"previous_score": previous_score,
"score": score
})
# 2. 입력과 정답 분리
X = df[["study_hours", "previous_score"]]
y = df["score"]
# 3. 학습 데이터와 시험 데이터 분리
# 여기서 X_test가 처음 만들어집니다.
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 4. 선형회귀 모델 학습
model = LinearRegression()
model.fit(X_train, y_train)
# 5. 예측
y_pred = model.predict(X_test)
# 6. 성능 확인
print("평균 절대 오차(MAE):", mean_absolute_error(y_test, y_pred))
print("결정계수(R²):", r2_score(y_test, y_pred))
# 7. 학습 시간과 점수 관계 그래프
plt.figure(figsize=(10, 6))
plt.scatter(
X_test["study_hours"],
y_test,
color="steelblue",
alpha=0.7,
label="실제 점수"
)
plt.scatter(
X_test["study_hours"],
y_pred,
color="orange",
alpha=0.7,
label="예측 점수"
)
study_hours_range = np.linspace(
X["study_hours"].min(),
X["study_hours"].max(),
100
)
previous_score_mean = X["previous_score"].mean()
regression_line = model.predict(
pd.DataFrame({
"study_hours": study_hours_range,
"previous_score": [previous_score_mean] * len(study_hours_range)
})
)
plt.plot(
study_hours_range,
regression_line,
color="red",
linewidth=2,
label="선형회귀 예측선"
)
plt.title("주간 학습 시간과 수능 모의고사 점수의 관계")
plt.xlabel("주간 학습 시간 (시간)")
plt.ylabel("모의고사 점수")
plt.legend()
plt.grid(alpha=0.3)
plt.show()
# 8. 실제 점수와 예측 점수 비교 그래프
plt.figure(figsize=(7, 7))
plt.scatter(
y_test,
y_pred,
color="seagreen",
alpha=0.7,
label="학생별 예측 결과"
)
limit_min = min(y_test.min(), y_pred.min())
limit_max = max(y_test.max(), y_pred.max())
plt.plot(
[limit_min, limit_max],
[limit_min, limit_max],
color="red",
linestyle="--",
linewidth=2,
label="완벽한 예측선"
)
plt.title("실제 모의고사 점수와 예측 점수 비교")
plt.xlabel("실제 점수")
plt.ylabel("예측 점수")
plt.legend()
plt.grid(alpha=0.3)
plt.show()
코드 실행 순서
반드시 아래 순서대로 실행되어야 합니다.
- 라이브러리 불러오기
- 데이터 만들기 또는 CSV 불러오기
- X, y 만들기
- train_test_split()으로 X_test, y_test 만들기
- model.fit()으로 학습하기
- model.predict()로 y_pred 만들기
- 그래프 그리기
특히 X_test["study_hours"]를 쓰려면 4번, y_pred를 쓰려면 6번이 먼저 실행되어야 합니다. 위 전체 코드를 그대로 실행하면 두 개의 그래프가 차례로 나타납니다.
1. 가상 데이터 생성
np.random.seed(42)
n = 100
study_hours = np.random.uniform(2, 40, n)
previous_score = np.random.uniform(30, 90, n)
score = (
30 + 0.8 * study_hours
+ 0.35 * previous_score
+ np.random.normal(0, 5, n)
)
score = np.clip(score, 0, 100)
df = pd.DataFrame({
"study_hours": study_hours,
"previous_score": previous_score,
"score": score
})
가상 데이터 생성 부분을 자세하게 설명해줘
이 코드는 실제 학생 데이터가 없을 때, 마치 100명의 학생이 모의고사를 본 것처럼 데이터를 만드는 부분입니다. 모델 학습 연습용 데이터이며, 실제 성적 데이터를 CSV로 불러올 때는 이 부분을 삭제하면 됩니다.
전체 흐름
np.random.seed(42)
n = 100
study_hours = np.random.uniform(2, 40, n)
previous_score = np.random.uniform(30, 90, n)
score = (
30
+ 0.8 * study_hours
+ 0.35 * previous_score
+ np.random.normal(0, 5, n)
)
score = np.clip(score, 0, 100)
df = pd.DataFrame({
"study_hours": study_hours,
"previous_score": previous_score,
"score": score
})
이 코드는 100명의 학생마다 주간 학습 시간, 이전 모의고사 점수, 다음 모의고사 점수를 만들어 표 형태로 저장합니다.
한 줄씩 설명
1. np.random.seed(42)
난수의 시작점을 고정하는 코드입니다. 난수는 무작위 숫자이지만, seed를 정하면 실행할 때마다 같은 무작위 데이터가 만들어집니다.
따라서 지금 코드를 여러 번 실행해도 학습 시간, 이전 점수, 점수 데이터가 같게 유지됩니다. 숫자 42 자체는 특별한 의미가 없고, 아무 정수나 사용해도 됩니다.
2. n = 100
학생 수를 100명으로 정하는 코드입니다. n을 1000으로 바꾸면 학생 1000명의 가상 데이터를 만들 수 있습니다.
3. 학습 시간 만들기
2시간부터 40시간 사이의 실수 형태 무작위 학습 시간 100개를 만듭니다. 예를 들어 16.23시간, 38.13시간처럼 소수점이 있는 값이 나올 수 있습니다.
여기서 uniform(2, 40, n)의 의미는 다음과 같습니다.
| 2 | 최솟값: 최소 2시간 |
| 40 | 최댓값: 최대 40시간 |
| n | 만들 개수: 100개 |
즉, “주간 학습 시간이 2~40시간 사이인 학생 100명”의 데이터를 만든 것입니다.
4. 이전 모의고사 점수 만들기
30점부터 90점 사이의 무작위 이전 모의고사 점수 100개를 만듭니다. 이 값은 학생이 이전에 받았던 점수라고 가정한 것입니다.
예를 들어 어떤 학생은 이전 점수가 31.89점, 다른 학생은 68.18점일 수 있습니다.
5. 다음 모의고사 점수 만들기
이 부분이 가장 중요합니다. 다음 모의고사 점수를 인위적으로 만드는 공식입니다.
각 항의 의미는 다음과 같습니다.
| 30 | 기본 점수. 학습 시간과 이전 점수가 0일 때의 가상 기준값 |
| 0.8 * study_hours | 학습 시간이 1시간 늘면 점수가 약 0.8점 오른다고 가정 |
| 0.35 * previous_score | 이전 점수가 1점 높으면 다음 점수가 약 0.35점 높다고 가정 |
| np.random.normal(0, 5, n) | 현실에서 생기는 우연한 변동, 즉 오차 |
예를 들어 학습 시간이 20시간이고 이전 점수가 70점인 학생은 다음과 같이 계산됩니다.
여기에 오차가 더해져 실제 점수는 80.5점 근처가 됩니다. 오차가 있기 때문에 모든 학생이 정확히 같은 공식대로 점수를 받지는 않습니다.
6. 오차 만들기
평균이 0이고 표준편차가 5인 정규분포 오차 100개를 만듭니다. 쉽게 말해, 실제 시험 점수에는 운, 컨디션, 문제 난이도 같은 우연한 요인이 있으므로 그 변동을 흉내 낸 것입니다.
- 평균 0: 오차가 평균적으로는 점수를 올리거나 내리지 않음
- 표준편차 5: 보통 ±5점 정도의 변동이 생김
- n: 학생 100명 각각에게 다른 오차 부여
그래서 같은 학습 시간과 이전 점수를 가진 학생이라도 점수가 조금씩 다르게 됩니다.
7. 점수 범위 제한하기
점수가 0점 미만이면 0점으로, 100점 초과면 100점으로 바꾸는 코드입니다.
모의고사 점수는 원래 0~100점 사이여야 하기 때문입니다. 오차 때문에 계산 결과가 102점처럼 나올 수도 있는데, np.clip()이 이를 100점으로 제한합니다.
8. 표로 만들기
지금까지 만든 세 개의 리스트를 하나의 표로 합칩니다. pandas의 DataFrame은 엑셀 표처럼 생긴 데이터 구조입니다.
실행 결과는 대략 다음과 같습니다.
| 16.23 | 31.89 | 50.75 |
| 38.13 | 68.18 | 85.53 |
| 29.82 | 48.86 | 72.42 |
왜 이렇게 만드는가
선형회귀 모델은 다음 관계를 학습해야 합니다.
그런데 모델은 이 공식을 미리 알지 못합니다. 모델은 100명의 study_hours, previous_score, score 데이터만 보고, “학습 시간과 이전 점수가 점수에 어떤 영향을 주는지”를 스스로 추정합니다.
따라서 이 가상 데이터는 모델에게 연습 문제와 정답을 제공하는 역할을 합니다. 실제 데이터에서는 이 공식이 정확히 알려져 있지 않지만, 모델이 데이터로부터 비슷한 관계를 찾아내는지 확인할 수 있습니다.
실제 데이터로 바꾸는 방법
실제 학생 데이터를 사용할 때는 위 가상 데이터 생성 코드 전체를 지우고 아래처럼 바꾸면 됩니다.
단, CSV 파일에는 다음처럼 동일한 열 이름이 있어야 합니다.
| 12 | 55 | 61 |
| 20 | 68 | 74 |
| 30 | 75 | 88 |
그러면 이후의 X, y 분리, train_test_split, model.fit() 코드는 그대로 사용할 수 있습니다.
'26년2학기' 카테고리의 다른 글
| 파이썬에서 데이터 분석을 하려면 어떤 패키지가 있는지 알려주고, 예시를 들어 자세하게 설명하는데, 표 형태로 만들어줘 ... perplexity (0) | 2026.10.23 |
|---|---|
| 파이썬에서 데이터 분석을 하려면 어떤 패키지가 있는지 알려주고, 예시를 들어 자세하게 설명하는데, 표 형태로 만들어줘 ... claude (0) | 2026.10.23 |
| Pandas 라이브러리가 설치되어 있지 않아서 ... gemini (0) | 2026.10.22 |
| 딥러닝 이전의 기계학습과 딥러닝의 차이 ... chatgpt (0) | 2026.10.16 |
| 딥러닝 이전의 기계학습과 딥러닝의 차이 ... genspark (0) | 2026.10.16 |