사이킷런 설치

1. 머신러닝의 기본 개념 및 원리
- 머신러닝의 정의: 모델 내부의 **가중치(Weight)**들이 실수값을 가지며, 데이터를 통해 이 값을 최적화하는 과정이다.
- 입력 데이터: 일반적으로 데이터(Feature)와 정답(Label)의 쌍으로 구성된다.
- 추론(Inference): 학습된 모델을 통해 새로운 데이터에 대한 예상값을 도출하는 과정이다.
2. 학습 방식에 따른 분류
머신러닝은 데이터의 성격과 학습 목표에 따라 세 가지로 분류된다.
지도 학습 (Supervised Learning)
- 특징: 데이터와 함께 명확한 **정답표(Label)**를 제공한다.
- 목표: 입력값에 대한 정확한 정답을 예측하는 것이다.
비지도 학습 (Unsupervised Learning)
- 특징: 정답 없이 데이터 자체만 보고 학습한다.
- 핵심 기술: 비슷한 데이터끼리 묶는 **클러스터링(군집화)**이 대표적이다.
강화 학습 (Reinforcement Learning)
- 특징: 보상(Reward)과 패널티를 통해 학습한다. 아무것도 모르는 상태에서 확률적인 선택을 반복하며 최적의 경로를 찾는다.
- 비유: 영화 '엣지 오브 투모로우', 벽돌깨기 게임.
- 사례: 구글 딥마인드의 알파고(AlphaGo). 확률 기반의 의사결정이 중요하다.
3. 인공지능의 수준 분류
- 약인공지능 (Weak A.I.): 특정 영역에서만 지능을 발휘하는 AI (현재 대부분의 AI).
- 강인공지능 (Strong A.I.): 인간 수준의 범용적인 지능을 가진 AI.
4. 실무 및 주요 사례
- 알파고(AlphaGo): 딥마인드에서 개발했으며, 수많은 기보 데이터를 학습하여 바둑의 확률적 승률을 계산한다.
- 머신러닝 실무의 핵심:
- 이미 다양한 모델이 시중에 공개되어 있다.
- 따라서 양질의 데이터 확보, 데이터 전처리, 상황에 맞는 적재적소의 알고리즘 선택 능력이 더 중요하다.
5. 머신러닝의 수학적 본질
머신러닝은 결국 오차를 줄여나가는 반복적인 최적화 과정이다.
- 오차(Error) 계산: 실제값과 예측값의 차이를 구한다.
- 반복 학습: 오차가 0이 될 때까지 파라미터(Weight)를 수정하며 반복한다.
- 점화식의 관점: 이전 단계의 파라미터를 바탕으로 다음 단계의 파라미터를 갱신하는 과정은 수학의 점화식 원리와 유사하다.

6. 회귀(Regression) vs 분류(Classification)
지도 학습은 출력값(정답)의 형태에 따라 크게 두 가지로 나뉜다.
| 구분 | 회귀 (Regression) | 분류 (Classification) |
| 출력값 형태 | 연속적인 실수(Value) | 이산적인 카테고리(Label) |
| 예시 | 주택 가격 예측, 키 예측 | 개와 고양이 구분, 스팸 메일 판별 |
| 특징 | 데이터 간의 상관관계를 파악함 | 데이터를 특정 기준(결정 경계)으로 나눔 |
- 분류의 수치화: AI는 '개', '고양이'라는 글자 자체를 이해하지 못하므로, 학습 시에는 이를 숫자(예: 개=0, 고양이=1)로 변환하는 과정이 필요하다.
7. 선형 회귀(Linear Regression)의 원리
데이터를 가장 잘 설명하는 직선을 찾는 과정이다.
주요 변수 및 용어
- 독립변수 (X): 원인이 되는 데이터. 주택 면적, 부모의 키 등 (특성, Feature, Property).
- 종속변수 (Y): 결과가 되는 데이터. 주택 가격, 자녀의 키 등.
- 피어슨 상관계수: 두 변수가 양의 관계인지 음의 관계인지, 혹은 관계가 없는지 나타내는 척도다.

