머신러닝은 빅 데이터를 분석할 수 있는 강력한 툴, 기존 통계학 및 시각화 방법의 한계를 해결 (예측, 패턴 파악, 추천 시스템)
머신러닝이란 명시적으로 프로그래밍을 하지 않고도 컴퓨터가 학습할 수 있는 능력을 갖게 하는 것
머신러닝은 지도학습, 비지도학습, 강화학습으로 구분
지도학습은 회귀분석(Regression), 분류(Classification)으로 구분
지도학습 vs 비지도학습
예측해야 할 결과에 대한 정답 데이터가 있는지 확인
있으면 지도 없으면 비지도학습
강화학습 같은 경우 학습할 데이터가 필요없음 -> 기계가 스스로 학습할 데이터를 만들고 그 데이터를 바탕으로 학습
지도학습을 구현하기 위해서는
1) 데이터에 대한 이해
2) 머신러닝에 사용하기 위한 데이터 처리법
3) 지도학습 방법
- 회귀 알고리즘
- 분류 알고리즘
머신러닝은 데이터라는 디지털 자료를 바탕으로 수행하는 분석 방식으로 자료의 형태를 파악하는 것은 필수 과정!
자료는 크게 수치형(연속형, 이산형), 범주형(순위형, 명목형) 자료로 나뉨
수치형 자료 = 양적 자료
- 수치로 측정이 가능한 자료
ex) 키 ,몸무게, 시험 점수, 나이 등
- 연속형 자료 - 연속적인 관측값을 가짐 ex) 원주율
- 이산형 자료 - 셀 수 있는 관측값을 가짐 ex) 뉴스 글자 수 , 주문 상품 개수
범주형 자료 = 질적 자료
- 수치로 측정이 불가능한 자료
ex) 성별, 지역, 혈액형 등
- 순위형 자료 - 범주 사이의 순서에 의미가 있음 ex) 학점
- 명목형 자료 - 범주 사이의 순서에 의미가 없음 ex) 혈액형
범주형 자료의 요약
- 다수의 범주가 반복해서 관측, 관측값의 크기보다 포함되는 범주에 관심 !
각 범주에 속하는 관측값의 개수를 측정 -> 전체에서 차지하는 각 범주의 비율 파악 -> 효율적으로 범주 간의 차이점을 비교 가능
대표적으로 쓰이는게 도수분포표
- 도수 - 각 범주에 속하는 관측값의 개수 # value_counts()
- 상대도수 - 도수를 자료의 전체 개수로 나눈 비율 # value_counts(normalize=True)
- 도수분포표 - 범주형 자료에서 범주와 그 범주에 대응하는 도수, 상대도수를 나열해 표로 만든 것
크기 차이를 시각화하는 방법 -> 막대그래프
import pandas as pd
import numpy as np
from statistics import variance,stdev
variance() # 분산 구하는 방법
# 분산의 양의 제곱근을 표준편차라고 하고 s로 표기
stdev()
#수치는 -> 히스토그램으로 표시
plt.hist()
수치형 자료는 많은 양의 자료를 의미 있는 수치로 요약하여 대략적인 분포상태를 파악 가능
평균(mean)- 수치형 자료의 통계값 중 가장 많이 사용되는 방법
분산, 표준편차 등을 분포의 퍼진 정도의 측도로 사용
분산의 단위 = 관측값의 단위의 제곱
데이터 전처리 파트
머신러닝 과정
데이터 수집(크롤링 또는 DB 데이터를 통하여 데이터 수집) -> 데이터 분석 및 전 처리(수집한 데이터를 분석하고 머신러닝에 사용할 형태로 전 처리) -> 머신러닝 학습(머신러닝 모델을 사용하여 데이터를 학습) -> 머신러닝 평가(학습된 머신러닝 모델을 평가용 데이터를 사용하여 평가)
여러가지 상태를 되돌아가서 다시 수행하기도 함!
데이터 전 처리의 역할이란?
- 머신러닝의 입력 형태롤 데이터 변환(특성 엔지니어링)
- 결측값 및 이상치를 처리하여 데이터 정제
- 학습용 및 평가용 데이터 분리(머신러닝의 객관성을 위해 학습용과 평가용 데이터를 분리 !)
대부분의 머신러닝 모델은 행렬 형태의 숫자 데이터를 입력 받음 -> 데이터 변환이 필요한 일, 따라서 전 처리 과정이 필요 !
데이터 정제 과정이 필요한 이유 -> 데이터의 결측값(ex NaN같은 값) 및 이상치(ex 나이는 정수지만 소수로 되어있는 값)를 처리하기 위함
범주형 자료 전 처리
대표적인 범주형 자료 변환 방식에는
명목형 자료:
- 수치 맵핑 방식(일반적으로 범주를 0,1로 맵핑하는 방식, 범주가 3개 이상일 경우 수치의 크기 간격을 같게하여 맵핑)
import pandas as pd
titanic = pd.read_csv('./data/titanic.csv')
print('변환 전: \n',titanic['Sex'].head())
titanic = titanic.replace({'male':0,'female':1})
# 변환한 성별 데이터를 출력합니다.
print('\n변환 후: \n',titanic['Sex'].head())
- 더미(Dummy) 기법(각 범주를 0 or 1로 변환, 1은 하나만 존재)
import pandas as pd
# 데이터를 읽어옵니다.
titanic = pd.read_csv('./data/titanic.csv')
print('변환 전: \n',titanic['Embarked'].head())
dummies = pd.get_dummies(titanic[['Embarked']])
# 변환한 Embarked 데이터를 출력합니다.
print('\n변환 후: \n',dummies.head())
순서형 자료:
- 수치 맵핑 방식(수치 간 크기 차이는 커스텀 가능)
수치형 자료 전 처리
모델의 성능을 높이기 위해서 데이터 변환이 필요 !
대표적인 수치형 자료 변환 방식
1) 스케일링: 변수 값의 범위 및 크기를 변환하는 방식, 변수 간의 범위가 차이가 나면 사용
- 정규화: 변수 x를 정규화함 ((x - x_min)/(x_max - x_min)) 0~1사이의 값으로 정규홤
- 표준화: 변수 x를 표준화함 ((x - 평균)/표준편차) 평균이 0이고 표준편차가 1인 경우로 많이 표준화함
2) 범주화: 변수의 값보다 범주가 중요한 경우 사용
데이터 정제 및 분리하기
일반적으로 머신러닝 모델의 입력 값으로 결측값(Null,NaN) 사용 불가능 !
결측값 처리 방식
1) 결측값이 존재하는 샘플 삭제
import pandas as pd
# 데이터를 읽어옵니다.
titanic = pd.read_csv('./data/titanic.csv')
# 변수 별 데이터 수를 확인하여 결측 값이 어디에 많은지 확인합니다.
print(titanic.info(),'\n')
"""
1. Cabin 변수를 제거합니다.
"""
titanic_1 = titanic.drop(columns='Cabin')
# Cabin 변수를 제거 후 결측값이 어디에 남아 있는지 확인합니다.
print('Cabin 변수 제거')
print(titanic_1.info(),'\n')
"""
2. 결측값이 존재하는 샘플 제거합니다.
"""
titanic_2 = titanic_1.dropna()
# 결측값이 존재하는지 확인합니다.
print('결측값이 존재하는 샘플 제거')
print(titanic_2.info())
2) 결측값이 많이 존재하는 변수 삭제
3) 결측값을 다른 값으로 대체
이상치의 경우 모델의 성능을 저하시킬 수 있음, 일반적으로 전 처리 과정에서 이상치를 제거하며 어떤 값이 이상치 인지 판단하는 기준이 중요 !
이상치 판단 기준 방법
1) 통계 지표(카이제곱 검점, IQR 지표 등)를 사용하여 판단
2) 데이터 분포를 보고 직접 판단
3) 머신러닝 기법을 사용하여 이상치 분류
import pandas as pd
import numpy as np
# 데이터를 읽어옵니다.
titanic = pd.read_csv('./data/titanic.csv')
# Cabin 변수를 제거합니다.
titanic_1 = titanic.drop(columns=['Cabin'])
# 결측값이 존재하는 샘플 제거합니다.
titanic_2 = titanic_1.dropna()
# (Age 값 - 내림 Age 값) 0 보다 크다면 소수점을 갖는 데이터로 분류합니다.
outlier = titanic_2[titanic_2['Age']-np.floor(titanic_2['Age']) > 0 ]['Age']
print('소수점을 갖는 Age 변수 이상치')
print(outlier)
print('이상치 처리 전 샘플 개수: %d' %(len(titanic_2)))
print('이상치 개수: %d' %(len(outlier)))
"""
1. 이상치를 처리합니다.
"""
titanic_3 = titanic_2[(titanic_2['Age']-np.floor(titanic_2['Age']) == 0)]
print('이상치 처리 후 샘플 개수: %d' %(len(titanic_3)))
데이터 분리가 필요한 이유는
머신러닝 모델을 평가하기 위해서는 학습에 사용하지 않은 평가용 데이터가 필요! 보통 7:3 ~ 8:2 비율로 데이터를 분리
지도학습 데이터 분리 -> 지도학습의 경우 feature 데이터(label을 예측하기 위한 입력 값)와 label 데이터(예측해야 할 대상이 되는 데이터)를 분리하여 저장
ex) 공부시간 대비 시험점수를 예측할 때 공부시간의 경우 feature 데이터, 시험점수의 경우 label 데이터
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split #데이터 분리 library
# 데이터를 읽어옵니다.
titanic = pd.read_csv('./data/titanic.csv')
# Cabin 변수를 제거합니다.
titanic_1 = titanic.drop(columns=['Cabin'])
# 결측값이 존재하는 샘플 제거합니다.
titanic_2 = titanic_1.dropna()
# 이상치를 처리합니다.
titanic_3 = titanic_2[titanic_2['Age']-np.floor(titanic_2['Age']) == 0 ]
print('전체 샘플 데이터 개수: %d' %(len(titanic_3)))
"""
1. feature 데이터와 label 데이터를 분리합니다.
"""
X = titanic_3.drop(columns='Survived')
y = titanic_3['Survived']
print('X 데이터 개수: %d' %(len(X)))
print('y 데이터 개수: %d' %(len(y)))
"""
2. 학습용, 평가용 데이터로 분리합니다.
"""
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 분리한 데이터의 개수를 출력합니다.
print('학습용 데이터 개수: %d' %(len(X_train)))
print('평가용 데이터 개수: %d' %(len(X_test)))
지도학습 – 회귀
회귀분석이란?
데이터를 가장 잘 설명하는 모델을 찾아 입력값 에 따른 미래 결과값을 예측하는 알고리즘
(label 데이터가 수치형으로 되어있는 것을 예측)
주어진 데이터가 X, Y일 때 X에 대한 Y를 예측할 수 있어야 함
Y = B_0 + B_1*X 식에서 적절한 B_0, B_1을 찾을 수 있어야 함
완벽한 예측은 불가능 -> 최대한 잘 근사해야함
단순 선형 회귀란?
데이터를 설명하는 모델을 직선 형태로 가정
Y = B_0 + B_1*X 로 표현 가능
실제 값과 예측 값 차이의 제곱의 합을 Loss 함수로 정의 !
=> Loss 함수가 작을수록 좋은 모델
Loss: (1/N)∑(y(i) - (B_0 + B_1 * x(i)) )^2 (i ~ N까지의 합)
Loss 함수를 줄인다는 것은 => B_0(y절편), B_1(기울기)을 조절하는 것
이러한 B_0, B_1를 찾는 방법으로는
1) Gradient descent (경사 하강법)
2) Normal equation (least squares)
3) Brute force search
4) ...
경사 하강법: Loss 함수 값이 제일 작게 하는 절편, 기울기를 B_0, B_1라고 할 때
계산 한번으로 그 값들을 구하는 것이 아니라 초기값에서 점진적으로 구하는 방식
Loss 함수 값이 작아지게 계속 업데이트 하는 방법
1) B_0, B_1 값을 랜덤하게 초기화
2) 현재 B_0, B_1 값으로 Loss 값 계산
3) 현재 B_0, B_1 값을 어떻게 변화해야 Loss값을 줄일 수 있는지 알 수 있는 Gradient 값 계산
4) Gradient 값을 활용하여 B_0, B_1 값 업데이트
5) Loss 값의 차이가 거의 없어질 때까지 2~4번 과정을 반복
단순 선형 회귀 특징
•가장 기초적이나 여전히 많이 사용되는 알고리즘
•입력값이 1개인 경우에만 적용이 가능함
•입력값과 결과값의 관계를 알아보는데 용이함
•입력값이 결과값에 얼마나 영향을 미치는지 알 수 있음
•두 변수 간의 관계를 직관적으로 해석하고자 하는 경우 활용
import matplotlib as mpl
mpl.use("Agg")
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
import elice_utils
eu = elice_utils.EliceUtils()
X = [8.70153760, 3.90825773, 1.89362433, 3.28730045, 7.39333004, 2.98984649, 2.25757240, 9.84450732, 9.94589513, 5.48321616]
Y = [5.64413093, 3.75876583, 3.87233310, 4.40990425, 6.43845020, 4.02827829, 2.26105955, 7.15768995, 6.29097441, 5.19692852]
train_X = pd.DataFrame(X, columns=['X'])
train_Y = pd.Series(Y)
# 모델을 트레이닝합니다.
lrmodel = LinearRegression()
lrmodel.fit(train_X, train_Y)
"""
1. train_X에 대해서 예측합니다.
"""
pred_X = lrmodel.predict(train_X)
print('train_X에 대한 예측값 : \n{}\n'.format(pred_X))
print('실제값 : \n{}'.format(train_Y))
다중 선형 회귀
여러 개의 입력값으로 결과값을 예측하고자 하는 경우 -> 다중 선형 회귀
Y = B_0 + B_1*X_1 + B_2*X_2 + .. + B_i*X_i
단순 선형 회귀와 마찬가지로 Loss 함수는 입력값과 실제값 차이의 제곱의 합으로 정의
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
from sklearn.model_selection import train_test_split
# 데이터를 읽고 전 처리합니다
df = pd.read_csv("data/Advertising.csv")
df = df.drop(columns=['Unnamed: 0'])
X = df.drop(columns=['Sales'])
Y = df['Sales']
train_X, test_X, train_Y, test_Y = train_test_split(X, Y, test_size=0.2, random_state=42)
# 다중 선형 회귀 모델을 초기화 하고 학습합니다
lrmodel = LinearRegression()
lrmodel.fit(train_X, train_Y)
print('test_X : ')
print(test_X)
"""
1. test_X에 대해서 예측합니다.
"""
pred_X = lrmodel.predict(test_X)
print('test_X에 대한 예측값 : \n{}\n'.format(pred_X))
# 새로운 데이터 df1을 정의합니다
df1 = pd.DataFrame(np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 1]]), columns=['FB', 'TV', 'Newspaper'])
print('df1 : ')
print(df1)
"""
2. df1에 대해서 예측합니다.
"""
pred_df1 = lrmodel.predict(df1)
print('df1에 대한 예측값 : \n{}'.format(pred_df1))
다중 선형 회귀 특징
여러 개의 입력값과 결과값 간의 관계 확인 가능
어떤 입력값이 결과값에 어떠한 영향을 미치는지 알 수 있음
여러 개의 입력값 사이 간의 상관 관계가 높을 경우 결과에 대한 신뢰성을 잃을 가능성이 있음
다항 회귀(Polynimial Regression)
1차 함수 선형식으로 표현하기 어려운 분포의 데이터를 위한 회귀
Y = B(0)+B(1)*X(1) + B(2)*(X(2)^2) + ... + B(i)*(X(i)^i)
다항 회귀 특징
- 극단적으로 높은 차수의 모델을 구현할 경우 과도하게 학습 데이터에 맞춰지는 과적합 현상 발생
과적합(Overfitting)이란?
모델이 주어진 훈련 데이터에 과도하게 맞춰져 새로운 데이터가 입력 되었을 때 잘 예측하지 못하는 현상
즉, 모델이 과도하게 복잡해져 일반성이 떨어진 경우를 의미함
과적합 방지 방법 – 교차 검증(Cross Validation) , 정규화
교차 겸증 – 모델이 잘 적합되었는지 알아보기 위해 훈련용 데이터와 별개의 테스트 데이터, 그리고 검증 데이터로 나누어 성능 평가하는 방법
일반적으로 k-fold 교차 검증을 많이 사용
k-fold 교차 검증 – 훈련 데이터를 계속 변경하여 모델을 훈련시킴, 데이터를 K등분으로 나누고 K번 훈련시킴
과정
K를 설정하여 데이터 셋을 K개로 나눔
K개 중 한 개를 valid, 나머지를 훈련용으로 사용
K개 모델의 평균 성능이 최종 모델 성능
정규화(Regularization) - 모델의 복잡성을 줄여 일반화된 모델을 구현하기 위한 방법 => 모델 B(i)에 패널티를 부여(선형 회귀를 위한 정규화:L1, L2 정규화)
선형 회귀를 위한 정규화 방법
L1 정규화(Lasso): 불필요한 입력값에 대응되는 B(i)를 정확히 0으로 만든다
L2 정규화(Ridge): 아주 큰 값이나 작은 값을 가지는 이상치에 대한 B(i)를 0에 가까운 값으로 만든다.
회귀 평가 지표
RSS-단순 오차
1) 실제 값과 예측 값의 단순 오차 제곱 합
2) 값이 작을수록 모델의 성능이 높음
3) 전체 데이터에 대한 실제 값과 예측하는 값의 오차 제곱의 총합
RSS 특징
가장 간단한 평가 방법으로 직관적인 해석이 가능
오차를 그대로 이용하기 때문에 입력 값의 크기에 의존적
절대적인 값과 비교 불가능
MSE(Mean Squared Error), MAE – 절대적인 크기에 의존한 지표
MSE - 평균 제곱 오차, RSS에서 데이터 수 만큼 나눈 값, 작을수록 모델의 성능이 높다고 평가
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import mean_squared_error
# 데이터를 읽고 전 처리합니다
df = pd.read_csv("data/Advertising.csv")
df = df.drop(columns=['Unnamed: 0'])
X = df.drop(columns=['Sales'])
Y = df['Sales']
train_X, test_X, train_Y, test_Y = train_test_split(X, Y, test_size=0.2, random_state=42)
# 다중 선형 회귀 모델을 초기화 하고 학습합니다
lrmodel = LinearRegression()
lrmodel.fit(train_X, train_Y)
# train_X 의 예측값을 계산합니다
pred_train = lrmodel.predict(train_X)
"""
1. train_X 의 MSE, MAE 값을 계산합니다
"""
MSE_train = mean_squared_error(train_Y, pred_train)
MAE_train = mean_absolute_error(train_Y, pred_train)
print('MSE_train : %f' % MSE_train)
print('MAE_train : %f' % MAE_train)
# test_X 의 예측값을 계산합니다
pred_test = lrmodel.predict(test_X)
"""
2. test_X 의 MSE, MAE 값을 계산합니다
"""
MSE_test = mean_squared_error(test_Y,pred_test)
MAE_test = mean_absolute_error(test_Y,pred_test)
print('MSE_test : %f' % MSE_test)
print('MAE_test : %f' % MAE_test)
Loss와 MSE의 차이점은 MSE는 지표인 반면 Loss는 그 모델에서 줄여하는 값 즉, 계산을 의미
MAE(Mean Absolute Error) - 평균 절대값 오차, 실제 값과 예측 값의 오차의 절대값의 평균
MSE, MAE 특징
MSE: 이상치 즉, 데이터들 중 크게 떨어진 값에 민감함 => MAE에 민감
MAE: 변동성이 큰 지표와 낮은 지표를 같이 예측할 시 유용
가장 간단한 평가 방법들로 직관적인 해석이 가능
평균을 그대로 이용하기 때문에 입력 값의 크기에 의존적
절대적인 값과 비교 불가능
R^2(결정 계수)
회귀 모델의 설명력을 표현하는 지표로 1에 가까울수록 높은 성능의 모델이라고 해석
R^2 = 1 - (RSS/TSS)
TSS는 데이터 평균 값과 실제 값 차이의 제곱의 합
R^2의 특징
값이 0인 경우, 데이터의 평균 값을 출력하는 직선 모델을 의미
음수 값이 나온 경우, 평균 값 예측보다 성능이 좋지 않음
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import mean_squared_error
# 데이터를 읽고 전 처리합니다
df = pd.read_csv("data/Advertising.csv")
df = df.drop(columns=['Unnamed: 0'])
X = df.drop(columns=['Sales'])
Y = df['Sales']
train_X, test_X, train_Y, test_Y = train_test_split(X, Y, test_size=0.2, random_state=42)
# 다중 선형 회귀 모델을 초기화 하고 학습합니다
lrmodel = LinearRegression()
lrmodel.fit(train_X, train_Y)
# train_X 의 예측값을 계산합니다
pred_train = lrmodel.predict(train_X)
"""
1. train_X 의 R2 값을 계산합니다
"""
R2_train = r2_score(train_Y,pred_train)
print('R2_train : %f' % R2_train)
# test_X 의 예측값을 계산합니다
pred_test = lrmodel.predict(test_X)
"""
2. test_X 의 R2 값을 계산합니다
"""
R2_test = r2_score(test_Y,pred_test)
print('R2_test : %f' % R2_test)
분류 알고리즘(범주형)
분류란?
주어진 입력값이 어떤 클래스(label 범주)에 속할지에 대한 결과값을 도출하는 알고리즘으로 다양한 분류 알고리즘이 존재하며, 예측 목표와 데이터 유형에 따라 적용
알고리즘 종류
트리 구조 기반 – 의사결정나무(간단하고 성능이 좋음 => 앙상블이라 표현), 랜덤포레스트, ...
확률 모델 기반 – 나이브 베이즈 분류기, ...
결정 경계 기반 – 선형 분류기, 로지스틱 회귀 분류기, SVM, ...
신경망 – 퍼셉트론, 딥러닝 모델, ...
의사결정나무(Decision Tree)란?
스무고개와 같이 특정 질문들을 통해 정답을 찾아가는 모델로 최상단의 뿌리 마디에서 마지막 끝 마디까지 아래 방향으로 진행
의사결정나무 분리 기준 -> 데이터의 불순도(Impurity)를 최소화하는 구역으로 나눔
import numpy as np
import pandas as pd
# 풍속을 threshold 값에 따라 분리하는 의사결정나무 모델 함수
def binary_tree(data, threshold):
yes = []
no = []
# data로부터 풍속 값마다 비교를 하기 위한 반복문
for wind in data['풍속']:
# threshold 값과 비교하여 분리합니다.
if wind > threshold:
yes.append(wind)
else:
no.append(wind)
# 예측한 결과를 DataFrame 형태로 저장합니다.
data_yes = pd.DataFrame({'풍속': yes, '예상 지연 여부': ['Yes']*len(yes)})
data_no = pd.DataFrame({'풍속': no, '예상 지연 여부': ['No']*len(no)})
return data_no.append(data_yes,ignore_index=True)
# 풍속에 따른 항공 지연 여부 데이터
Wind = [1, 1.5, 2.5, 5, 5.5, 6.5]
Delay = ['No', 'No', 'No', 'Yes', 'Yes', 'Yes']
# 위 데이터를 DataFrame 형태로 저장합니다.
data = pd.DataFrame({'풍속': Wind, '지연 여부': Delay})
print(data,'\n')
"""
1. binary_tree 모델을 사용하여 항공 지연 여부를 예측합니다.
"""
data_pred = binary_tree(data, threshold = 4)
print(data_pred,'\n')
불순도 측정 방법, 지니 불순도
지니 계수: 해당 구역 안에서 특정 클래스에 속하는 데이터의 비율을 모두 제외한 값 즉, 다양성을 계산하는 방법
지니 불순도
Gini index = 1 - (yes의 확률)^2 - (no의 확률)^2
Gini Impurity = (n_1*N)*Gini_1 + (n_2*N)*Gini_2
n_i: I번째 자식 마디의 데이터 개수
N: 부모 마디의 데이터 개수
의사결정나무의 특징
나무 깊이가 깊어질수록 과적합(Overfitting) 문제 발생 가능성이 매우 높음
학습이 끝난 트리의 작업 속도가 매우 빠르다
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn import tree
from elice_utils import EliceUtils
elice_utils = EliceUtils()
# sklearn에 저장된 데이터를 불러 옵니다.
X, Y = load_iris(return_X_y = True)
# DataFrame으로 변환
df = pd.DataFrame(X, columns=['꽃받침 길이','꽃받침 넓이', '꽃잎 길이', '꽃잎 넓이'])
df['클래스'] = Y
X = df.drop(columns=['클래스'])
Y = df['클래스']
# 학습용 평가용 데이터로 분리합니다
train_X, test_X, train_Y, test_Y = train_test_split(X, Y, test_size=0.2, random_state = 42)
# DTmodel에 의사결정나무 모델을 초기화 하고 학습합니다
DTmodel = DecisionTreeClassifier()
DTmodel.fit(train_X, train_Y)
# test_X에 대해서 예측합니다.
pred_X = DTmodel.predict(test_X)
print('test_X에 대한 예측값 : \n{}'.format(pred_X))
분류 평가 지표
혼동 행렬(Confusion Matrix): 분류 모델의 성능을 평가하기 위함, 예측과 실제에 대한 Positive인지 Negative인지를 행렬로 나타냄
예측 | |||
Positive | Negative | ||
실제 | Positive | True Positive(TP) | False Negative(FN) |
Negative | False Positive(FP) | True Negative(TN) |
FP -> 1형 오류
FN -> 2형 오류
import numpy as np
import pandas as pd
import seaborn as sns
from matplotlib import pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn import tree
from sklearn.metrics import confusion_matrix
from sklearn.utils.multiclass import unique_labels
from elice_utils import EliceUtils
elice_utils = EliceUtils()
# sklearn에 저장된 데이터를 불러 옵니다.
X, Y = load_breast_cancer(return_X_y = True)
X = np.array(X)
Y = np.array(Y)
# 데이터 정보를 출력합니다
print('전체 샘플 개수: ',len(X))
print('X의 feature 개수: ',len(X[0]))
# 학습용 평가용 데이터로 분리합니다
train_X, test_X, train_Y, test_Y = train_test_split(X, Y, test_size=0.2, random_state = 42)
# 분리된 평가용 데이터 정보를 출력합니다
print('평가용 샘플 개수: ',len(test_Y))
print('클래스 0인 평가용 샘플 개수: ',len(test_Y)-sum(test_Y))
print('클래스 1인 평가용 샘플 개수: ',sum(test_Y),'\n')
# DTmodel에 의사결정나무 모델을 초기화 하고 학습합니다
DTmodel = DecisionTreeClassifier()
DTmodel.fit(train_X, train_Y)
# test_X을 바탕으로 예측한 값을 저장합니다
y_pred = DTmodel.predict(test_X)
"""
1. 혼동 행렬을 계산합니다
"""
cm = confusion_matrix(test_Y, y_pred)
print('Confusion Matrix : \n {}'.format(cm))
# 혼동 행렬을 출력합니다
fig = plt.figure(figsize=(5,5))
ax = sns.heatmap(cm, annot=True)
ax.set(title='Confusion Matrix',
ylabel='True label',
xlabel='Predicted label')
fig.savefig("decistion_tree.png")
elice_utils.send_image("decistion_tree.png")
정확도 : 전체 데이터 중에서 제대로 분류된 데이터의 비율로 모델이 얼마나 정확하게 분류하는지를 나타냄, 일반적으로 분류 모델의 주요 평가 방법으로 사용
그러나, 클래스 비율이 불균형 할 경우 평가 지표의 신뢰성을 잃을 가능성이 있음
Accuracy = (TP+TN)/(P+N) P: TP+FN, N: TN+FP
import numpy as np
import pandas as pd
import seaborn as sns
from matplotlib import pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn import tree
from sklearn.metrics import confusion_matrix
from sklearn.utils.multiclass import unique_labels
from elice_utils import EliceUtils
elice_utils = EliceUtils()
# sklearn에 저장된 데이터를 불러 옵니다.
X, Y = load_breast_cancer(return_X_y = True)
X = np.array(X)
Y = np.array(Y)
# 학습용 평가용 데이터로 분리합니다
train_X, test_X, train_Y, test_Y = train_test_split(X, Y, test_size=0.2, random_state = 42)
# 분리된 데이터 정보를 출력합니다
print('학습용 샘플 개수: ',len(train_Y))
print('클래스 0인 학습용 샘플 개수: ',len(train_Y)-sum(train_Y))
print('클래스 1인 학습용 샘플 개수: ',sum(train_Y),'\n')
print('평가용 샘플 개수: ',len(test_Y))
print('클래스 0인 평가용 샘플 개수: ',len(test_Y)-sum(test_Y))
print('클래스 1인 평가용 샘플 개수: ',sum(test_Y),'\n')
# DTmodel에 의사결정나무 모델을 초기화 하고 학습합니다
DTmodel = DecisionTreeClassifier()
DTmodel.fit(train_X, train_Y)
# 예측한 값을 저장합니다
y_pred_train = DTmodel.predict(train_X)
y_pred_test = DTmodel.predict(test_X)
# 혼동 행렬을 계산합니다
cm_train = confusion_matrix(train_Y, y_pred_train)
cm_test = confusion_matrix(test_Y, y_pred_test)
print('train_X Confusion Matrix : \n {}'.format(cm_train))
print('test_X Confusion Matrix : \n {}'.format(cm_test))
"""
1. 정확도를 계산합니다.
"""
acc_train = DTmodel.score(train_X, train_Y)
acc_test = DTmodel.score(test_X,test_Y)
# 정확도를 출력합니다.
print('train_X Accuracy: %f' % (acc_train))
print('test_X Accuracy: %f' % (acc_test))
정밀도(precision): 모델이 Positive라고 분류한 데이터 중에서 실제로 Positive인 데이터의 비율
Negative가 중요한 경우 => 실제로 Negative인 데이터를 Positive라고 판단하면 안되는 경우 사용되는 지표
재현율(Recall, TPR): 실제로 Positive인 데이터 중에서 모델이 Positive로 분류한 데이터의 비율
Positive가 중요한 경우 => 실제로 Positive인 데이터를 Negative라고 판단하면 안되는 경우 사용되는 지표
import numpy as np
import pandas as pd
import seaborn as sns
from matplotlib import pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn import tree
from sklearn.metrics import confusion_matrix
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from elice_utils import EliceUtils
elice_utils = EliceUtils()
# sklearn에 저장된 데이터를 불러 옵니다.
X, Y = load_breast_cancer(return_X_y = True)
X = np.array(X)
Y = np.array(Y)
# 학습용 평가용 데이터로 분리합니다
train_X, test_X, train_Y, test_Y = train_test_split(X, Y, test_size=0.2, random_state = 42)
# DTmodel에 의사결정나무 모델을 초기화 하고 학습합니다
DTmodel = DecisionTreeClassifier()
DTmodel.fit(train_X, train_Y)
# 예측한 값을 저장합니다
y_pred_train = DTmodel.predict(train_X)
y_pred_test = DTmodel.predict(test_X)
# 혼동 행렬을 계산합니다
cm_train = confusion_matrix(train_Y, y_pred_train)
cm_test = confusion_matrix(test_Y, y_pred_test)
print('train_X Confusion Matrix : \n {}'.format(cm_train))
print('test_X Confusion Matrix : \n {}'.format(cm_test),'\n')
"""
1. 정밀도를 계산합니다.
"""
precision_train = precision_score(train_Y, y_pred_train)
precision_test = precision_score(test_Y,y_pred_test)
# 정밀도를 출력합니다.
print('train_X Precision: %f' % (precision_train))
print('test_X Precision: %f' % (precision_test),'\n')
"""
2. 재현율을 계산합니다.
"""
recall_train = recall_score(train_Y, y_pred_train)
recall_test = recall_score(test_Y, y_pred_test)
# 재현율을 출력합니다.
print('train_X Recall: %f' % (recall_train))
print('test_X Recall: %f' % (recall_test))
분류 목적에 따라 다양한 지표의 활용
분류 결과를 전체적으로 보고 싶다면 -> 혼동 행렬
정답을 얼마나 잘 맞췄는지 -> 정확도
FP 도는 FN의 중요도가 높다면 -> 정밀도, 재현율
로지스틱 회귀(Logistic Regression)란?
분류 문제에 적용하기 위해 출력값의 범위를 수정한 회귀로 Y값은 0~1사이 값만을 가짐
이진 분류 문제를 해결하기 위한 모델이 로지스틱 회귀
SVM(Support Vector Machine) - 최적읜 결정 경계 즉, 데이터를 분류하는 기준 선을 정의하는 모델
최적의 결정 경계는 데이터 군으로부터 최대한 멀리 떨어지는 것
클래스를 분류하는 기준서에 Margin(결정 경계와 서포트 벡터 사이의 거리)을 둘 수 있음
서포트 벡터: 결정 경계와 가장 가까이 있는 데이터 포인트들
SVM의 역할=>Margin을 최대화 하는 결정 경계를 찾음
Hard Margin vs Soft Margin
이상치 허용 범위에 따라 구분됨
Hard는 Margin 안에 데이터 포인트가 없어야 하고 다른 클래스가 들어가면 안됨
Soft는 Margin 안에 데이터가 어느 정도 들어갈 수 있도록 허용, 다른 클래스가 들어가는 것도 어느 정도 허용
SVM 특징
선형 분류와 비선형 분류 모두 기능
고차원 데이터에서도 높은 성능의 결과를 도출
회귀에도 적용 가능
나이브 베이즈 분류
각 특징들이 독립적 즉, 서로 영향을 미치지 않을 것이라는 가정 설정
베이즈 정리를 활용한 확률 통계학적 분류 알고리즘
𝑃(𝐴𝐵) = 𝑃(𝐴∩𝐵) / 𝑃(𝐵) = (𝑃(𝐵|𝐴)𝑃(𝐴)) / 𝑃(𝐵)
P(A|B): 사건 B가 발생했을 때, A도 같이 발생했을 확률
베이즈 정리를 활용하여 입력값이 해당 클래스에 속할 확률을 계산하여 분류 !
ex)
𝑃(스팸|단어1, 단어2, 단어3...)>𝑃(정상|단어1, 단어2, 단어3...) 이면 스팸
나이브 베이즈 분류 특징
각 특징들이 독립이라면 다른 분류 방식에 비해 결과가 좋고, 학습 데이터도 적게 필요
각 특징들이 독립이 아니라면 즉, 특징들이 서로 영향을 미치면 분류 결과 신뢰성 하락
학습 데이터에 없는 범주의 데이터일 경우 정상적 예측 불가능
KNN(K-Nearest Neighbor)
기존 데이터 가운데 가장 가까운 k개 이웃의 정보로 새로운 데이터를 예측하는 방법론
(유사한 특성을 가진 데이터는 유사 범주에 속하는 경향이 있다는 가정 하에 분류)
- 설정된 K값에 따라 가까운 거리 내의 이웃의 수에 따라 분류
- 새로운 고객 데이터(검정색)이 들어왔을 때
만약 K=1 이면 주황색 클래스로 분류
K=3 이면 초록색 클래스로 분류
KNN 특징
- 직관적이며 복잡하지 않은 알고리즘, 결과 해석이 쉬움
- K값 결정에 따라 성능이 크게 좌우됨
- 딱히 학습이랄 것이 없는 Lazy Model
'AI & Data' 카테고리의 다른 글
Apache Flink에 대해.. (1) | 2024.01.24 |
---|---|
비지도 학습 (0) | 2021.11.07 |
Matplotlib 기초 학습 내용 (0) | 2021.10.30 |
pandas 기초 학습 내용 (0) | 2021.10.29 |
numpy 기초 내용 학습 (0) | 2021.10.29 |