본문 바로가기
[KT AIBLE SCHOOL]에이블스쿨

[KT에이블스쿨] 04.09 머신러닝 회귀

by 오동일지 2025. 4. 9.

지난 글에 이어서~.~


머신러닝 실습(회귀 문제)

머신러닝 기본 프로세스

  1. 데이터 불러오기
  2. 데이터 탐색(EDA)
  3. 데이터 전처리
  4. 학습 / 테스트 데이터 분리
  5. 모델 선택 및 학습
  6. 예측 및 평가

 

1. 데이터 불러오기

- 필요한 라이브러리 설치

- pd.read_cvs() 함수로 데이터 읽어오기

 

2. 데이터 탐색(EDA)

- .info() 함수를 통해 데이터의 요약을 한눈에! (이 때 결측치와 y값 확인하기)

- .value_counts()를 통해 특정 값의 분포 확인하기

- .describe()를 통해 수치형 데이터의 이상치와 요약통계량 살피기

 

3. 데이터 전처리

- .duplicated()를 통해 중복값 확인

- drop_duplicates()를 통해 중복된 값 삭제

- .isnull().sum()으로 결측치 여부 확인

- .fillna()를 통해 결측치가 존재하는 행을 .mean()으로 평균값으로 채워줌

- LabelEncoder / fit / transform을 통해 라벨 인코딩 진행

- 다양한 시각화 툴로 확인!

- df.loc[df['bmi']>47]와 같이 조건식으로 이상치의 데이터 살펴보기

- MinMaxScaler를 이용하여 정규화 진행

 

--------------------------------------------<복습 끝>--------------------------------------------------------

 

4. 학습 / 테스트 데이터 분리

from sklearn.model_selection import train_test_split

-> 데이터 분리에 필요한 라이브러리 임포트

x = df_scaled[:, :-1] # 모든 행, 마지막 열을 제외한 모든 열 → "입력 변수들 (features)"
y = df_scaled[:, -1] # 모든 행, 마지막 열만 선택         → "타겟 변수 (label)"

# print(df_scaled.shape)
# print(x.shape)
# print(y.shape)

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=0)

print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)

📌 NumPy 슬라이싱 규칙

  • [:, :] : [행, 열] 의미
  • :-1 : 마지막 열을 제외한 모든 열
  • -1 : 마지막 열만

-> 정답 변수 분리(x, y)

-> 학습 데이터와 테스트 데이터를 분리

-> 분리 비율 8:2


5-1. 모델 선택 및 학습 - LinearRegression()

from sklearn.linear_model import LinearRegression

model = LinearRegression()
model.fit(x_train, y_train)

-> 선형 회귀 모델 선택

-> 학습데이터를 넣고 학습

 

6-1. 예측 / 평가 - LinearRegression()

pred = model.predict(x_test)

-> 학습된 회귀 모델의 성능평가를 위해 테스트 데이터로 예측

from sklearn.metrics import mean_absolute_error, mean_squared_error

mae = mean_absolute_error(y_test, pred)
mse = mean_squared_error(y_test, pred)

print('mae : ', mae)
print('mse : ', mse)

-> 회귀 모델의 성능 평가

-> 성능 평가 지표인 mae, mse를 이용하여 예측데이터와 비교


5-2. 모델 선택 및 학습 - RandomForestRegressor()

from sklearn.ensemble import RandomForestRegressor

model = RandomForestRegressor()
model.fit(x_train, y_train)

-> sklearn.ensemble - RandomForestRegressor

-> 모델 선택 , 학습

 

6-2. 예측 및 평가 - RandomForestRegressor()

-> 전과 동일


5-3. 모델 선택 및 학습 - Ridge()

from sklearn.linear_model import Ridge

model = Ridge()
model.fit(x_train, y_train)

 

5-4. 모델 선택 및 학습 - Lasso()

from sklearn.linear_model import Lasso

model = Lasso()
model.fit(x_train, y_train)

 

대부분 랜덤포레스트가 값이 잘나옴

성능평가지표 값이 작을수록 Good!!


분류(Classification) 학습

- 종속 변수가 범주형 데이터일 때 사용하는 지도학습 방법

- 데이터를 특정 그룹(클래스)로 분류하는 모델을 만들 때 사용