수학적 모델 (가설)
단순한 직선 방정식에서 시작하여 다변수로 확장된다.
- 일변수 회귀 (단순 선형 회귀): 특성이 1개일 때

- 다변수 회귀 (다중 선형 회귀): 특성이 여러 개일 때

- 벡터 표기 (행렬 연산):
- W: 가중치(Weight), 기울기, 계수(Coefficient).
- b: 편향(Bias), 절편(Intercept), 때로는 노이즈를 포함하는 개념.
- W의 T: 가중치 행렬의 전치(Transpose).

8. 오차와 차원
오차(Residual, 잔차)
실제 정답과 모델이 예측한 값 사이의 거리다. 머신러닝의 목적은 이 잔차의 합을 최소화하는 최적의 W와 b를 찾는 것이다.
고차원의 세계
- 2차원: 선(Line)으로 데이터를 설명한다.
- 3차원: 평면(Plane)으로 데이터를 설명한다.
- 4차원 이상: 인간의 눈으로 시각화할 수 없는 영역이며, 이를 **하이퍼플레인(Hyperplane, 초평면)**이라고 부른다.
코드
공부시간에 따른 시험성적 예측
1. 데이터의 차원 (Shape)
- scikit-learn에서 독립변수 X는 반드시 2차원 행렬 형태여야 한다. [163] 처럼 대괄호를 두 번 쓴 이유는 행(데이터 개수)과 열(특성 개수)을 맞추기 위함이다.
2. 가중치(W)와 편향(b)
- regr.coef_: 입력값 X가 결과값 y에 주는 영향력을 의미한다. 위 예시에서는 "1시간 공부할 때마다 오르는 점수"가 된다.
- regr.intercept_: X가 0일 때의 기본값이다. "공부를 아예 안 했을 때의 기본 점수"로 해석할 수 있다.
3. 결정계수
- 이 점수는 0에서 1 사이의 값을 가진다.
- 1에 가까울수록 "선형 회귀 직선이 데이터를 완벽하게 설명한다"는 뜻이며, 필기에서 언급한 **오차(Residual)**가 매우 적다는 것을 의미한다.

