pocket

[ML] Machine Learning 머신러닝 과정 정리 (코드로 이해하기) 본문

Machine Learning

[ML] Machine Learning 머신러닝 과정 정리 (코드로 이해하기)

jpocket 2025. 5. 8. 18:42
반응형

머신러닝 전체 흐름도 도식화

사용 툴: tldraw

출처: 나

 

 

 

 

 

 

데이터 준비

# 데이터 생성
import pandas as pd
import numpy as np
data = pd.DataFrame({
    '메뉴': ['[인기]아이펠치킨','닭강정','간장치킨','마늘치킨','파닭','승일양념치킨','양념반후라이드반','황금후라이드','[베스트]풀잎치킨'],
    '가격': [16000,15000,14000,14000,14000,13000,13000,12000,9900],
    '호수' : [11,12,9,9,11,10,10,10,10],
    '칼로리' : [1200.0,1500.0,1600.0,1800.0,1300.0,1400.0,1300.0,1000.0,1000.0],
    '할인율' : [0.5,0.2,0.2,0.2,0.2,0.2,0.2,0.2,np.nan],
    '할인가' : [8000.0,12000.0,11200.0,11200.0,11200.0,10400.0,10400.0,9600.0,np.nan],
    '원산지' : ['국내산','브라질','국내산','국내산','브라질','국내산','국내산','국내산','국내산'],
    '살찔까요' : ['no','yes','yes','yes','yes','yes','yes','no','no'],
    '고민' : ['무조건먹자','먹지말자','먹지말자','먹지말자','먹지말자','먹지말자','먹지말자','무조건먹자','무조건먹자']
})
data.to_csv('final_modudak.csv', index=False)


# 데이터 변경
data.loc[2,"원산지"] = "미국"


df = data[["가격", "호수", "칼로리", "원산지","살찔까요"]].copy()
df

 

 

 

 

 

 

데이터 전처리

데이터 유형에 따라 다르게 처리한다.

크게 범주형 데이터(=문자열 데이터)와 수치형 데이터로 구분한다.

 

 

1. 범주형 데이터

먼저 범주형 데이터를 숫자 형태로 변경해야 한다.

1) Label Encoding

from sklearn.preprocessing import LabelEncoder


le = LabelEncoder()
le.fit(df['원산지'])
le.transform(df['원산지'])

# 방법1
# 기본 방법
le = LabelEncoder()
le.fit(df['원산지'])
df['원산지'] = le.transform(df['원산지'])
le.fit(df['살찔까요'])
df['살찔까요'] = le.transform(df['살찔까요'])


# 방법2
# 간편한 방법
df['원산지'] = le.fit_transform(df['원산지'])
df['살찔까요'] = le.fit_transform(df['살찔까요'])


# 방법3
# 여러 개 컬럼 한 번에 인코딩(반복문 사용)
df = data[["가격", "호수", "칼로리", "원산지","살찔까요"]].copy() # 원본 보호
cols = ['원산지','살찔까요']

for col in cols:
    le = LabelEncoder()
    df[col] = le.fit_transform(df[col])


# 방법4
# 리스트 형태로 쓰기 어려울 경우
df = data[["가격", "호수", "칼로리", "원산지","살찔까요"]].copy()
cols = df.select_dtypes(include='object').columns # object형태를 한 번에 리스트로 바꾸기

for col in cols:
    le = LabelEncoder()
    df[col] = le.fit_transform(df[col])

 

2) One-Hot Encoding

from sklearn.preprocessing import OneHotEncoder

ohe = OneHotEncoder(sparse_output=False) # sparse_output 기본값은 True, False로 해주어야 배열 형태로 반환
cat = ohe.fit_transform(df[['원산지']]) # 데이터프레임 형태로 들어가야 함


# 컬럼 이름 설정 방법1
ohe.categories_
# [array(['국내산', '미국', '브라질'], dtype=object)]

# 컬럼 이름 설정 방법2
ohe.get_feature_names_out()
# array(['원산지_국내산', '원산지_미국', '원산지_브라질'], dtype=object)


# 데이터프레임으로 변환
df_cat = pd.DataFrame(cat,columns=ohe.get_feature_names_out()) # 컬럼 이름 설정 방법2 선택


# 원본 데이터프레임에 합기기
df = pd.concat([df,df_cat], axis=1)


# 중복 컬럼 제거하기
df = df.drop(['원산지'], axis=1)