ex) 이메일이 스팸인지 아닌지, 환자가 병이 있는지 아닌지 예측

 

특징)

  • 출력값(정답, 목표 변수)이 범주형 데이터
  • 입력 데이터가 어느 그룹(클래스)에 속하는지 예측
  • 다중 클래스 문제(여러 카테고리)도 가능

대표 분류 모델

  • 로지스틱 회귀(Logistic Regression) - sklearn.linear_model

로지스틱 회귀는 이름은 회귀지만, 실제로는 분류 모델

결과값을 "확률"로 해석하고, 이를 기준으로 "클래스를 예측"하기 때문

- 출력값이 0 또는 1(이진분류) 혹은 여러 개의 클래스(다중분류)로 나뉨

- 시그모이드 함수를 사용하여 확률 값으로 변환

ex) 스팸 메일 분류, 암 진단

 

  • 결정 트리(Decision Tree) - sklearn.tree

- 데이터를 여러 개의 규칙을 기반으로 나누어 예측

- 과적합 위험이 높음

ex) 고객 세분화, 금융 사기 탐지

 

  • 랜덤 포레스트(Random Forest) - sklearn.ensemble

- 여러 개의 의사결정트리를 조합하여 예측

- 과적합 방지 기능

ex) 신용 점수 예측, 질병 진단

 

  • 그래디언트 부스팅 분류(Gradient Boosting Classifier)

- 여러 개의 약한 분류 모델을 조합하여 강력한 모델을 만듦

- XGBoost, LightGBM, CatBoost 등 알고리즘 포함

ex) 금융 사기 탐지, 광고 클릭 예측

 

성능은 good / 속도는 bad

-> eXtreme Gradient Boosting(XGBoost )는 병렬처리로 단점 보완


분류 모델 성능평가 지표

1. 혼동 행렬, 오차 행렬(Confusion Matrix)

- 분류의 예측 범주와 실제 데이터의 분류 범주를 교차 표 형태

- 예측 오류가 얼마인지, 어떠한 유형의 예측 오류가 발생하는지 함께 나타냄

 

 

2. 정확도(Accuracy)

- 모델이 전체 문제 중 정답을 맞춘 비율

- 0~1 사이의 값, 1에 가까울수록 좋음

- 불균형한 데이터의 경우에 정확도는 적합한 평가지표가 아님

 

3. 재현율(Recall) = 민감도(sensitivity)

- 실제 정답이 positive인 것들 중 모델이 positive로 예측한 비율

- recall을 높이기 위해선 FN을 낮추는게 중요

- 0~1사이의 값, 1에 가까울수록 좋음

ex) 

“암에 걸린 사람 중에 진짜로 암이라고 진단받은 비율”

높으면 좋다진짜 환자를 놓치지 않는다

4. 정밀도(Precision)

- 모델이 positive로 예측한 것들 중 실제 정답이 positive인 비율

- precisioin을 높이기 위해선 FP를 낮추는게 중요

- 0~1사이의 값, 1에 가까울수록 좋음

ex)

“암이라고 진단받은 사람 중에 실제 암 환자의 비율”

높으면 좋다헛소리 안 한다 (건강한 사람 겁주지 않는다)


🧠 예시 상황에서의 고민

  • 병원에서 재현율을 높게 가져가면?
    → 암 환자 거의 다 잡음 (좋음),
    근데 건강한 사람도 암이라고 할 수 있음 (정밀도 낮음)
  • 정밀도만 높이려다 재현율 떨어지면?
    → 암 환자 대부분을 놓칠 수도 있음 (진짜 위험함)

🔁 정밀도를 높이면 왜 재현율이 떨어질까?

핵심은 이거야:

정밀도를 높이려면 "진짜 확실한 경우만 암이라고 판단"하게 돼.

그 말은 곧…

  • 애매하거나 의심스러운 케이스는 암이 아닌 걸로 넘긴다
  • 그러면 진짜 암 환자도 일부 놓치게 된다

👉 그래서 재현율이 떨어지는 것

 

🎯 예시 비유

상황: 암 진단 시스템