- W (Coefficient): 기울기
- b (Intercept): 절편/편향
- 머신러닝의 목적은 수많은 X, y 쌍을 보고 최적의 W, b를 찾아내어, 새로운 X가 들어왔을 때 정확한 y를 **추론(Inference)**하는 것이다.
import numpy as np
from sklearn import linear_model
# 1. 모델 객체 생성
regr = linear_model.LinearRegression()
# 2. 데이터 준비 (X는 반드시 2차원 배열 형태여야 함)
# [공부 시간(시간)]
X = [[2], [4], [6], [8], [10]]
# [시험 점수(점)]
y = [40, 55, 70, 92, 98]
# 3. 모델 학습 (데이터 피팅)
regr.fit(X, y)
# 4. 결과 추출
coef = regr.coef_ # 가중치 (W, 기울기)
intercept = regr.intercept_ # 편향 (b, 절편)
score = regr.score(X, y) # 결정계수 (R-squared)
# 5. 결과 출력
print(f"회귀 방정식: y = {coef[0]:.2f} * X + {intercept:.2f}")
print(f"모델 설명력(R²): {score:.2%}")
# 6. 새로운 데이터로 추론(Prediction)
new_study_time = [[7]]
predicted_score = regr.predict(new_study_time)
print(f"7시간 공부했을 때 예상 점수: {predicted_score[0]:.1f}점")
데이터 시각화
- 파란색 점과 빨간색 선 사이의 수직 거리가 바로 **오차(잔차)**다.
- 선형 회귀는 이 거리들의 제곱 합을 최소화하는 직선을 찾는 알고리즘이다.
import matplotlib.pyplot as plt
# 실제 수집된 데이터를 파란색(blue) 다이아몬드(D) 모양의 점으로 표시
plt.scatter(X, y, color='blue', marker='D')
y_pred = regr.predict(X)
plt.plot(X, y_pred, 'r:') # 모델이 예측한 값(y_pred)을 빨간색(r) 점선(:)으로 잇는다.
분석 결과 해석
- 회귀 방정식: y = 7.65X + 25.10
- 기울기가 7.65이므로 공부 시간이 1단위 증가할 때마다 점수는 약 7.65점 상승한다고 해석할 수 있다.
- 절편이 25.10이므로 공부를 전혀 하지 않아도 기본적으로 얻는 점수(Bias)가 약 25점임을 의미한다.
- 관계 점수(Score): 0.9803 (98.03%)
- 데이터가 직선에 매우 가깝게 분포하고 있으며, 이 모델이 현재 데이터를 매우 높은 정확도로 설명하고 있다는 증거다.
새로운 공부 시간으로 시험점수 예측
1. 모델을 활용한 추론 (Inference)
학습된 가중치(W)와 편향(b)을 사용하여 본 적 없는 새로운 데이터에 대한 결과값을 예측하는 단계다.
- 예측 과정: 모델에 167이라는 값을 입력하면, 내부적으로 y = Wx + b 연산을 수행한다.
- 외삽(Extrapolation)의 위험: 현재 예시에서 공부 시간 167은 학습 데이터 범위(2~10시간)를 심하게 벗어나 있다. 이렇게 데이터 범위를 크게 벗어난 예측은 현실적인 제약(예: 하루는 24시간, 점수 만점은 100점 등)을 반영하지 못하므로 주의가 필요하다.
2. 결정계수 (R^2 Score, Coefficient of Determination)
모델이 실제 데이터를 얼마나 잘 설명하는지 나타내는 지표다.
- 계산 방법: regr.score(X, y)와 sklearn.metrics의 r2_score(y, y_pred)는 동일한 수치를 반환한다.
- 수식적 의미: 전체 분산 중 모델이 설명하는 분산의 비율을 의미한다.


- 점수 해석:
- 1.0: 모델이 데이터를 완벽하게 설명함.
- 0.5: 데이터 변동성의 절반 정도를 설명함.
- 0.0: 데이터를 평균값으로 예측하는 것과 차이가 없음.
new_study_time = [[167]]
result = regr.predict(new_study_time)
print(f'공부 시간이 {new_study_time}시간 이므로 시험점수는 {result.round(1)}점으로 추정됨')
from sklearn.metrics import r2_score
print(f"데이터와 선형 회귀 직선의 r square 점수: {r2_score(y, y_pred):.3}")
| 단계 | 주요 작업 | 코드 예시 |
| 1. 데이터 준비 | 독립변수($X$)와 종속변수($y$) 설정 | X = [[...]], y = [...] |
| 2. 모델 생성 | 알고리즘 객체 선언 | regr = LinearRegression() |
| 3. 모델 학습 | 데이터를 모델에 피팅 | regr.fit(X, y) |
| 4. 모델 평가 | $R^2$ 등으로 성능 검증 | regr.score(X, y) |
| 5. 결과 시각화 | 산포도 및 회귀선 출력 | plt.scatter(), plt.plot() |
| 6. 예측(추론) | 새로운 데이터 입력 및 결과 도출 | regr.predict(new_data) |
다중 선형 회귀 코드: 성적 예측
import numpy as np
from sklearn import linear_model
# 모델 객체 생성
regr = linear_model.LinearRegression()
# 데이터 설정: [공부 시간(시간), 하루 커피 섭취량(잔)]
X = [
[10, 0], [8, 1], [9, 0], [7, 2], [12, 1], [5, 3],
[11, 0], [6, 2], [8, 4], [4, 1], [10, 2], [7, 0]
]
# 정답 데이터: [시험 점수]
y = [95, 88, 92, 80, 98, 65, 96, 75, 82, 60, 91, 85]
# 학습 (Fit)
regr.fit(X, y)
# 결과 분석
print(f'각 특성의 가중치(W1, W2): {regr.coef_}')
print(f'기본 점수(절편, b): {regr.intercept_:.2f}')
print(f'모델의 설명력(Score): {regr.score(X, y):.4f}')
# 새로운 데이터 추론: [13시간 공부하고 커피 안 마신 사람, 3시간 공부하고 커피 5잔 마신 사람]
new_students = [[13, 0], [3, 5]]
predictions = regr.predict(new_students)
print(f'예상 점수들: {predictions.round(1)}')

