KT 에이블스쿨 복습
[0327 복습] 데이터 전처리 리뷰, 머신러닝, 분류 모델, 회귀모델, 사이킷런 Sklearn
리니끄적
2024. 3. 27. 19:49
머신러닝
학습 방법에 따른 분류
- 지도 학습: 학습 대상이 되는 데이터에 정답을 제공, 규칙성과 데이터의 패턴을 배우게 함!
- 비지도 학습: 정답이 없으며, 데이터 만으로 머신러닝이 알아서 학습하도록 함
- 강화 학습: 선택한 결과에 대해 보상을 받아 행동 개선하는 학습 방법 (ex.알파고)
과제에 따른 분류
- 분류 문제: 이미 분류되 데이터를 학습해 규칙 찾고, 그 규칙 기반으로 새롭게 주어진 데이터를 적절히 분류하는 것을 목적으로 함 (지도 학습) ex. 많이 팔릴까 적게 팔릴까? (범주형)
- 회귀 문제: 이미 결과값이 있는 데이터를 학습 → 입력 값과 결과 값의 연관성 찾고, 연관성 기반으로 새롭게 주어진 데이터에 대한 값을 예측하는 것 목적으로 함 (지도 학습) ex. 판매량 예측 등 (연속적, 수치형)
- 클러스터링(군집화): 주어진 데이터를 학습해 적절한 분류 규칙 찾아 데이터를 분류함을 목적으로 → 정답이 없어 성능 평가도 어려움 (비지도 학습)
분류와 회귀
- 분류와 회귀를 구분하기 전, 성능 vs 설명 중 목적이 어떤 것인지 먼저 구분
- 성능: 얼마나 빠르게 주어진 문제를 풀어내는가? (ex. 고양이, 강아지 분류)
- 회귀: 성능이 조금 떨어지더라도 비즈니스 관점에서 어떻게 설명할 수 있는가?
(ex. 판매량에 중요하게 영향을 미치는 요소들이 무엇일까?)
용어
- 모델: 데이터로부터 패턴을 찾아 수학식으로 정리한 것
- 모델링: 오차가 적은 모델을 만드는 과정
- 모델의 목적: 샘플 → 전체 추정 샘플: 표본, 부분집합, 일부, 과거이ㅡ 데이터 전체: 모집단, 전체집합, 현재와 미래의 데이터 추정: 예측, 추론
행과 열 (**중요행)
- 열(=변수, 특성, 속성, 필드)
- 행(=관측치, 개체, 기록, 사례, 경우)
- 독립변수, 종속변수
- 독립변수 x: 영향을 주는 값, 원인, features
- 종속변수 y: 영향을 받는 값, 결과, target
- 평균과 오차
- 통계학에서 사용되는 가장 단순한 모델 = 평균 (평균도 모델이다!)
- 관측값(=실제값)과 모델 예측값의 차이: 이탈도 → 오차
- 데이터 분리
- 데이터 셋을 학습용, 검증용, 평가용 데이터로 분리!
- 실전: 학습용 / 검증용(튜닝용) / 평가용으로 분리
- 수업: 학습용 / 평가용(마지막에 성능이 좋은지 아닌지 판단하기 위한 미래 데이터)
- x, y 분리
- X ; 행렬이기 때문에 대문자로 표현
- y ; 벡터이기 때문에 소문자로 표현
- 과대적합 vs 과소적합
- 과대적합
- 학습 데이터에서 성능 매우 좋은데, 평가 데이터 성능 매우 좋지 않음 → 실전에서 예측 성능 좋지 않음
- 데이터를 너무 깊이 학습 시켰기 때문임
- 개선: 모델의 복잡도를 조작해 학습에 대해 제한해야 함
- 과소적합
- 학습 데이터보다 평가 데이터에 대한 성능이 매우 좋거나, 모든 데이터에 대한 성능 매우 안 좋음
- 모델이 너무 단순해서 학습 많이 안 되었기 때문
- 개선: 더 많은 데이터를 학습 시켜야 함과소적합
전처리 리뷰
- 라이브러리 불러오기 (numpy, pandas, matplotlib.pyplot, seaborn)
- 데이터 읽어오기: path = ‘경로’ df = pd.read_csv(path)
- 불필요한 변수 제거: 여러 열 동시 제거
drop_cols = [’열 이름1’, ‘열 이름2’, ‘열 이름3’] #리스트로 선언
df.drop(drop_cols, axis=1, inplace=True)
df.drop(columns=drop_cols, inplace=True)
df = df.drop(drop_cols)
** axis = 0은 행, axis = 1은 열을 의미!
결측치 처리(NaN 조치) - 제거
- df.isna().sum(): 변수들의 결측치를 먼저 확인
# 결측치가 있는 모든 행 제거
df.dropna(axis=0, inplace=True)
# 결측치가 있는 모든 열 제거
df.dropna(axis=1, inplace=True)
- 특정 열에서 결측치가 있는 것만 행을 제거하려면 subset 옵션 추가!
df.dropna(subset=['열 이름'], axis=0, inplace=True)
결측치 처리(NaN 조치) - 채우기
- 특정 열 별 평균값으로 채우기
# 특정 열별 열 평균 구하기
# 아래 코드는 Age 평균이 3개밖에 안 나와 있어서 데이터 전체인 891개를 채울 수 없음!
df.groupby(by='열 이름', as_index=False)[['Age']].mean()
# 특정 열별 Age 평균 구하기
df.groupby(by='열 이름', as_index=False)['Age'].transform('mean')
- 최빈값으로 채우기
# 특정 열 변수 값 확인, dropna=True는 결측치를 빼고 계산하라는 뜻!
df['열 이름'].value_counts(dropna=True)
# 데이터의 최빈값 구하기 -> 시리즈 형태 / [0]인덱싱으로 S만 도출
df['열 이름'].fillna(df['열 이름'].mode()[0], inplace=True)
- 앞/뒤 값으로 채우기
# Ozone 변수 NaN 값을 바로 앞의 값으로 채우기
air['Ozone'].fillna(method='ffill', inplace=True)
# Solar.R 변수 NaN 값을 바로 뒤의 값으로 채우기
air['Solar.R'].fillna(method='bfill', inplace=True)
# 확인
air.isna().sum()
- 선형 보간법으로 채우기
# 선형 보간법으로 채우기
# df['열 이름1'].interpolate(method='linear', inplace=True)
# df['열 이름2'].interpolate(method='linear', inplace=True)
df.interpolate(method='linear', inplace=True) # 두 열만 결측치가 있는 것을 알기 때문에 이렇게 해도 가능
- 가변수화
# 가변수 대상 변수 식별
dumm_cols = ['열 이름1', '열 이름2', '열 이름3']
# 가변수화, dtype=int 옵션 지정 안하면 True/False처럼 bool로 등장
df = pd.get_dummies(df, columns=dumm_cols, drop_first=True, dtype=int)
머신러닝01
머신러닝 (Sklearn 사이킷런)
# 라이브러리 불러오기
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
# 경고창 안 뜨게 하려고!
warnings.filterwarnings(action='ignore')
%config InlineBackend.figure_format = 'retina'
- 상관관계 시각화: 문자열이 포함되어 있을 수 있어서 numeric_only 옵션 추가해야 함!
sns.heatmap(df.corr(numeric_only=True),
annot=True, # 숫자 보기
cbar=False, # 컬러바 삭제
fmt='.3f', # 소수점 자리수
square=True, # 정사각형으로 출력
cmap='Blues', # 색
annot_kws={'size':8}) # 숫자 폰트 사이즈
plt.show()
LinearRegression (회귀모델)
1) 사전에 필요 없는 데이터는 drop, fillna 등 전처리해야 함
2) x, y 분리
- target = y 로 선언 (시리즈)
- target 제외 나머지 변수 = x로 선언 (데이터프레임)
# target 확인
target = '열 이름'
# 데이터 분리 (데이터에서 선정한 열만 드롭함)
x = df.drop(target, axis=1)
y = df.loc[:, target
3) 학습용, 평가용 데이터 분리
# 모듈 불러오기 (model 치고 tab, tr 치고 tab)
from sklearn.model_selection import train_test_split
# 7:3으로 분리
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=1, shuffle=True, stratify=y)
- random_state=n: n에 같은 숫자를 넣으면 같은 결과를 받을 수 있음, 반복 실행 시 동일한 결과를 얻기 위해 옵션 지정
→ random_state는 난수 시드값 (시드값: 난수 생성 시 기준값) - shuffle=True: 무작위로 섞는기능, False하면 안섞어서 인덱스 0부터 입력된 순서 그대로 출력됨
- stratify=y는 각 데이터를 최대한 비슷한 개수로 추출하기 위한 옵션, 각 분할에서 클래스 비율이 원래 데이터셋과 동일하게 유지
4) 모델링
- 불러오기 → 선언하기 → 학습하기 → 예측하기 → 평가하기 순으로 진행
# 1단계: 불러오기
from sklearn.linear_model import LinearRegression # linear tab
from sklearn.metrics import mean_absolute_error # 평가지표는 metrics
# 2단계: 선언하기
model = LinearRegression()
# 3단계: 학습하기
model.fit(x_train, y_train)
# 4단계: 예측하기 (y_test 주면 안 됨)
y_pred = model.predict(x_test)
# 실제 값 (시리즈 형태에서 값만 10개 추출)
print(y_test.values[:10])
# 예측 값 (배열, predict 함수의 기능)
print(y_pred[:10])
# 5단계: 평가하기 (오차)
print('MAE:', mean_absolute_error(y_test, y_pred))
- Baseline (기준 모델) 성능 평가: 어떤 모델에서는 기준 모델이 회귀일 수도 있음! (설계하는 사람 마음이다 ~)
- 회귀: 학습 데이터의 평균
- 분류: 학습 데이터의 최빈값
# 기준(Baseline) 모델 성능 평가 -> 학습 데이터의 평균
mean_ozone = y_train.mean()
# 리스트에서 예측할 값 만큼 개수를 곱해서 반복, 배열로 쓰려면 np.array
y_base = np.array([mean_ozone] * len(y_test))
# 5단계: 평가하기
print('MAE:', mean_absolute_error(y_test, y_base))
→ 회귀 모델은 mean_absolute_error(오차)가 적을수록 성능이 좋다!
- 결과 시각화
# y_test는 시리즈라 .values해야 배열로 바뀜
plt.plot(y_test.values, label='Actual')
plt.plot(y_pred, label='Predicted')
plt.plot(y_base, label='Baseline', color='r', linestyle='--')
plt.legend()
plt.show()
KNeighborsClassifier (분류 모델)
- 불러올 때와 마지막 평가하기 부분만 차이가 있음
# 1단계: 불러오기
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
# 5단계: 평가하기 0.846666666667 출력 -> 84퍼센트 맞췄다!
print(accuracy_score(y_test, y_pred))
→ 분류 모델은 accuracy_score(정확도)가 클수록 성능이 좋다!
# 최빈값이 시리즈 형태로 나오기 때문에 인덱싱 해줘야 함
# 최빈값이 모두 같아서 아무거나 사용해도 가능함!
mode_ADMIN = y_train.mode()[0]
y_base = [mode_ADMIN] * len(y_test)
# 5단계: 평가하기
print(accuracy_score(y_test, y_base))
- Baseline (기준 모델) = 최빈값