① 재현율을 높이는 전략

  • 조금만 이상해도 암!
  • 웬만하면 암이라고 말함
  • 결과:
    • 암 환자 거의 다 찾아냄 (TP 많음)
    • 근데 건강한 사람도 많이 암이라고 함 (FP 많음)
    • 정밀도는 떨어짐, 재현율은 높음

② 정밀도를 높이는 전략

  • 진짜 확신이 있어야 암!
  • 애매하면 그냥 정상이라 판단함
  • 결과:
    • 암으로 진단된 사람은 진짜 암일 확률 높음 (Precision ↑)
    • 근데 암 환자 중 일부는 놓침 (FN 많아짐)
    • 정밀도는 오르지만 재현율은 떨어짐

5. F1-Score

- Recall과 Precision의 조화평균

조화평균은 평균적인 변화율을 측정할 때 주로 사용

- Recall과 Precision은 상호 보완적인 평가 지표이기에 F1-Score 사용

이 두가지는 Trade-off관계 : 한 쪽이 높아지면 한 쪽이 낮아짐

- 한쪽으로 치우치지 않고 모두 클 때 큰 값을 가짐

- 0~1사이의 값, 1에 가까울수록 좋음


머신러닝 실습(분류 문제)

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings(action='ignore')

-> 필요 라이브러리 불러오기

 

1. 데이터 불러오기

x = pd.read_csv('./data/X.csv', encoding='euc-kr')
y = pd.read_csv('./data/y.csv', encoding='euc-kr')

print(x.shape)
print(y.shape)

-> 인코딩 방식은 'euc-kr' / 한국어 처리에 용이

데이터 출처 : 한국데이터산업진흥원

 

2. 데이터 탐색

x.head() #상위 데이터를 출력하여 구조 확인

y.head() 

x.info() # 데이터 요약정보를 보고 변수의 유형과 분포 확인

x.describe() #데이터의 요약정보, 통계 정보를 보고 변수의 유형과 분포 확인

 

3. 데이터 전처리

머신러닝에 사용할 수 있도록 데이터 가공

from sklearn.preprocessing import LabelEncoder #인코딩
from sklearn.preprocessing import StandardScaler #데이터 표준화

-> 데이터 탐색 후 필요한 처리과정에 사용할 라이브러리 임포트

 

type(x) # 이 실습에서는 DataFrame
x = x.iloc[:, 1:]
y = y.iloc[:, -1]

  • iloc은 위치로 접근 (정수 인덱스)
  • loc은 이름(라벨)으로 접근 (컬럼명, 인덱스명)
  • NumPy에는 loc이나 iloc 없음, 그냥 [] 슬라이싱
  • Pandas의 DataFrame에서는 둘 다 사용 가능

-> x : 9개의 컬럼으로 y: 성별을 맞춰보자~

 

x.isnull().sum()

-> 결측치 확인

환불금액에서 결측치 확인됨

x['환불금액'].fillna(0, inplace=True)

-> 해당 결측치에 알맞은 값 채워넣기

-> inplace : 원본 데이터를 직접 바꿔라

 

x.info()

-> 주구매상품과 주구매지점 인코딩 필요

 

from sklearn.preprocessing import LabelEncoder

col_lst = ['주구매상품', '주구매지점']

for col in col_lst:
  encoder = LabelEncoder()
  x[col] = encoder.fit_transform(x[col])

x.head()

-> 반복문을 이용하여 인코딩

 

4. 학습 / 테스트 데이터 분리

from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=1234)
print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)

-> 데이터 분리 및 확인

 

<두가지 방법으로 스케일링 해보자>

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
x_train = scaler.fit_transform(x_train)
x_test = scaler.transform(x_test)

1. 전체 데이터 스케일링

cols = ['총구매액', '최대구매액', '환불금액', '내점일수', '내점당구매건수', '주말방문비율', '구매주기']
scaler = StandardScaler()
scaler.fit(x_train[cols])
x_train[cols] = scaler.transform(x_train[cols])
x_test[cols] = scaler.transform(x_test[cols])

x_train.head()

2. 특정 범위만 스케일링

두 방법의 차이점

주의점)

fit : 규칙만들기

transform은 적용

train 데이터에는 fit 과 transform

test 데이터에는 transform만 적용해야 함

 

5-1. 모델링 - LogisticRegression

from sklearn.linear_model import LogisticRegression #불러오기

