

import seaborn as sns
import matplotlib.pyplot as plt
# 예시 데이터 : 팁스
tips = sns.load_dataset("tips")
# 모델 에시 (선형 회귀 모델)
# reg plot은 추세선을 그려주는 기능을 가지고 있습니다.
sns.regplot(x="total_bill", y="tip", data=tips, ci=None, line_kws={"color": "red"})
print()
특히 데이터 간의 관계나 통계적 분포를 보여줄 때 빛을 발함.
Matplotlib이 도화지와 붓이라면, Seaborn은 이미 완성된 멋진 템플릿 세트와 같다
=
"데이터의 흐름을 직선(추세선)으로 표현했더니, 그 직선이 곧 미래를 예측하는 공식(선형회귀모델)이 되었다."는 의미!

# 2중 for문으로 Grid Search
for a in a_values:
for b in b_values:
#예측하기
y_hat = a * X + b # 직선 방정식으로 y 예측 값들 한꺼번에 계산
error = np.sum(np.abs(y - y_hat)) # Error 계산 = 오차의 합
if error < min_error:
min_error = error
best_a, best_b = a, b
# error = np.sum(np.abs(y - y_hat)) # Error = 오차의 합
error = np.mean(np.abs(y - y_hat)) # Error = 오차의 평균 <--- 이 부분이 달라졌어요!
error = np.mean(np.abs(y - y_hat) ** 2)
# 우리가 찾은 회귀선 (빨간색)
x_line = np.linspace(0, 50, 100)
y_line = best_a * x_line + best_b
우리가 회귀 분석을 할 때, 모델이 얼마나 틀렸는지 계산하는 도구가 MSE(평균제곱오차)이고, 그 MSE 값을 가장 작게 만드는(최소화하는) 구체적인 계산 방식이 바로 최소제곱법이다.
단순선형회귀와 다중선형회귀
import numpy as np
import seaborn as sns
# 데이터 불러오기
tips = sns.load_dataset("tips")
X = tips["total_bill"].values.reshape(-1,1) # 세로로 긴 행렬 (n,1) 형태로 변경
Y = tips["tip"].values.reshape(-1,1) # 세로로 긴 행렬인 (n,1) 형태로 변경
# X 행렬에 앞에 [1] 추가
X_b = np.c_[np.ones((X.shape[0], 1)), X] # [[1, x1], [1, x2], [1, x3]....]
# 정규방정식 계산: [b, a] = (X^T·X)^(-1)·X^T·Y
b, a = np.linalg.inv(X_b.T @ X_b) @ (X_b.T) @ (Y)
print("절편 b:", b)
print("기울기 a:", a)

B.T 로 전치행렬을 구하고, np.linalg.inv(A) 로 역행렬을 구할 수 있다.

목적 : 전체 데이터를 확인하지 않고, 최소한의 데이터만 살펴보는 방법으로 a=7일 때 최솟값인 것을 찾기!

X = tips["total_bill"].values # 입력값 (원인)
y = tips["tip"].values # 결과값 (예측 목표)
# 기울기(a)와 절편(b)을 아무 숫자나(랜덤) 넣고 시작합니다.
a = np.random.randn()
b = np.random.randn()
lr: Learning Rate (학습률) - 한 번에 얼마나 크게 움직일지 결정하는 '보폭' epochs : 이 과정을 몇 번 반복할지 for epoch in range(epochs):
y_hat = a * X + b # 1. 현재 가진 a, b로 예측값을 만듦
error = y_hat - y # 2. 실제 정답과 얼마나 차이나는지 오차 계산
# 3. 오차를 줄이기 위해 어느 방향으로 가야 할지(기울기) 계산
grad_a = np.mean(error * X)
grad_b = np.mean(error)
# 4. 계산된 방향으로 조금씩 업데이트 (점프!)
a -= lr * grad_a
b -= lr * grad_b
1)grad_b = np.mean(error) : 절편의 수정 방향
+ : 예측이 높으니 b를 낮춰야 함 2) grad_a = np.mean(error * X) : 기울기의 수정 방향
+라면 기울기를 낮춰야함3) Grad ?


선형 회귀(Linear Regression) 정리
<주어진 데이터>
공부 시간에 따른 시험 합격 여부
2시간 공부 한 A 학생 : 불합격
3시간 공부 한 B 한색 : 불합격
4시간 공부 한 C 학생 : 합격
3시간 공부 한 D 학생 : 불합격
5시간 공부 한 E 학생 : 합격
1시간 공부 한 F 학생 : 불합격

2시간 공부한 학생의 합격 확률 : 11%

import numpy as np
import matplotlib.pyplot as plt
# 시그모이드 함수 정의
def sigmoid(z):
return 1 / (1 + np.exp(-z))
# 학습 완료된 파라미터 결과 (a, b)
a = 1.5
b = -5
# 모델을 이쁘게 그려보기 위한 X 값
X = np.linspace(0, 7, 200)
# 모델 예측 값
y_hat = sigmoid(a * X + b) # z = ax + b
plt.plot(X, y_hat, color="red")
plt.xlabel("Study Time")
plt.ylabel("Pass Probability")
plt.grid(True)
print()
sigmoid(z) 함수: S자 곡선의 마법

학습을 통해 알아야 하는 값 = a b
import numpy as np
import matplotlib.pyplot as plt
# X: 원인 (공부 시간), y: 결과 (0은 불합격, 1은 합격)
X = np.array([1,2,3,4,5,6,2,3,4,5,6,7,1,2,3,4,5,6,7,8,2,3,4,5,6,7,8,9,10])
y = np.array([0,0,0,1,1,1,0,0,1,1,1,1,0,0,0,1,1,1,1,1,0,0,1,1,1,1,1,1,1])
# 시그모이드 함수: 어떤 숫자든 0~1 사이의 '확률'로 바꿔줌
def sigmoid(z):
return 1 / (1 + np.exp(-z))
# 로스 함수 (MSE): 실제 정답(y)과 모델의 예측값(y_hat)이 얼마나 다른지 계산
def get_loss(y, y_hat):
return np.sum((y - y_hat)**2)
sigmoid(z) : 선형 방정식()의 결과값을 0(절대 불합격)과 1(무조건 합격) 사이의 값으로 변환get_loss : 모델이 틀린 정도를 측정. 이 값이 0에 가까울수록 정확한 모델임# a(기울기)는 0~3 사이를 100등분, b(절편)는 -10~10 사이를 100등분해서 준비
a_values = np.linspace(0, 3, 100)
b_values = np.linspace(-10, 10, 100)
best_a, best_b = None, None # 최적의 값을 저장할 변수
min_loss = float("inf") # 최소 오차를 찾기 위해 아주 큰 값으로 초기화
for a in a_values: # 100번 반복
for b in b_values: # 100번 반복 (총 10,000번 실행)
# 1. 현재 a, b 조합으로 예측값(확률) 계산
y_hat = sigmoid(a * X + b)
# 2. 이 조합이 얼마나 틀렸는지(loss) 계산
loss = get_loss(y, y_hat)
# 3. 지금까지 본 것 중 가장 오차가 적다면? "최고의 조합"으로 저장!
if loss < min_loss:
min_loss = loss
best_a, best_b = a, b
y_hat = sigmoid(a * X + b) : 로지스틱 회귀의 핵심!!