[ ✅ 상관 분석]
1. 이론
- 두 변수의 선형 관계 확인
- 1에 가까울 수록 선형 관계가 강함
- 수치형 데이터에 대해서만 분석 가능
2. 예시 문제
- ~의 상관관계를 분석하였을 떄 가장 낮은 상관계수는?
- 날씨에 따른 기온과 자전거 대여의 상관계수 변수 변화를 알아보고자 한다. "weather"변수의 값에 따른 상관계수 차이의 절대값은 얼마인가?
3. import 메서드
import pandas as pd
from scipy.stats import pearsonr
from scipy.stats import spearmanr
from scipy.stats import kendalltau
4. 사용 함수
1) pandas - corr()
import pandas as pd
#수치형 데이터에 대해서만 분석
df.corr(numeric_only = True)
#일부에 대해서만 상관관계 분석
df[["casual", "registered", "count"]].corr()
# 상관계수 지정
df[["casual", "registered", "count"]].corr(method = "spearman")
2) 피어슨 상관계수
- stat, p = pearsonr(df["casual"], df["registered"])
5. 대표 예제
-날씨에 따른 기온과 자전거 대여의 상관계수 변수 변화를 알아보고자 한다. "weather"변수의 값에 따른 상관계수 차이의 절대값은 얼마인가?
- 풀이
: is_sunny값에 따른 == is_sunny별로(group by한다)
df = pd.read_csv("bike.csv")
df.head(2)
#수치형으로 변경
df["is_sunny"] = (df["weather"] == 1) + 0
#sunny인지 아닌지 계절 별로 확인
pd.crosstab(df["is_sunny"], df["weather"])
#is_sunny(weather) 변수 값에 따른 기온 & 자전거 대여의 상관 계수 변수
# is_sunny값에 따른 == is_sunny별로(group by한다)
df_corr = df.groupby("is_sunny")[["temp", "casual"]]).corr()
#0.4463610705397161 - 0.471052716733539
round(abs(df_corr.iloc[1,0] - df_corr.iloc[3, 0]), 3) #정답 : 0.025
tempcasualis_sunny
0 | temp | 1.000000 | 0.446361 |
casual | 0.446361 | 1.000000 | |
1 | temp | 1.000000 | 0.471053 |
casual | 0.471053 | 1.000000 |
[ ✅ 비계층 군집 분석]
1. 이론
- K-means
- MinMaxScalar, StandardScalar
- 수치형 데이터에 해당
- fit()후에는 pd.DataFrame으로 변경해야 보기가 편함
2. 예시 문제
- 군집 분석을 실시하는 경우 군집 개수가 가장 큰 군집의 Insulin 평균은 얼마인가?
- k-means 군집 분석을 실시하는 경우 군집 개수가 가장 큰 군집의 나이 평균은?
- k-means 군집 분석을 실시하고, 군집의 중심점 간 유클리드 거리가 가장 가까운 그룹 간의 거리는?
3. import 메서드
import pandas as pd from sklearn.cluster import KMeans from sklearn.preprocessing import MinMaxScaler from sklearn.preprocessing import StandardScaler |
4. 사용 함수
1) sklearn.preprocessing - MinMaxScalar()
- minmax.data_max_, minmax .data_min_
- fit(X) -> pd.DataFrame() -> transform() 행렬 전환
- minmax결과가 numpyArray이기 때문
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from slearn.preprocessing import StandardScaler
#학습 시키기(단, 수치형 데이터에서만 해당)
nor_minmax = MinMaxScaler().fit(df.iloc[: , :-1]) #맨 마지막 범주형 데이터 제거
#data max, data min값이 변수로 생김. DataFrame으로 바꾸기
pd.DataFrame([nor_minmax.data_max_, nor_minmax.data_min_],
columns = df.columns)
# 결과 변환
nor_minmax.transform(df.iloc[:, :-1])
2) sklearn.preprocessing - StandardScaler()
- 표준화를 실시하는 sklearn의 함수
- fit() : 모델을 만들고 transform() 함수로 변환을 실시
3) sklearn.cluster - KMeans()
- K, M이 대문자
- KMeans() : n_clusters, max_iter, random_state 인자 설정
- KMeans() : fit()에 데이터를 할당하여 학습 진행
- kmeans.cluster_centers_와 kmeans.labels_ : 군집 중심과 각 행의 군집 번호 확인 가능
from sklearn.cluster import KMeans
import numpy as np
# 예제 데이터 생성
X = np.array([[1, 2], [1, 4], [1, 0], [4, 2], [4, 4], [4, 0]])
# KMeans 모델 생성 및 학습
kmeans = KMeans(n_clusters=2, random_state=42).fit(X)
# labels_ 확인
print(kmeans.labels_) # 각 데이터가 속한 클러스터 번호 출력
출력 예시: [1 1 1 0 0 0]
→ 데이터 3개는 클러스터 1, 나머지 3개는 클러스터 0에 속함.
print(kmeans.cluster_centers_) # 클러스터 중심 좌표 출력
출력 예시:
[[4. 2.]
[1. 2.]]
→ 첫 번째 클러스터의 중심은 [4, 2], 두 번째 클러스터의 중심은 [1, 2].
5. 대표 예제
-BMI가 0이 아닌 사람 데이터를 대상으로 k-means 군집 분석을 실시하고, 군집의 중심점 간 유클리드 거리가 가장 가까운 그룹 간의 거리는?
(군집은 3개, seed는 123개)
import pandas as pd
from sklearn.cluster import KMeans
# 1. BMI가 0이 아닌 데이터만 뽑기
# 이 땐, []으로 감싼다
df = pd.read_csv("diabetes.csv")
df_sub = [df.loc["BMI"] != 0, ]
df_sub.head(2)
# 2. K-Means 모델 생성 후 학습
model = KMeans(n_clusters = 3, random_state = 123)
model.fit(df_sub)
# 3. cluster_centers_ 값을 Pandas DataFrame으로 변환
# columns=df_sub.columns: 원본 데이터 df_sub의 컬럼명을 유지하여 가독성을 높임.
df_centers = pd.DataFrame(model.cluster_centers_, columns =df_sub.columns)
# 4. fransform을 쓰면서 전치 행렬 (행/열 바꾸기)
df_centers = df_centers.transpose()
# 5. 유클리드 거리 구하기
# sum((좌표 1 - 좌표 2) ** 2) ** 0.5
print(sum((df_centers.iloc[:, 0] - df_centers.iloc[:, 1]) ** 2) ** 0.5)
print(sum((df_centers.iloc[:, 1] - df_centers.iloc[:, 2]) ** 2) ** 0.5)
print(sum((df_centers.iloc[:, 0] - df_centers.iloc[:, 2]) ** 2) ** 0.5)
+ 추가 설명
📌 KMeans 클러스터 중심(df_centers) 해석
- -KMeans를 사용하여 3개의 클러스터(n_clusters=3)로 데이터를 분류한 후, 각 클러스터의 중심 좌표(cluster_centers_)를 출력한 결과를 보면, 각 클러스터별 평균적인 특성값이 다르게 나타난다.
- 즉, 각 군집(클러스터)의 대표값(중심점)이 각 특성(Feature)별로 다르게 설정된 것이다.
1️⃣ 군집 중심 좌표는 왜 다를까?
- KMeans는 데이터를 n개의 군집으로 나누고, 각 군집의 "평균 좌표"를 중심점으로 설정하기 때문.
- 즉, 각 군집의 중심좌표는 해당 군집에 속한 데이터들의 평균값을 나타낸다.
그러므로 같은 군집에 속한 데이터라 해도, 중심점은 그 데이터들의 평균적인 위치가 된다.
1️⃣ 군집 중심 좌표는 왜 다를까?
- - KMeans는 데이터를 n개의 군집으로 나누고, 각 군집의 "평균 좌표"를 중심점으로 설정하기 때문.
- - 즉, 각 군집의 중심좌표는 해당 군집에 속한 데이터들의 평균값을 나타낸다.
- 그러므로 같은 군집에 속한 데이터라 해도, 중심점은 그 데이터들의 **평균적인 위치**가 된다.
2️⃣ 각 군집(Cluster) 해석하기¶
클러스터PregnanciesGlucoseBloodPressureSkinThicknessInsulinBMIDiabetesPedigreeFunctionAgeOutcome
0번 군집 | 4.03 | 158.4 | 72.0 | 32.26 | 441.3 | 35.1 | 0.57 | 34.76 | 0.58 |
1번 군집 | 3.97 | 114.2 | 68.6 | 15.26 | 14.7 | 31.4 | 0.43 | 33.81 | 0.30 |
2번 군집 | 3.54 | 129.4 | 71.5 | 30.34 | 159.4 | - | - | - | - |
3️⃣ 군집별 특징 분석
- 군집 0 (고혈당 그룹일 가능성 높음)
- Glucose(혈당) 값이 158.4로 매우 높음.
- Insulin(인슐린 수치) 도 441.3으로 가장 높음.
- Outcome(당뇨 여부) 가 0.58로 다른 군집보다 높음 → 당뇨 환자가 많을 가능성.
- BMI(체질량지수)도 35.1로 높음 → 비만율 높음 예상.
- 군집 1 (정상 혈당 그룹)
- Glucose(혈당) 값이 114.2로 상대적으로 낮음.
- Insulin(인슐린 수치) 값도 14.7로 매우 낮음.
- Outcome(당뇨 여부) 가 0.30 → 정상 혈당 그룹일 가능성.
- 군집 2 (중간 그룹)
- Glucose(혈당) 값이 129.4로 중간 수준.
- BloodPressure(혈압) 과 SkinThickness(피부두께) 도 중간 값.
- Insulin(인슐린 수치) 도 159.4로 군집 1보다는 높지만, 군집 0보다는 낮음.
✅ 결론
- 각 군집별 중심 좌표는 해당 군집에 속한 데이터들의 평균값을 나타냄.
- 같은 군집에 속한 데이터들이 있더라도 중심 좌표는 해당 군집의 대표적인 평균적인 위치.
- KMeans는 개별 데이터를 하나의 점으로 이동시키는 것이 아니라, 유사한 데이터들의 중심을 찾는 방식.
👉 따라서 군집이 같아도 각 클러스터의 중심 좌표는 다를 수 있음! 👉 군집별로 혈당 수치, 인슐린 값 등에서 차이가 나타나므로, 특정 특성을 가진 그룹을 구별하는 데 활용 가능.
[ ✅ 단순 회귀 분석]
1. 이론
📌 단순 회귀 분석(Simple Linear Regression) 개념
- 단순 회귀 분석은 하나의 독립 변수(X)와 종속 변수(Y) 사이의 관계를 선형적으로 설명하는 모델이다.
- 즉, "X가 증가하면 Y는 어떻게 변하는가?" 를 분석하는 방법이다.
1️⃣ 수학적 표현
- 단순 회귀 모델은 다음과 같은 일차 방정식 형태를 가진다.
- [ Y = \beta_0 + \beta_1 X + \epsilon ]
- ( Y ): 종속 변수(결과, 예측하고 싶은 값)
- ( X ): 독립 변수(설명 변수)
- ( \beta_0 ): 절편 (intercept, X가 0일 때 Y값)
- ( \beta_1 ): 기울기 (slope, X가 1 증가할 때 Y가 변하는 값)
- ( \epsilon ): 오차항 (error term, 실제 값과 예측 값의 차이)
📌 ols() 함수란?
- ols()는 Ordinary Least Squares(최소자승법) 을 사용하여 회귀 모델을 생성하는 함수이다.
- ols()는 statsmodels 라이브러리에서 제공하며, 선형 회귀 분석을 수행할 수 있음.
- 최소자승법(OLS, Ordinary Least Squares)을 사용하여 X와 Y 사이의 최적의 직선을 찾음.
📌 ols() 사용 예제
```python
import pandas as pd
import statsmodels.api as sm
# 예제 데이터 생성
data = {'X': [1, 2, 3, 4, 5], 'Y': [2, 4, 5, 4, 5]}
df = pd.DataFrame(data)
# 독립 변수(X)와 종속 변수(Y) 정의
X = df['X']
Y = df['Y']
# 절편 추가 (OLS에서는 X에 절편 추가가 필요함)
X = sm.add_constant(X)
# OLS 회귀 모델 생성 및 학습
model = sm.OLS(Y, X).fit()
# 회귀 분석 결과 출력
print(model.summary())
📌 LinearRegression() (회귀 모델 생성)
- LinearRegression()은 Scikit-Learn에서 제공하는 선형 회귀 모델을 생성하는 클래스
- 데이터를 학습하여 최적의 회귀 직선을 찾고 예측값을 반환한다.
🔹 주요 메서드
.fit(X, y) | 주어진 데이터를 이용하여 회귀 모델 학습 |
.predict(X) | 학습된 모델을 사용하여 X의 예측값 반환 |
.coef_ | 회귀 계수(기울기) 확인 |
.intercept_ | 절편(Intercept) 값 확인 |
2️⃣ mean_absolute_error(y_true, y_pred) (평균 절대 오차, MAE)
- mean_absolute_error()는 평균 절대 오차 (MAE, Mean Absolute Error) 를 계산하는 함수이다.
- 실제 값과 예측 값 사이의 평균적인 절대 차이를 계산하여 오차 정도를 평가한다.
🔹 수식
[ MAE = \frac{1}{n} \sum_{i=1}^{n} |y_i - \hat{y}_i| ]
- ( y_i ): 실제 값
- ( \hat{y}_i ): 예측 값
- ( n ): 샘플 개수
🔹 특징
- MAE 값이 작을수록 예측 정확도가 높음.
- 모든 오차를 절대값으로 변환하므로, 양수/음수 관계없이 오차의 크기만 고려.
3️⃣ mean_squared_error(y_true, y_pred) (평균 제곱 오차, MSE)
- mean_squared_error()는 평균 제곱 오차 (MSE, Mean Squared Error) 를 계산하는 함수이다.
- 실제 값과 예측 값 사이의 차이를 제곱하여 평균을 계산한다.
🔹 수식
[ MSE = \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 ]
- ( y_i ): 실제 값
- ( \hat{y}_i ): 예측 값
- ( n ): 샘플 개수
🔹 특징
- 오차를 제곱하므로 큰 오차에 더 큰 패널티를 부여.
- 큰 값의 오차를 중요하게 고려할 때 사용.
✅ MAE vs MSE 차이점
MAE (평균 절대 오차) | 오차의 절대값 평균 | 해석이 직관적, 이상치(Outlier)에 덜 민감 |
MSE (평균 제곱 오차) | 오차의 제곱 평균 | 이상치에 민감, 큰 오차를 더 크게 반영 |
✅ 주요 메서드 요약
LinearRegression().fit(X, y) | 선형 회귀 모델 학습 | 회귀 계수 및 예측 수행 |
LinearRegression().predict(X) | 예측값 반환 | 새로운 데이터에 대한 예측 |
mean_absolute_error(y_true, y_pred) | 평균 절대 오차(MAE) 계산 | 오차 크기를 직관적으로 평가 |
mean_squared_error(y_true, y_pred) | 평균 제곱 오차(MSE) 계산 | 큰 오차를 중요하게 평가 |
👉 MAE는 직관적이고 해석이 쉬운 반면, MSE는 큰 오차에 민감하여 신뢰도가 더 높음.
👉 LinearRegression()은 기본적인 회귀 모델을 생성하는 데 필수적인 함수.
📌 formula = "registered ~ temp"(y ~ X)의 의미
🔹 1. formula란?
- formula = "registered ~ temp"는 회귀 분석에서 사용할 독립 변수(설명 변수)와 종속 변수(반응 변수)의 관계를 정의하는 방식이다.
- 이때 "~ (틸다)" 기호는 "우항(오른쪽 변수)으로 좌항(왼쪽 변수)을 설명한다"는 의미를 가진다.
🔹 2. "registered ~ temp"의 의미
- registered → 종속 변수(반응 변수, Y)
→ 예측하고 싶은 값 (등록된 사용자 수) - temp → 독립 변수(설명 변수, X)
→ 예측을 위한 입력 값 (온도) - 즉, "온도(temp)가 등록된 사용자 수(registered)에 어떤 영향을 미치는가?" 를 분석하는 단순 회귀 모델을 만든다는 의미이다.
🔹 3. formula 확장 가능
- formula는 단순 회귀뿐만 아니라 다중 회귀 분석(여러 개의 독립 변수) 도 가능하다.
- ✅ 다중 회귀 예제
- python formula = "registered ~ temp + humidity + windspeed"
2. 예시 문제
-종속 변수를 registered, 독립 변수를 temp로 했을 때 결정계수는? (statesmodel 함수 활용)
- 종속 변수를 casual, 독립 변수를 atemp로 했을 떄 RMSE는?
- 종속 변수를 casual, 독립 변수를 atemp로 했을 때 여름과 겨울의 RMSE 차이는?
3. import 메서드
import pandas as pd from statsmodels.formula.api import ols from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_absolute_error from sklearn.metrics import mean_squared_error |
4. 사용 함수
1) statsmodels.formula.api / ols
- ols(formula = "SW ~ PL", data = df).fit()
- 컬럼명에 특수문자가 있으면 에러 반환
import pandas as pd
from statsmodels.formult.api import ols
df = pd.read_csv("iris.csv")
df.head(2)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
# ols 학습하기 전 컬럼면 변경
df.columns = ["SL", "SW", "PL", "PW", "species"]
df.head(2)
SL SW PL PW species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
# ols로 학습
model = ols(formula = "SL ~ SW", data = df).fit()
model.summary()

✅ OLS Regression Results 해석
R-squared | 모델 설명력 | 0.927 (92.7% 설명 가능) |
Prob (F-statistic) | 선형 관계 유의성 | 4.68e-86 (귀무가설 기각) |
절편 (Intercept) | PW=0일 때 PL 값 | 1.0836 |
PW 계수 | PW 1 증가 시 PL 증가량 | 2.2299 |
p-value (PW) | PW가 유의미한지 검정 | 0.000 (유의미한 변수) |
📌 R-squared 값과 Prob(F-statistic)
- R-squared = 0.927 → 모델이 PL(꽃잎 길이)의 92.7%를 설명함.
- Prob(F-statistic) = 4.68e-86 → 귀무가설 기각, 선형 관계가 유의미함.
📌 귀무가설 기각 및 대립가설 채택
- 귀무가설 (H₀): PW(꽃잎 너비)는 PL(꽃잎 길이)에 영향을 주지 않는다.
- 대립가설 (H₁): PW(꽃잎 너비)는 PL(꽃잎 길이)에 영향을 준다.
- p-value가 0.000이므로, 귀무가설 기각 → PW는 PL에 유의미한 영향을 줌.
✅ 결론
✔ PW(꽃잎 너비)는 PL(꽃잎 길이)에 강한 선형적 영향을 줌.
✔ 선형 회귀 모델이 92.7%의 설명력을 가지며, 유의미한 관계를 가짐.
# 즉, y = 2.2299 * x + 1.0836 과 동일하다
# R square ~ P -value, P값을 보는것이 중요
model.predict(df.iloc[:3, ])
0 1.529546
1 1.529546
2 1.529546
dtype: float64
df["pred"] = model.predict(df)
df.head()
SL SW PL PW species pred
0 5.1 3.5 1.4 0.2 setosa 1.529546
1 4.9 3.0 1.4 0.2 setosa 1.529546
2 4.7 3.2 1.3 0.2 setosa 1.529546
3 4.6 3.1 1.5 0.2 setosa 1.529546
4 5.0 3.6 1.4 0.2 setosa 1.529546
2) sklearn.linear_model import LinearRegression
LinearRegression().fit(X, y) | 선형 회귀 모델 학습 | 회귀 계수 및 예측 수행 |
LinearRegression().predict(X) | 예측값 반환 | 새로운 데이터에 대한 예측 |
.fit(X, y) | 주어진 데이터를 이용하여 회귀 모델 학습 |
.predict(X) | 학습된 모델을 사용하여 X의 예측값 반환 |
.coef_ | 회귀 계수(기울기) 확인 |
.intercept_ | 절편(Intercept) 값 확인 |
- model = LinearRegression().fit(X = df["PL"] , y = df["PW"]) 으로 하면 error 남! 2차원 array로 만들어야 한다.
- model = LinearRegression().fit(X = df[["PL"]] , y = df[["PW"]])
from sklearn.linear_model import LinearRegression
# 회귀 모델 학습
model = LinearRegression().fit(X = df[["PL"]] #[]를 하나 더 씌움
, y = df[["PW"]])
# 계수(기울기) 구하기
model.coef_
array([[0.41575542]])
# 절편 구하기
model.intercept_
array([-0.36307552])
# 새 데이터에 대해 X의 예측값 반환
model.predict(df[["PL"]])
3) mean_absolute_error(y_true, y_pred) (평균 절대 오차, MAE) mean_squared_error(y_true, y_pred) (평균 제곱 오차, MSE)
- 각 값들은 pred_data에 대해서 구해야 함
- 따라서, 반드시 train_data와 test_data를 분리해야 함!
- y_true는 test_data, y_pred는 model.predict(test_data)로 구한 예측값
종속 변수를 registered, 독립 변수를 temp로 했을 때 결정계수는?
import pandas as pd
from sklearn.model_selection import train_test_split
from sleran.metrics import mean_absolute_error
from slearn.metrics import mean_squared_error
df_train, df_test = train_test_split(df, train_size = 0.7, random_state = 123)
df_train.head(2) #학습 데이터 분리
#registered를 종속, temp를 독립으로 train
# "R-squared" 를 찾기
model = ols(formula = "registered ~ temp", data = df_train).fit()
model.summary()
------------------------------------------
종속 변수를 casual, 독립 변수를 atemp로 했을 떄 RMSE는?
#학습 데이터 분리
df_train, df_test = train_test_split(df, train_size = 0.7, random_state = 123)
df_train.head(2)
# ols로 모델 학습
model = ols(formula = "casual ~ atemp", data = df_train).fit()
# df_test 데이터를 기반으로 예측 값 생성
pred = model.predict(df_test)
pred.head(2)
# RMSE = MSE의 루트
# MSE는 예측 model에 대해서 구해야 한다!
mean_squared_error(y_pred = pred,
y_true = df_test["casual"]) ** 0.5
5. 대표 예제
- 종속 변수를 casual, 독립 변수를 atemp로 했을 때 여름과 겨울의 RMSE 차이는?
import pandas as pd
from statsmodels.formula.api import ols
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import mean_squared_error
df = pd.read_csv("bike.csv")
df.head(2)
# 1. 여름 데이터, 겨울 데이터만 추출
df_s2 = df.loc[df["season"] == 2, ]
df_s4 = df.loc[df["season"] == 4, ]
df_s2_train, df_s2_test = train_test_split(df_s2,
train_size = 0.7,
random_state = 123)
df_s4_train, df_s4_test = train_test_split(df_s4,
train_size = 0.7,
random_state = 123)
# 2. 모델 학습 및 예측값 추출
model_s2 = ols(formula = "casual ~ atemp", data = df_s2_train).fit()
model_s4 = ols(formula = "casual ~ atemp", data = df_s4_train).fit()
pred_s2 = model_s2.predict(df_s2_test)
pred_s4 = model_s4.predict(df_s4_test)
# 3. RMSE 값 추출
RMSE_s2 = mean_squared_error(y_pred = pred_s2, y_true = df_s2_test["casual"]) ** 0.5
RMSE_s4 = mean_squared_error(y_pred = pred_s4, y_true = df_s4_test["casual"]) ** 0.5
✅ [다중 회귀 분석]
1. 이론
🔹 1. 다중 공선성이란?
- 다중 공선성(Multicollinearity)은 독립 변수(X)들 사이의 상관관계가 높아, 회귀 모델이 특정 변수의 영향을 제대로 학습하지 못하는 문제를 의미한다.
이 문제가 발생하면 회귀 계수의 신뢰성이 낮아지고, 모델 해석이 어려워진다.
🔹 2. 다중 공선성 문제의 영향
- 회귀 계수(coef_)의 값이 비현실적으로 크거나 부호가 바뀌는 경우 발생
- 특정 독립 변수(p-value)가 유의미하지 않게 나올 가능성이 높음
- 새로운 데이터에 대한 예측 성능이 저하됨 (과적합 발생 가능)
🔹 3. 다중 공선성 확인 방법: 분산 팽창 계수(VIF)
- 다중 공선성 문제를 확인하는 대표적인 지표가 VIF (Variance Inflation Factor, 분산 팽창 계수) 이다.
VIF 값이 클수록 다중 공선성이 높다고 판단한다. VIF 값이 10 이상이면 다중 공선성 문제를 해결해야 한다.
🔹 4. patsy.dmatrices()를 이용한 데이터 변환
- patsy.dmatrices() 함수는 회귀 분석을 위한 디자인 행렬(Design Matrices) 을 생성한다.
회귀 모델에서 독립 변수(X)와 종속 변수(Y)를 쉽게 분리할 수 있다. - return_type 인자에 "dataframe"으로 설정 시 후처리 용이
🔹 5. variance_inflation_factor()를 이용한 VIF 계산
- statsmodels.stats.outliers_influence.variance_inflation_factor() 함수를 사용하여 각 독립 변수의 VIF 값을 계산할 수 있다.
- 분산 팽창 계수 연산을 위해 반복문 또는 list comprehension을 사용
🔹 6. 다중 공선성 해결 방법
- VIF 값이 높은 변수 제거
- 상관관계가 높은 변수 중 하나를 제거
- 변수 결합 또는 차원 축소
- 주성분 분석(PCA) 등 사용하여 변수를 줄이기
- 정규화(Regularization) 사용
- 릿지 회귀(Ridge Regression) 또는 라쏘 회귀(Lasso Regression) 활용
✅ 요약
다중 공선성 | 독립 변수(X)들 간의 높은 상관관계로 인해 회귀 분석이 왜곡되는 문제 |
VIF (분산 팽창 계수) | 다중 공선성을 측정하는 지표 (10 이상이면 문제 있음) |
patsy.dmatrices() | 독립 변수(X)와 종속 변수(Y)를 디자인 행렬로 변환 |
variance_inflation_factor() | VIF를 계산하여 다중 공선성 여부 확인 |
👉 VIF가 10 이상인 변수가 있다면, 다중 공선성 해결을 고려해야 한다!
2. 예시 문제
- Price를 종속 변수로 하고 나머지 수치형 변수를 독립변수로 했을 때 다중 공선성의 문제가 있다고 판단되는 변수의 개수는?
- price를 종속변수로 하고 carat과 depth를 독립변수로 하여 생성한 선형 회귀 모델을 사용하여 알아본 carat이 1이고 depth가 60, table이 55인 다이아몬드의 가격은?
- price를 종속 변수로 하고 carat, color, depth를 독립변수로 하여 생성한 선형 회귀 모델을 사용하여 알아본 carat이 1이고 depth가 50, color가 E인 다이아몬드의 가격은?
3. import 메서드
import pandas as pd from patsy import dmatrices from statsmodels.stats.outliers_influence import variance_inflation_factor as vif |
4. 사용 함수
1) patsy import dmatrices
- 디자인 행렬 생성
- y, X = dmatrices(formula, data, return_type)
- return_type = "dataframe"으로 지정 가능
- `dmatrices()`를 사용하면 자동으로 Intercept(절편) 항이 추가되는데, 이는 기본적으로 회귀 모델이 절편을 포함하도록 설계되었기 때문이다.
formula = "casual ~ " + " + ".join(df_sub.columns[:-1]) y, X = dmatrices(formula, data = df_sub, return_type = "dataframe") |
2) statsmodels.stats.outliers_influence import variance_inflation_factor as vif
y, X = dmatrices("price ~ " + " + ".join(df_sub.columns[1:]), data = df_sub, return_type = "dataframe") df_vif = pd.DataFrame() df_vif["vars"] = X.columns df_vif["VIF"] = [vif(X.values, i) for i in range(X.shape[1])] df_vif |
vars VIF
0 | Intercept | 4821.696350 |
1 | carat | 21.602712 |
2 | depth | 1.496590 |
3 | table | 1.143225 |
4 | x | 56.187704 |
5 | y | 20.454295 |
6 | z | 23.530049 |
- intercept를 제외하고, 4개가 다중공선성 문제와 관련이 있다.
5. 대표 예제
- price를 종속 변수로 하고 carat, color, depth를 독립변수로 하여 생성한 선형 회귀 모델을 사용하여 알아본 carat이 1이고 depth가 50, color가 E인 다이아몬드의 가격은? 단, 특정 범주형 변수로부터 만들어진 가변수 중 첫번째 가변수는 제외 후 분석
* 풀이
1단계 | price, carat, color, depth만 선택 |
2단계 | color를 더미 변수로 변환 (첫 번째 범주 D 제외) |
3단계 | ols()를 사용해 선형 회귀 모델 적합 |
4단계 | carat=1, depth=50, color=E인 데이터 생성 |
5단계 | 모델을 사용해 다이아몬드 가격 예측 |
import pandas as pd
from patsy import dmatrices
from statsmodels.stats.outliers_influence import variance_inflation_factor as vif
df = pd.read_csv("diamonds.csv")
df.head(2)
# 1. 필요한 feature만 생성
df_sub = df.loc[:, ["price", "carat", "color", "depth"]]
df_sub.head(2)
# 2. color를 get_dummies로 생성
#color가 범주형이라 dummy변수로 만들기, drop_first를 안하면 다중공선성 문제가 생김 ->dummy 변수로 생성
# 원래 color는 D, E, F, G, H, I, J의 7가지 범주가 있었음.
#첫번째 가변수를 제외하라고 했으므로, drop_first = True 실행
df_dum = pd.get_dummies(df_sub,
columns = ["color"],
drop_first= True)
df_dum.head(2)
price carat depth color_E color_F color_G color_H color_I color_J
0 326 0.23 61.5 1 0 0 0 0 0
1 326 0.21 59.8 1 0 0 0 0 0
# 3.OLS로 회귀분석 진행
# prices를 제외한 나머지 columns를 독립 변수로 모두 포함시키기 위해 .join실행
# ols(formula = , data = ).fit()
model = ols(formula = "prices ~" + " + ".join(df_dum.columns[1:]),
data = df_dum).fit()
model.summary()
# 4. carat=1, depth=50, color=E인 데이터 생성
# 독립변수는 carat ~ color_J까지 총 8개. 8개의 변수를 독립 변수로 하는 데이터를 새로 만들어야 한다!
# df_dum에서 샘플 하나를 가져와 예측 데이터의 틀을 만듦
df_test = df_dum.iloc[[0], :].copy()
# 예측할 값으로 업데이트
df_test["carat"] = 1
df_test["depth"] = 50
# 더미 변수 초기화 (color_E만 1, 나머지는 0)
for col in ["color_E", "color_F", "color_G", "color_H", "color_I", "color_J"]:
df_test[col] = 0
df_test["color_E"] = 1
# 생성된 예측 데이터 확인
df_test
price carat depth color_E color_F color_G color_H color_I color_J
0 326 1 50 1 0 0 0 0 0
# 5. 생성한 데이터로 가격 예측
model.predict(df_test)
round(model.predict(df_test)) # 6702.0
✅ [로지스틱ㅡ 회귀 분석]
1. 이론
🔹 1. 로지스틱 회귀 분석이란?
- 로지스틱 회귀 분석(Logistic Regression)은 종속 변수가 범주형(0 또는 1)일 때 사용하는 분류 모델이다.
데이터가 특정 클래스에 속할 확률을 예측하며, 출력 값이 0~1 사이의 확률 값으로 나타난다.
🔹 2. 로지스틱 회귀 분석의 특징
특징 설명
확률 기반 예측 | 예측 결과가 0~1 사이의 확률 값으로 출력됨 |
시그모이드 함수 사용 | 선형 회귀와 달리 시그모이드(sigmoid) 함수를 적용하여 값을 변환 |
이진 분류 문제 해결 | 종속 변수가 두 개의 범주(예: 성공/실패, 질병 유무)인 경우 적합 |
선형 회귀와의 차이 | 선형 회귀는 연속적인 숫자 예측, 로지스틱 회귀는 범주형 예측 |
다중 분류 확장 가능 | 소프트맥스(Softmax)를 사용하여 다중 분류 문제에도 적용 가능 |
🔹 3. 주요 함수 설명
함수 설명 인자
statsmodels.Logit() | statsmodels의 로지스틱 회귀 모델 | (y, X) |
sklearn.linear_model.LogisticRegression() | sklearn의 로지스틱 회귀 모델 | .fit(X, y) |
sklearn.metrics.roc_auc_score() | AUC(곡선 아래 면적) 계산 | (y_true, y_score) |
sklearn.metrics.accuracy_score() | 정확도(Accuracy) 계산 | (y_true, y_pred) |
sklearn.metrics.f1_score() | F1 점수 계산 (정밀도 & 재현율의 조화 평균) | (y_true, y_pred) |
sklearn.metrics.precision_score() | 정밀도(Precision) 계산 | (y_true, y_pred) |
sklearn.metrics.recall_score() | 재현율(Recall) 계산 | (y_true, y_pred) |
📌 로지스틱 회귀 분석 수식
🔹 정확도(Accuracy) 계산 공식

🔹 F1-score 계산 공식

🔹 정밀도(Precision) 계산 공식

🔹 재현율(Recall) 계산 공식

## 🔹 **예제 코드**
```python
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score, roc_auc_score
# 예제 데이터 생성
data = {
'temp': [30, 32, 34, 36, 38, 40, 42, 44, 46, 48],
'humidity': [60, 62, 64, 66, 68, 70, 72, 74, 76, 78],
'registered': [0, 0, 1, 1, 1, 1, 1, 1, 1, 1]
}
df = pd.DataFrame(data)
# 데이터 분할
X = df[['temp', 'humidity']]
y = df['registered']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 로지스틱 회귀 모델 학습
model = LogisticRegression()
model.fit(X_train, y_train)
# 예측 수행
y_pred = model.predict(X_test)
y_score = model.predict_proba(X_test)[:, 1] # 예측 확률값
# 평가 지표 계산
acc = accuracy_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
auc = roc_auc_score(y_test, y_score)
# 결과 출력
print(f"Accuracy: {acc}")
print(f"F1 Score: {f1}")
print(f"Precision: {precision}")
print(f"Recall: {recall}")
print(f"AUC: {auc}")
2. 예시 문제
-독립 변수를 혈압, 혈당, BMI, 인슐린으로 하고 종속변수를 당뇨 여부로 로지스틱 회귀분석을 할 경우 분류 정확도는 얼마인가?
-독립 변수를 혈당, BMI, 나이로 하고 종속변수를 당뇨 여부로 로지스틱 회귀분석을 할 경우 나이의 승산비는 얼마인가?
-독립 변수를 혈당, BMI, 나이로 하고 종속변수를 당뇨 여부로 로지스틱 회귀분석을 할 경우 모델의 AUC는 얼마인가?
3. import 메서드
import pandas as pd from statsmodels import Logit from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score, roc_auc_score |
4. 사용 함수
1) Logit() : statsmodel 사용
- model = Logit(endog = 종속 변수 , exog =독립 변수).fit()
- Logit().fit() 결과 : pvalues와 params
🔹 1. pvalues란? (p-값, 유의확률)
- pvalues는 각 독립 변수(X)가 종속 변수(Y)에 대해 통계적으로 유의미한 영향을 미치는지를 평가하는 지표이다.
- p-값이 0.05 이하이면 해당 변수가 종속 변수에 유의미한 영향을 미친다고 판단한다.
pvalue 값해석
p < 0.05 | 변수가 종속 변수에 유의미한 영향을 미침 (통계적으로 의미 있음) |
p ≥ 0.05 | 변수가 종속 변수에 유의미한 영향을 미치지 않음 (해석 시 주의 필요) |
즉, p-값이 0.05 이상이면 해당 변수는 종속 변수 예측에 크게 기여하지 않을 가능성이 높다.
🔹 2. params란? (회귀 계수, 모델 파라미터)
- params는 각 독립 변수의 회귀 계수(β 계수)를 나타냄.
- 회귀 계수는 독립 변수가 종속 변수(Y)에 미치는 영향을 설명한다.
✅ 회귀 계수 해석
temp | 1.25 | temp가 1 증가할 때, log(odds)가 1.25만큼 증가 |
humidity | -0.75 | humidity가 1 증가할 때, log(odds)가 0.75만큼 감소 |
- 즉, params 값이 양수이면 해당 변수가 증가할수록 Y=1일 확률이 증가하며,
음수이면 해당 변수가 증가할수록 Y=1일 확률이 감소한다.
import pandas as pd
import numpy as np
from statsmodels.api import Logit
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
df = pd.read_csv("iris.csv")
df.head(2)
df["is_setosa"] = (df["Species"] == "setosa") + 0
#첫번째, 두번쨰 변수만 (Sepal.Length, Sepal.Width)사용해서 setosa인지를 학습
model = Logit(endog = df["is_setosa"],
exog = df.iloc[:, :2]).fit()
model
# 예측 값 생성(데이터 3개만, feature는 SL, SW 2개)
pred = model.predict(df.iloc[:3, :2])
pred
0 0.999477
1 0.923824
2 0.998678
dtype: float64
# 우리는 분류 모델을 쓰는 것이기 떄문에, 0.5를 기준으로 분류하기
(pred > 0.5) + 0
2) sklearn.linear_model import LogisticRegression
- 인자로 "X" 로 안쓰면 error 남!
- 결과값 : coef_(기울기) , intercept_(절편)
- model.predict의 결과값은 numArray이기 때문에 dataFrame형식이 아님 -> loc을 못씀
🔹 1. predict_proba( X_test )
- 설명: 각 클래스(0 또는 1)에 대한 확률값(Probability)을 반환하는 함수.
- 출력값: [P(Y=0), P(Y=1)] 형식의 배열을 반환.
- 사용 목적: ROC AUC, 확률 기반의 모델 평가를 할 때 사용.
- y_proba = model.predict_proba(X_test)
- [[0.87 0.13]
[0.30 0.70]
[0.45 0.55]
[0.05 0.95]
[0.60 0.40]] - 첫 번째 값(0.87)은 클래스 0일 확률, 두 번째 값(0.13)은 클래스 1일 확률.
- 예측 확률을 기반으로 특정 임계값(threshold, 기본 0.5) 이상이면 1, 아니면 0으로 예측
🔹 2. predict(X_test)
- 설명: 학습된 모델을 사용하여 최종 예측 결과(0 또는 1)를 반환하는 함수.
- 출력값: 0 또는 1만 반환(임계값 0.5 기준).
- 사용 목적: 최종 분류(classification) 결과를 얻을 때 사용.
y_pred = model.predict(X_test)[0 1 1 1 0]
- predict_proba()에서 확률값이 0.5 이상이면 1, 미만이면 0으로 변환하여 반환.
#대문자 X주의!
model = LogisticRegression(random_state = 123)
# 학습
model.fit(X = df.iloc[:, :2],
y = df["is_setosa"])
# 계수와 절편 알아내기
model.coef_
model.intercept_
# 주의 사항 !!!!! numpyArray이기 때문에 dataFrame이 아님 -> loc 못씀!!!!
pred = model.predict_proba(df.iloc[:3, :2])
pred = pred[:, 1]
(pred > 0.5 ) + 0
3) sklearn.metrics 함수
- 인자 : (y_true, y_pred)
- 예측 값에 대한 점수를 나타내는 것
from sklearn.metrics import roc_auc_score
pred = model.predict_proba(df.iloc[:, :2])
pred = pred[:, 1]]
# roc_auc_score
roc_auc_score(y_true = df["is_setosa"], y_score= pred)
5. 대표 예제
-독립 변수를 혈당, BMI, 나이로 하고 종속변수를 당뇨 여부로 로지스틱 회귀분석을 할 경우 모델의 AUC는 얼마인가?
- statsmodel 함수 사용
- 소수점 둘쨰자리까지 산출
import pandas as pd
import numpy as np
from statsmodels.api import Logit
from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
# 1. 필요한 feature만 뽑아서 회귀분석
df = pd.read_csv("diabetes.csv")
df.head(2)
model = Logit( endog = df["Outcome"], # 종속변수 : 당뇨 여부
exog = df.loc[:, ["Glucose", "BMI", "Age"]]) #독립 변수 : 3개
model.fit()
# 2. 5개만 예측 결과 확인해보기
# exog로 넣은 X로 확인하기
model.predict(df.loc[:, ["Glucose", "BMI", "Age"]])[:5]
# 3. roc_auc_score 계산
# y_score = 예측 결과 (2에서 구한 data)
round(roc_auc_score(y_true = df["Outcome"],
y_score = model.predict(df.loc[:, ["Glucose", "BMI", "Age"]])), 2)
# 0.54
✅ [나이브 베이즈]
1. 이론
- 사전 확률 및 추가 정보를 기반으로 사후 확률을 추론하는 통계 방법인 베이즈 추정 기반의 분류
- 종속 변수 각 범주의 등장 빈도인 사전확률 설정이 중요
- 나이브 베이즈(Naive Bayes) 분류는 베이즈 정리를 기반으로 한 확률적 머신러닝 알고리즘이다.
특히 독립 변수(특징)들이 서로 독립이라는 가정을 기반으로 함(나이브, 즉 "순진한" 가정).
텍스트 분류(스팸 필터링, 감성 분석)와 같은 자연어 처리(NLP)에서 많이 사용됨.
🔹 2. 나이브 베이즈의 기본 원리
나이브 베이즈 분류기는 베이즈 정리(Bayes' Theorem) 를 활용하여 특정 클래스에 속할 확률을 계산한다.
✅ 베이즈 정리 공식

- ( P(C|X) ) : X(특징)가 주어졌을 때 클래스 C에 속할 확률 (사후 확률, Posterior)
- ( P(X|C) ) : 클래스 C가 주어졌을 때 X가 나타날 확률 (우도, Likelihood)
- ( P(C) ) : 클래스 C가 발생할 확률 (사전 확률, Prior)
- ( P(X) ) : X가 발생할 확률 (Evidence, 모든 클래스의 확률 합)
👉 즉, 특정 입력 데이터(X)가 주어졌을 때, 가장 높은 확률을 가지는 클래스로 분류!
🔹 3. 나이브 베이즈의 특징
특징설명
빠르고 효율적 | 계산이 간단하여 대량 데이터에서도 빠르게 작동 |
텍스트 데이터에 강함 | 스팸 필터링, 감성 분석 등에서 많이 사용됨 |
변수 간 독립 가정 | 실제로는 완전 독립이 아니지만, 가정만으로도 좋은 성능을 보임 |
적은 데이터로도 학습 가능 | 비교적 적은 양의 데이터로도 좋은 결과를 얻을 수 있음 |
🔹 4. 나이브 베이즈의 종류
나이브 베이즈 분류에는 다양한 변형이 있으며, 입력 데이터의 분포 형태에 따라 다르게 적용됨.
유형설명
Gaussian Naive Bayes | 입력 변수가 연속적인 값(실수형 데이터, 정규 분포) 를 따를 때 사용 |
Multinomial Naive Bayes | 입력 변수가 빈도 기반 데이터(텍스트, 문서 분류 등) 일 때 사용 |
Bernoulli Naive Bayes | 입력 변수가 이진 값(0/1)으로 표현될 때 사용 |
👉 실수형 데이터에는 GaussianNB(), 텍스트 분류에는 MultinomialNB() 사용!
2. 예시 문제
- BMI가 0 초과인 데이터만 사용하여 나이브 베이즈 분류를 실시하고자 한다.Coutcome을 종속 변수로 하고 나머지 변수를 독립변수로할 때 종속 변수의 사전 확률은?
- 혈당, 혈압, 나이를 독립변수로 하고 당뇨 발병 여부를 종속변수로 했을 때 그 정확도는 얼마인가?
- 임신여부, 연령대, BMI, 혈당을 독립변수로 하고 당뇨 발병 여부를 종속변수로 했을 떄 나이브 베이즈와 로지스틱 회귀 분석을 실시하고 둘 중 정확도가 높은 모델의 정확도는?
3. import 메서드 & 사용 함수
sklearn - GaussianNB()
import pandas as pd from sklearn.naive_bayes import GaussianNB |
- model = GaussianNB().fit( X = , y = )
- 나이브베이즈 분류 모델을 위한 sklearn의 함수
- 독립변수와 종속변수는 GaussianNB() 함수의 메서드인 fit()에 할당
- 모델 객체의 predict_proba() 메서드로 예측 확률값을 생산
- 이진 분류의 경우 출력된 예측 확률값의 두 번째 열이 1이 될 확률
.fit(X, y) | 모델 학습 |
.predict(X) | 클래스 예측(0, 1, ...) |
.predict_proba(X) | 각 클래스에 대한 확률 예측 |
.score(X, y) | 정확도 평가 |
import pandas as pd
from sklearn.naive_bayes import GaussianNB
df = pd.read_csv("diabetes.csv")
df.head(2)
1. BMI가 0 초과인 데이터만 사용하여 나이브 베이즈 분류를 실시하고자 한다.
outcome을 종속 변수로 하고 나머지 변수를 독립변수로할 때 종속 변수의 사전 확률은?
df_sub = df.loc[df["BMI"] > 0, ]
df_sub["Outcome"].value_counts(normalize=True)
0 0.648613
1 0.351387 --> 정답
2. 혈당, 혈압, 나이를 독립변수로 하고 당뇨 발병 여부를 종속변수로 했을 때 그 정확도는 얼마인가?
# 독립변수 (X): Glucose, BloodPressure, Age 3개 사용.
# 종속변수 (y): Outcome (당뇨병 여부).
1) 나이브 베이즈 분류기로 학습
model = GaussianNB().fit( X = df.loc[:, ["Glucose", "BloodPressure", "Age"]],
y = df["Outcome"])
2) 예측값 추출
pred = model.predict_proba(df.loc[:, ["Glucose", "BloodPressure", "Age"]])
3) 당뇨병 여부 (Outcome=1) 확률이 50% 이상이면 1로 예측( 각 샘플에 대해 클래스 0 (정상), 클래스 1 (당뇨)의 확률 예측)
pred_class = (pred[:, 1] > 0.5 ) + 0
4) 당뇨병 여부의 정확도 학습(accuracy_scroe)
accuray_score(y_pred = pred_class, y_true = df["Outcome"])
round(accuray_score(y_pred = pred_class, y_true = df["Outcome"]) * 100)
# 정답 :76
단계설명
1단계 | Glucose, BloodPressure, Age 변수를 독립변수로 선택 |
2단계 | GaussianNB()로 나이브 베이즈 모델 학습 |
3단계 | predict_proba()로 Outcome=1 (당뇨) 확률 계산 |
4단계 | 확률이 0.5 이상이면 1, 아니면 0으로 변환 |
5단계 | accuracy_score()를 사용해 모델 정확도 평가 |
5. 대표 예제
- 임신여부, 연령대, BMI, 혈당을 독립변수로 하고 당뇨 발병 여부를 종속변수로 했을 떄 나이브 베이즈와 로지스틱 회귀 분석을 실시하고 둘 중 정확도가 높은 모델의 정확도는?
- BMI가 0 초과인 것을 사용하며 학습/평가 세트를 8:2로 분할, seed는 123
- 연령대는 age가 21인 경우 20으로, 39일 경우 30으로 계산한다.
- sklearn의 로지스틱 회귀 함수를 사용하며, thres값은 0.5로 한다.
🔹 1. 문제 개요
- 목표: 임신 여부, 연령대, BMI, 혈당을 독립변수로 하고, 당뇨 발병 여부(Outcome)를 종속변수로 하여 나이브 베이즈와 로지스틱 회귀 분석을 수행.
- 데이터 분할: 학습 데이터와 평가 데이터 비율을 8:2로 분할.
- 임계값(threshold): 0.5 기준으로 분류.
- 평가 지표: accuracy_score()를 사용하여 두 모델의 정확도를 비교.
🔹 2. 데이터 전처리 과정
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
# 데이터 불러오기
df = pd.read_csv("diabetes.csv")
# BMI가 0보다 큰 데이터만 선택
df = df.loc[df["BMI"] > 0, ]
# 연령대 변환 (예: 21 → 20, 39 → 30)
df["Age_g"] = (df["Age"] // 10) * 10
# 임신 여부 변수 생성 (임신 경험 있으면 1, 없으면 0)
df["is_preg"] = (df["Pregnancies"] > 0) + 0
# 학습/테스트 데이터 분할 (8:2 비율, seed=123)
df_train, df_test = train_test_split(df, train_size=0.8, random_state=123)
🔹 3. 가우시안 나이브 베이즈(GaussianNB) 모델 학습 및 평가
# 가우시안 나이브 베이즈 모델 학습
model_nb = GaussianNB()
model_nb.fit(
X=df_train.loc[:, ["is_preg", "Age_g", "BMI", "Glucose"]],
y=df_train["Outcome"]
)
# 확률 예측
pred_nb = model_nb.predict_proba(df_test.loc[:, ["is_preg", "Age_g", "BMI", "Glucose"]])
# 임계값 0.5 기준으로 최종 예측값 변환
pred_nb_class = (pred_nb[:, 1] > 0.5) + 0
# 정확도 계산
accuracy_nb = accuracy_score(y_true=df_test["Outcome"], y_pred=pred_nb_class)
🔹 4. 로지스틱 회귀(Logistic Regression) 모델 학습 및 평가
# 로지스틱 회귀 모델 학습
model_lr = LogisticRegression()
model_lr.fit(
X=df_train.loc[:, ["is_preg", "Age_g", "BMI", "Glucose"]],
y=df_train["Outcome"]
)
# 확률 예측
pred_lr = model_lr.predict_proba(df_test.loc[:, ["is_preg", "Age_g", "BMI", "Glucose"]])[:, 1]
# 임계값 0.5 기준으로 최종 예측값 변환
pred_lr_class = (pred_lr > 0.5) + 0
# 정확도 계산
accuracy_lr = accuracy_score(y_true=df_test["Outcome"], y_pred=pred_lr_class)
✅ [KNN]
1. 이론
📌 K-최근접 이웃(K-Nearest Neighbors, KNN)
🔹 1. KNN이란?
- KNN(K-Nearest Neighbors)은 주어진 데이터 포인트와 가장 가까운 k개의 데이터를 기준으로 예측하는 알고리즘이다.
분류(Classification)와 회귀(Regression) 모두 가능하며, 비모수적(non-parametric) 모델로 데이터 분포를 가정하지 않음.
🔹 2. KNN 분류(Classification)
- 가장 가까운 k개의 데이터를 보고 다수결 투표 방식으로 분류.
- 새로운 데이터가 들어오면 기존 데이터와 유클리드 거리(Euclidean Distance) 등을 이용해 가장 가까운 k개의 데이터를 찾음.
- k값 선택이 중요 → 1에 가까우면 과적합, 너무 크면 과소적합 발생.
✅ K값 설정 가이드
1 (작은 k값) | 모델이 데이터에 너무 민감해 과적합(Overfitting) 발생 가능 |
큰 k값 | 데이터의 일반적인 경향을 따름, 하지만 과소적합(Underfitting) 가능 |
짝수 k값 피하기 | 다수결에서 동점이 발생할 가능성이 있어 보통 홀수를 사용 |
🔹 3. KNN 회귀(Regression)
- KNN 회귀는 분류 모델과 개념은 같지만, 최근접 k개의 값의 평균 또는 가중 평균을 이용하여 예측.
- K값이 작으면 노이즈에 민감, 크면 평균적인 예측이 이루어짐.
🔹 4. KNN 주요 함수
✅ sklearn.neighbors.KNeighborsClassifier()
- 매개변수(n_neighbors) 설정
- n_neighbors: 학습 시 고려할 이웃 데이터 개수 (1이면 과적합 위험)
- metric: 거리 측정 방식 (기본값: minkowski, 일반적으로 euclidean 사용)
- 사용 예시
from sklearn.neighbors import KNeighborsRegressor
model = KNeighborsRegressor(n_neighbors=5)
model.fit(X_train, y_train)
✅ sklearn.neighbors.KNeighborsRegressor()
- 매개변수(n_neighbors) 설정
n_neighbors | 고려할 최근접 이웃 개수 |
weights | uniform(평균), distance(가중 평균) |
from sklearn.neighbors import KNeighborsRegressor
model = KNeighborsRegressor(n_neighbors=5)
model.fit(X_train, y_train)
✅ 정리
KNN 분류 | 가장 가까운 k개의 데이터 다수결 투표로 분류 |
KNN 회귀 | 가장 가까운 k개의 데이터 평균 또는 가중 평균으로 예측 |
k값 설정 | 작은 값 → 과적합 / 큰 값 → 과소적합 (적절한 값 선택 필요) |
KNeighborsClassifier() | KNN 분류 모델 학습 (n_neighbors 설정 가능) |
KNeighborsRegressor() | KNN 회귀 모델 학습 (n_neighbors, weights 설정 가능) |
👉 K값 조절이 KNN 모델 성능의 핵심이며, 데이터에 따라 적절한 값 선택 필요!
2. 예시 문제
-당뇨 발생 여부를 예측하기 위해 임신 횟수, 혈당, 혈압을 사용할 경우 그 정확도는 얼마인가?
- 종속변수를 당뇨 발병 여부로 하고 임신 여부, 혈당, 혈압, 인슐린, 체질량지수를 독립변수로 하여 정확도를 확인했을 떄 그 k값과 정확도가 올바르게 연결되지 않은 것은?
- 종속변수를 체질량지수로 하고 임신여부, 혈당, 혈압, 인슐린을 독립변수로 하여 예측값을 확인했을 때 그 k값과 RMSE가 올바르게 연결되지 않은 것은?
3. import 메서드
import pandas as pd from sklearn.neighbors import KNeighborsClassifier from sklearn.neighbors import KNeighborsRegressor |
4. 사용 함수
1) sklearn.neighbors import KNeighborsClassifier
- 분류 시, 종속 변수는 빼고 학습시켜야 한다.
model = KNeighborsClassifier(n_neighbors = k값들) model.fit(X = df_train.loc[:, X_cols], y = df_train["Outcome"]) pred = model.predict(df_test.loc[:, X_cols]) acc_sub = accuracy_score(y_pred = pred, y_true = df_test["Outcome"] |
2) sklearn.neighbors import KNeighborsRegressor
=> 파라미터 튜닝에 대한 문제가 나오면 KNN
종속변수를 당뇨 발병 여부로 하고 임신 여부, 혈당, 혈압, 인슐린, 체질량지수를 독립변수로 하여 정확도를 확인했을 떄 그 k값과 정확도가 올바르게 연결되지 않은 것은?
df = pd.read_csv("diabetes.csv")
df.head(2)
1. 임신 여부를 수치형으로 변경
df["is_preg"] = (df["Pregnancies"] > 0) + 0
df.head(2)
2. train / test set 나눔
df_train, df_test = train_test_split(df, train_size= 0.8, random_state = 123)
3. k 파라미터 별로 KNN진행
# 독립 변수들 따로 저장
X_cols = ["is_preg", "Glucose", "BloodPressure", "Insulin", "BMI"]
#k의 목록들
neighbors = [3, 5, 10, 20]
accs = []
#for문으로 model의 성능들을 저장
for n_n in neighbors:
model = KNeighborsClassifier(n_neighbors = n_n)
model.fit(X = df_train.loc[:, X_cols], y = df_train["Outcome"])
pred = model.predict(df_test.loc[:, X_cols])
acc_sub = accuracy_score(y_pred = pred, y_true = df_test["Outcome"])
accs = accs + [acc_sub]
#df_score들을 DataFrame으로 변경한 뒤 저장
df_score = pd.DataFrame({"neighbors ": neighbors, "accs" : accs})
df_score["accs"] = df_score["accs"].round(2)
df_score
neighbors accs
0 3 0.71
1 5 0.73
2 10 0.78
3 20 0.76
5. 대표 예제
-종속변수를 체질량지수로 하고 임신여부, 혈당, 혈압, 인슐린을 독립변수로 하여 예측값을 확인했을 때 그 k값과 RMSE가 올바르게 연결되지 않은 것은?
- 데이터를 학습 8의 비율로 분할, seed는 123
- k를 제외한 설정은 모두 기본값
from sklearn.metrics import mean_squared_error
df = pd.read_csv("diabetes.csv")
df.head(2)
df["is_preg"] = (df["Pregnancies"] > 0) + 0
df.head(2)
df_train, df_test = train_test_split(df, train_size= 0.8, random_state = 123)
X_cols = ["is_preg", "Glucose", "BloodPressure", "Insulin"]
neighbors = [3, 5, 10, 20] #k의 목록들
rmses = []
for n_n in neighbors:
model = KNeighborsRegressor(n_neighbors=n_n)
model.fit(X = df_train.loc[:, X_cols], y = df_train["BMI"])
pred = model.predict(df_test.loc[:, X_cols])
rmse_sub = mean_squared_error(y_pred = pred, y_true = df_test["BMI"]) ** 0.5
rmses = rmses + [rmse_sub]
df_score = pd.DataFrame({"neighbors ": neighbors, "rmses" : rmses})
df_score["rmses"] = df_score["rmses"].round(2)
df_score
✅ [의사결정 나무 모델]
1. 이론
📌 의사결정나무(Decision Tree)
🔹 1. 의사결정나무란?
- 의사결정나무(Decision Tree)는 데이터를 기반으로 여러 개의 규칙을 만들어 트리 형태로 분류 또는 회귀를 수행하는 머신러닝 알고리즘이다.
🔹 2. 의사결정나무 분류(Classification Tree)
- 종속 변수가 명목형(범주형)일 때 사용.
- 각 노드에서 데이터를 이진 분류하며, 지니 지수(Gini Index)를 활용한 CART(Classification and Regression Tree) 알고리즘을 사용.
- 과적합 방지 및 모델 단순화를 위해 max_depth, min_samples_split 등의 하이퍼파라미터 조정이 필요.
✅ 지니 지수(Gini Index) 공식