model = LogisticRegression() #선언하기

model.fit(x_train, y_train) #학습하기

-> 이진분류 모델

 

6-1. 예측 성능 확인해보기 - LogisticRegression

from sklearn.metrics import confusion_matrix, accuracy_score, recall_score, precision_score, f1_score

pred = model.predict(x_test)

confusion = confusion_matrix(y_test, pred)
accuracy = accuracy_score(y_test , pred)
precision = precision_score(y_test , pred)
recall = recall_score(y_test , pred)
f1 = f1_score(y_test,pred)

print('오차 행렬')
print(confusion)

print(f'정확도: {accuracy}, 정밀도: {precision}, 재현율: {recall}, F1: {f1}')

5-2. 모델링 - DecisionTreeClassifier

from sklearn.tree import DecisionTreeClassifier

model = DecisionTreeClassifier(max_depth=10) #모델 객체화
model.fit(x_train, y_train) #모델 학습

 

6-2. 예측 성능 확인 - DecisionTreeClassifier

다른 모델과 똑같이 진행


5-3. 모델링 - RandomForestClassifier

from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier()
model.fit(x_train, y_train)

6-3. 예측 성능 확인 - RandomForestClassifier

다른 모델과 똑같이 진행

 


5-4. 모델링 - XGBoost

from xgboost import XGBClassifier
model = XGBClassifier(n_estimators=100, max_depth=3)
model.fit(x_train, y_train)

6-4. 예측 성능 확인 - XGBoost

다른 모델과 똑같이 진행

 

요약 한 줄

✔ 회귀: "얼마나 틀렸는가?" → 작을수록 좋음
✔ 분류: "얼마나 맞췄는가?" → 클수록 좋음


군집화(Clustering)

1. 군집화

- 비슷한 데이터끼리 그룹으로 묶는 방법

 

특징)

  • 라벨이 없는 데이터에서 유사한 특성을 가진 데이터끼리 자동으로 그룹화
  • 새로운 데이터에 대한 그룹 예측 가능
  • 데이터에 숨겨진 구조파악에 유용

대표 군집화 알고리즘

  • K-평균 군집화: 데이터를 k개의 그룹으로 나눔
  • 계층적 군집화: 데이터 간의 유사도를 기반으로 계층구조로 나눔
  • DBSCAN: 밀도가 높은 지역을 기준으로 데이터 군집을 찾고, 이상치 식별

2. 차원축소

- 고차원 데이터를 저차원으로 변환하여 중요한 특징만 남기는 방법

- 데이터 복잡성을 줄여서 분석하기 쉽게하고 연산속도를 높임

 

대표 차원 축소 알고리즘

  • 주성분 분석: 데이터의 분산을 최대한 유지하면서 차원 축소
  • t-SNE: 데이터 간의 관계를 유지하면서 저차원으로 변환(시각화에 적합)
  • LDA: 분류 문제에서 클래스 간의 차이를 최대화하는 방식으로 차원 축소

비지도 학습 실습 : 붓꽃 품종 군집화

1. 데이터 불러오기

from sklearn.datasets import load_iris
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

iris = load_iris()
irisDF = pd.DataFrame(data=iris.data, columns=['sepal_length','sepal_width','petal_length','petal_width'])
irisDF.head()

-> 붓꽃 데이터셋을 불러오고 DataFrame으로 변환

 

2. KMeans 군집화 진행

from sklearn.cluster import KMeans

model = KMeans(n_clusters=3,  max_iter=300, random_state=1234)
model.fit(irisDF)

n_clusters -> 나눌 그룹 갯수

max_iter -> 반복 횟수

 

3. 군집화 결과 확인

print(model.labels_)

-> 각 데이터가 어느 그룹에 속했는지 확인

 

4. 원래 타겟값과 군집 결과 비교

irisDF['target'] = iris.target
irisDF['cluster'] = model.labels_

irisDF.groupby(['target', 'cluster'])['s_l'].count()

 

5. 군집 시각화

plt.scatter(irisDF['p_l'], irisDF['p_w'], c=irisDF['cluster'])
plt.colorbar(label='Cluster')
plt.show()

-> 2차원 공간으로 시각화해야 군집을 확인하기 더 좋음