수동 가설 설정 및 시각화
import matplotlib.pyplot as plt
import numpy as np
# 실제 관측 데이터 (예: 광고비 대비 매출)
x_data = np.array([1, 2, 3, 4, 5])
y_data = np.array([3.1, 5.2, 8.9, 11.5, 15.1])
# 1. 실제 데이터 산포도
plt.scatter(x_data, y_data, color='green', marker='s', label='Actual Data')
# 2. 내가 직접 세운 가설 1: y = 3x (단순 3배 비례할 것이다)
plt.plot(x_data, 3.0 * x_data, 'r--', label='Hypothesis: y=3x')
# 3. 내가 직접 세운 가설 2: y = 2.5x + 1 (조금 더 완만할 것이다)
plt.plot(x_data, 2.5 * x_data + 1, 'b-', label='Hypothesis: y=2.5x+1')
plt.xlabel('Advertising Cost')
plt.ylabel('Sales')
plt.legend()
plt.grid(True)
plt.show()
평균 제곱 오차(MSE, Mean Squared Error)
1. 평균 제곱 오차(MSE)의 의미
머신러닝에서 모델의 성능을 평가할 때 사용하는 대표적인 **손실 함수(Loss Function)**다.
- 오차(Error): 실제값(y)과 예측값(y 햇)의 차이다.
- 제곱하는 이유: 1. 오차가 음수일 때 합산하면 오차가 상쇄되는 문제를 방지한다. 2. 오차가 클수록 더 큰 페널티를 부여한다(제곱이 되기 때문).
- 평균: 전체 데이터 개수로 나누어 데이터 규모와 상관없이 평균적인 오차 수준을 파악한다.

2. 비슷한 지표: 평균 절대 오차(MAE)
MSE와 비슷하지만, 제곱 대신 절댓값을 사용하는 **평균 절대 오차(MAE, Mean Absolute Error)**가 있다.
- 특징: 오차의 크기를 그대로 반영한다. MSE보다 이상치(Outlier)에 덜 민감하다.