- ( p_i ) : 특정 클래스에 속할 확률
- Gini 값이 낮을수록 더 순수한(한쪽 클래스에 치우친) 노드임.
🔹 3. 의사결정나무 회귀(Regression Tree)
- 종속 변수가 연속형(수치형)일 때 사용.
- 각 노드에서 데이터를 분할한 후, 평균 또는 중앙값을 사용하여 예측 수행.
- 과적합 방지를 위해 max_depth, min_samples_split 등의 하이퍼파라미터 조정이 필요.
🔹 4. 주요 함수 설명
✅ sklearn.tree.DecisionTreeClassifier()
- 주요 매개변수
- max_depth: 트리의 최대 깊이 (과적합 방지)
- random_state: 결과 재현성을 위해 고정
- 사용 예시
from sklearn.tree import DecisionTreeClassifier
model = DecisionTreeClassifier(max_depth=3, random_state=42)
model.fit(X_train, y_train)
✅ sklearn.tree.DecisionTreeRegressor()
- 주요 매개변수
- max_depth: 트리의 최대 깊이 설정
- random_state: 결과 고정
- 사용 예시
from sklearn.tree import DecisionTreeRegressor
model = DecisionTreeRegressor(max_depth=3, random_state=42)
model.fit(X_train, y_train)
✅ 정리
의사결정나무 분류 | 종속 변수가 범주형일 때 사용 (Gini 지수 활용) |
의사결정나무 회귀 | 종속 변수가 연속형일 때 사용 (평균 또는 중앙값 활용) |
과적합 방지 | max_depth, min_samples_split 등의 설정 필요 |
DecisionTreeClassifier() | 분류 모델 생성 (max_depth, random_state 설정 가능) |
DecisionTreeRegressor() | 회귀 모델 생성 (max_depth, random_state 설정 가능) |
👉 의사결정나무는 해석이 쉽고 강력한 모델이지만, 과적합 방지를 위해 적절한 하이퍼파라미터 설정이 중요하다!
2. 예시 문제
- 당뇨병 발병 여부를 예측하기 위해 의사결정나무를 사용하고자 한다. 이 떄 혈당, 혈압, 임신 횟수를 기반으로 예측했을 때의 정확도는?
- 환자의 BMI를 예측하기 위하여 회귀나무를 사용하고자 한다. 이 떄 혈당, 혈압, 피부 두께를 독립변수로 했을 경우 RMSE는 얼마인가?
- 분류나무의 파라미터를 바꿔가면서 성능 평가를 하려고 한다. 당뇨 발병 여부를 종속변수로 하고 혈당,혈압, 임신 횟수, BMI, 나이를 독립변수로 하고 Depth를 3에서 6까지 변화시킬 때 그 결과로 틀린 것은?
3. import 메서드
import pandas as pd from sklearn.tree import DecisionTreeClassifier from sklearn.tree import DecisionTreeRegressor |
4. 사용 함수
당뇨병 발병 여부를 예측하기 위해 의사결정나무를 사용하고자 한다. 이 떄 혈당, 혈압, 임신 횟수를 기반으로 예측했을 때의 정확도는?
-> model을 학습 후, test data에 대한 pred를 만듦 -> accuracy_score 계산
from sklearn.model_selection import train_test_split
df = pd.read_csv("diabetes.csv")
df.head(2)
df_train, df_test = train_test_split(df, train_size = 0.8, random_state =123)
model = DecisionTreeClassifier(random_state = 123)
model.fit(X = df_train.loc[:, ["Glucose", "BloodPressure", "Pregnancies"]],
y = df_train["Outcome"])
pred = model.predict(df_test.loc[:, ["Glucose", "BloodPressure", "Pregnancies"]])
round(accuracy_score(y_pred = pred, y_true = df_test["Outcome"]), 2)
#0.63
5. 대표 예제
분류나무의 파라미터를 바꿔가면서 성능 평가를 하려고 한다. 당뇨 발병 여부를 종속변수로 하고 혈당,혈압, 임신 횟수, BMI, 나이를 독립변수로 하고 Depth를 3에서 6까지 변화시킬 때 그 결과로 틀린 것은?
- 데이터는 학습 7의 비율
- seed는 345, 결과는 소수 둘쨰자리까지 산출
1. data를 train / test로 분리
df = pd.read_csv("diabetes.csv")
df.head(2)
from sklearn.model_selection import train_test_split
df_train, df_test = train_test_split(df, train_size = 0.7, random_state =345)
2. 독립변수에 대한 cols들 따로 저장, depth리스트 저장, 정확도 리스트 저장
cols = ["Glucose", "BloodPressure", "Pregnancies", "BMI", "Age"]
depth_list = [3, 4, 5, 6]
accs = []
3. for문 돌리면서 DecisionTreeClassifier 실행
for depth in depth_list:
model = DecisionTreeClassifier(max_depth = depth, random_state = 345)
model.fit(X = df_train.loc[:, cols],
y = df_train["Outcome"])
# 예측값 생성
pred = model.predict(df_test.loc[:, cols])
# 정확도 저장
accs = accs + [accuracy_score(y_pred = pred,
y_true = df_test["Outcome"])]
# 최종적으로 원하는 data만 보일 수 있도록 dataFrame 생성
df_score = pd.DataFrame({"Depth" : depth_list, "accs" : accs})
df_score["accs"] = df_score["accs"].round(2)
df_score
Depth accs
0 3 0.77
1 4 0.76
2 5 0.76
3 6 0.77
'DS > DS2' 카테고리의 다른 글
이론 1 (0) | 2025.02.25 |
---|---|
Numpy, Pandas (0) | 2025.02.21 |
데이터 분석에 필요한 Python 기본 문법 (0) | 2025.02.21 |