# 여러 개 컬럼 한 번에 인코딩
# 레이블 인코딩은 반복문을 사용했지만, 
# 원핫 인코딩은 반복문을 사용하지 않음
from sklearn.preprocessing import OneHotEncoder
df = data[["가격", "호수", "칼로리", "원산지","살찔까요"]].copy()

cols = df.select_dtypes(include='object').columns
ohe = OneHotEncoder(sparse_output=False)
cat = ohe.fit_transform(df[cols])
df_cat = pd.DataFrame(cat, columns=ohe.get_feature_names_out()) # 데이터프레임으로 변환
df = pd.concat([df, df_cat], axis=1) # 원본 데이터프레임에 합기기
df = df.drop(cols, axis=1) # 중복 컬럼 제거하기

 


[Tips] OneHotEncoding - Pandas이용

df = data[["가격", "호수", "칼로리", "원산지","살찔까요"]].copy()
df = pd.get_dummies(df)

 

train, test 데이터의 컬럼 수가 일치해야 하는데 그렇지 않을 경우에 get_dummies 를 사용하면 안 된다.
머신러닝 모델이 입력 차원 오류로 학습/예측을 못하게 된다.
이때 get_dummies가 아닌, OneHotEncoder를 사용하여 일관된 컬럼 구성을 보장할 수 있다.

 

 

 

 

 

 

2. 수치형 데이터

다음은 수치형 데이터다.

이는 표준화, 정규화 방법으로 변환한다.

  1. 표준화만 하기
  2. 정규화만 하기
  3. 표준화 -> 정규화하기

1) 표준화

# 표준화
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
scaler.fit_transform(df[['가격']])



# 여러 컬럼을 한 번에 표준화
cols = ['가격','호수','칼로리']
scaler = StandardScaler()
df[cols] = scaler.fit_transform(df[cols])

 

 

2) 정규화

# Min-Max 정규화 (0과 1사이의 값)
from sklearn.preprocessing import MinMaxScaler

cols = ['가격','호수','칼로리']
mm = MinMaxScaler()
df[cols] = mm.fit_transform(df[cols])

 

 

 

 

 

 

모델 선택

분류와 회귀 두 가지로 나누었고, 각각의 코드를 알아보자.

데이터셋 목표 값 특징 문제 유형
유방암 (Breast Cancer) 0 또는 1 (악성/양성) => 범주형 분류 (Classification)
당뇨병 (Diabetes) 수치형 값 (예: 혈당 수치 등) =>연속형 회귀 (Regression)

 

 

1) 분류 (유방암 데이터) = 분리

from sklearn.datasets import load_breast_cancer
import pandas as pd

# 데이터 준비
dataset = load_breast_cancer()

# feature name check
dataset.feature_names

# target check -> 훈련시키라고 제공되는 정답지
dataset.target

# make to dataframe
cancer_df = pd.DataFrame(data=dataset.data, columns=dataset.feature_names)

# Add to target
cancer_df['target'] = dataset.target

 

모델 학습 & 모델 예측 & 모델 평가

from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(
    cancer_df.drop('target',axis=1),
    cancer_df['target'],
    test_size=0.3, random_state=1004) # test_size=0.3이면 train_size는 70%다.
    

from sklearn.tree import DecisionTreeClassifier
# 모델 선택 - 의사결정나무
model = DecisionTreeClassifier()
model.fit(x_train, y_train)
pred = model.predict(x_test)


# 정확도 평가 accuracy_score(실제값, 예측값)
from sklearn.metrics import accuracy_score
accuracy_score(y_test, pred)

 

 

 

 

2) 회귀 (당뇨병 데이터)

from sklearn.datasets import load_diabetes
# 데이터 준비
dataset = load_diabetes()

# make to dataframe
diabetes_df = pd.DataFrame(data=dataset.data, columns=dataset.feature_names)

# Add to target
diabetes_df['target'] = dataset.target

 

모델 학습 & 모델 예측 & 모델 평가

from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(
    diabetes_df.drop('target',axis=1),
    diabetes_df['target'],
    test_size=0.3, random_state=1004) # test_size=0.3이면 train_size는 70%다.


from sklearn.linear_model import LinearRegression
# 모델 선택 - 선형회귀
model = LinearRegression()
model.fit(x_train, y_train)
pred = model.predict(x_test)


from sklearn.metrics import mean_squared_error
# 정확도 mean_squared_error(실제값, 예측값)
mean_squared_error(y_test, pred)