import numpy as np
from sklearn.metrics import mean_absolute_error, mean_squared_error
# 실제값과 예측값
y = np.array([1.2, 2.4, 2.5, 4.6, 5.4])
y_hat = np.array([1, 2, 3, 4, 5])
# 1. MAE (Mean Absolute Error) 수동 계산
mae_manual = np.abs(y_hat - y).mean()
# 2. MSE (Mean Squared Error) 수동 계산
diff = (y_hat - y) ** 2
mse_manual = diff.sum() / len(y)
# 3. RMSE (Root Mean Squared Error) 수동 계산
# MSE에 루트를 씌워 실제 데이터와 단위를 맞춤
rmse_manual = np.sqrt(((y_hat - y) ** 2).mean())
print(f"MAE (평균 절대 오차): {mae_manual:.3f}")
print(f"MSE (평균 제곱 오차): {mse_manual:.3f}")
print(f"RMSE (제곱근 평균 제곱 오차): {rmse_manual:.3f}")
# 4. 사이킷런 라이브러리 활용
mae_sklearn = mean_absolute_error(y, y_hat)
mse_sklearn = mean_squared_error(y, y_hat)
rmse_sklearn = np.sqrt(mse_sklearn)
print(f"MAE (평균 절대 오차): {mae_sklearn:.3f}")
print(f"MSE (평균 제곱 오차): {mse_sklearn:.3f}")
print(f"RMSE (제곱근 평균 제곱 오차): {rmse_sklearn:.3f}")
| 지표 | 수식 특징 | 장점 | 단점 |
| MSE | 오차 제곱의 평균 | 미분이 쉬워 최적화에 유리함 | 큰 오차에 지나치게 민감함 |
| MAE | 오차 절댓값의 평균 | 직관적이며 이상치에 강함 | 모델 학습 시 미분이 까다로움 |
| RMSE | MSE에 루트를 씌움 | 실제 정답과 단위가 같아 해석이 쉬움 | MSE의 민감도를 그대로 가짐 |
경사 하강법을 이용해 단순 선형 회귀 모델의 가중치와 편향 구하기
from sklearn import linear_model # 사이킷런의 선형 모델 모듈을 가져옴
import numpy as np # 배열 계산을 위해 넘파이를 가져옴
# X: 커피 잔 수, y: 총 결제 금액 (단위: 천원)
# 학습에 사용할 데이터 정의 (X: 원인/입력, y: 결과/타겟)
X = np.array([1, 2, 3, 4, 5])
y = np.array([8, 13, 18, 23, 28])
w, b = 0, 0
learning_rate, epoch = 0.01, 2000
n = len(X)
for i in range(epoch):
y_pred = w * X + b
error = y_pred - y
# 경사하강법 업데이트 (평균값 기준)
w = w - learning_rate * (error * X).mean()
b = b - learning_rate * error.mean()
print(f'예상 결과: y = 5x + 3 (1잔당 5천원 + 배달비 3천원)')
print(f'학습 결과: w = {w.round(2)}, b = {b.round(2)}')
from sklearn import linear_model
import numpy as np
X = np.array([1, 2, 3, 4, 5])
y = np.array([8, 13, 18, 23, 28])
# 선형 회귀 모델 객체 생성
regr = linear_model.LinearRegression()
# 사이킷런의 fit() 함수는 X 데이터로 2차원 배열을 요구함
# 기존 1차원 [1, 2, 3...]을 [[1], [2], [3]...] 형태의 2차원으로 변환
X = X[:, np.newaxis]
# 준비된 데이터를 모델에 넣어서 학습(훈련) 진행
regr.fit(X, y)
# 학습 결과 확인
# coef_: 가중치(기울기 w), intercept_: 편향(절편 b)을 의미함
print(f'w = {regr.coef_.round(2)}, b = {regr.intercept_.round(2)}')
그래프로 시각화
import matplotlib.pyplot as plt
import numpy as np
X = np.array([1, 2, 3, 4, 5])
y = np.array([8, 13, 18, 23, 28])
plt.scatter(X, y, color='blue', marker='D')
y_pred = regr.coef_[0] * X + regr.intercept_
# 공식을 직접 쓸 필요 없이 모델에게 예측을 시킴
# y_pred = regr.predict(X[:, np.newaxis])
plt.plot(X, y_pred, 'r:')

학습률이 작은 경우
학습률(learning_rate)은 경사 하강법에서 **"한 번에 얼마나 큰 걸음을 내디딜 것인가"**를 결정.
- 현재 설정된 0.00001은 걸음 폭이 너무 좁아서, 1,000번(epoch)을 반복해서 걸어도 목적지(최적의 w, b)까지 도달하기에 턱없이 부족함.
- 비유하자면, 서울에서 부산까지 가야 하는데 한 번에 1cm씩만 이동하는 것과 같음. 1,000걸음을 걸어도 여전히 서울 근처에 머물러 있는 상태
import numpy as np
import matplotlib.pyplot as plt
# 1. 데이터 정의
X = np.array([1, 2, 3, 4, 5])
y = np.array([8, 13, 18, 23, 28])
# 2. 모델 파라미터 초기화
w, b = 0, 0
# 학습률이 0.00001로 매우 작음: 가중치 업데이트가 아주 조금씩 일어남
learning_rate, epoch = 0.00001, 1000
n = len(X)
# 3. 경사 하강법 루프
for i in range(epoch):
y_pred = w * X + b # 현재 모델의 예측값 계산
error = y_pred - y # 실제값과의 차이(오차) 계산
# 오차를 바탕으로 기울기(w)와 절편(b) 업데이트
# 학습률이 작아서 1000번을 돌아도 w와 b가 목표값(5, 3)에 도달하지 못함
w = w - learning_rate * (error * X).sum()
b = b - learning_rate * error.sum()
# 4. 결과 출력
print(f'학습 완료 후 결과: w = {w.round(2)}, b = {b.round(2)}')
# --- 그래프 시각화 부분 ---
# 실제 데이터 점 (파란색 다이아몬드)
plt.scatter(X, y, color='blue', marker='D', label='Actual Data')
# 학습된 w, b를 이용한 예측 직선 (빨간색 점선)
y_final_pred = w * X + b
plt.plot(X, y_final_pred, 'r:', label='Model Prediction')
# 그래프 설정
plt.xlabel('X')
plt.ylabel('y')
plt.title(f'Learning Rate: {learning_rate} (Small)')
plt.legend()
plt.show()
학습률이 큰 경우
학습률이 너무 큰 경우(learning_rate = 1.0)는 걸음 폭이 너무 커서 최적의 지점을 지나쳐버리고, 오차가 점점 커지다가 결국 값이 폭발(발산)하게됨
import numpy as np
import matplotlib.pyplot as plt
# 1. 데이터 정의
X = np.array([1, 2, 3, 4, 5])
y = np.array([8, 13, 18, 23, 28])
# 2. 모델 파라미터 초기화
w, b = 0, 0
# 학습률이 1.0으로 매우 큼: 한 번의 업데이트가 데이터의 범위를 완전히 벗어날 정도로 큼
learning_rate, epoch = 1.0, 1000
n = len(X)
# 3. 경사 하강법 루프
for i in range(epoch):
y_pred = w * X + b # 현재 예측값
error = y_pred - y # 오차
# 가중치 업데이트
# 학습률이 너무 커서 w와 b가 최소 오차 지점을 향해 가는 게 아니라,
# 반대 방향으로 튕겨 나가며 값이 무한히 커짐 (Over-shooting/Divergence)
w = w - learning_rate * (error * X).sum()
b = b - learning_rate * error.sum()
# 값이 너무 커져서 에러가 날 수 있으므로 중간에 멈추는 출력 (선택 사항)
if np.isinf(w) or np.isnan(w):
print(f"{i+1}번째 에폭에서 값이 폭발했습니다.")
break
# 4. 결과 출력 (보통 nan 혹은 inf가 출력됨)
print(f'w = {w}, b = {b}')
# --- 시각화 코드 ---
# 데이터 점 시각화
plt.scatter(X, y, color='blue', marker='D', label='Actual Data')
# 초기 상태 (w=0, b=0)
plt.plot(X, 0*X + 0, 'g--', label='Initial (w=0, b=0)')
# 학습률이 너무 커서 엉뚱한 곳으로 가버린 예측 선 (값이 폭발하기 직전의 상태 가정)
# 실제 1.0 학습률로는 단 1회만 돌아도 선이 화면 밖으로 사라짐
if not np.isnan(w) and not np.isinf(w):
plt.plot(X, w * X + b, 'r:', label='Diverged Line')
else:
print("값이 너무 커서 그래프에 표시할 수 없습니다.")
plt.xlabel('X')
plt.ylabel('y')
plt.title(f'Learning Rate: {learning_rate} (Too Large)')
plt.legend()
plt.show()
'머신러닝' 카테고리의 다른 글
| 머신러닝 - 분류, 군집, SVM (0) | 2026.01.12 |
|---|---|
| 머신러닝 - 다중회귀 (0) | 2026.01.11 |
| PANDAS (0) | 2026.01.08 |
| SEABORN (0) | 2026.01.07 |
| MATPLOTLIB (0) | 2026.01.07 |