MySQL은 다음과 같이 설치해 주면 된다.

꼭 버전을 확인하고 알맞은 버전으로 설치해야 된다.

 

커뮤니티를 설치하고 새로운 DB를 사용하기 위해서는 schema칸을 선택하고 빈 공간에 우클릭후 BD이름을 작성한다.

하단의 Apply를 누르면 새로운 DB를 만들 수 있다. 생성된 DB를 더블클릭하면 해당 DB가 선택되고 진한 글씨로 바뀐다.

선택된 DB에서 쿼리문이 돌아가게 된다.

 

 

테이블을 생성하고 항목의 데이터를 보고싶다면, 해당 테이블을 우클릭하여 Select Rows를 실행하면 자동으로 확인할 수 있는 쿼리문을 작성해준다. 상단을 보면 Limit를 걸어둔 것을 볼 수 있다.

실문에서는 정말 많은 데이터를 갖고있기 때문에 리미트가 없다면 큰일이 날 수 있다.

우리가 다루는 데이터는 적은량의 데이터기에 리미트를 걸지 않아도 되지만 실무에서는 꼭 확인하고 리미트를 걸도록 하자.

 

 

SQL 문

SQL: Structured Query Language
•  데이터베이스에서데이터를 조회하거나처리(입력,수정,삭제)할 때사용하는 구문

 

주석

범위 주석 : /* */

한줄 주석 : -- 

Sequential

  • 순차적으로 쌓아가며 모델 생성
  • Input → Output Layer로 순차적 연결
  • Sequential 함수 안에 리스트로 레이어 입력
model = Sequential([Input(shape = (n, )),
                    Dense(128, activation = 'relu'),
                    Dense(64, activation = 'relu'),
                    Dense(32, activation = 'relu'),
                    Dense(16, activation = 'relu'),
                    Dense(10, activation = 'softmax')])

 

Function

  • 모델을 좀더 복잡하게 구성
  • 모델을 분리해서 사용 가능
  • 다중 입력, 다중 출력 가능
  • 레이어 : 앞 레이어 연결 지정
  • Model 함수로 시작과 끝 연결해서 선언
il = Input(shape = (nfeatures, ))
hl1 = Dense(10, activation = 'relu')(il)
hl2 = Dense(10, activation = 'relu')(hl1)
hl3 = Dense(2, activation = 'relu')(hl2)
ol = Dense(1)(hl3)

model = Model(inputs = il, outputs = ol)

 

 

다중 입력

모델 선언

  • concatenate 
  • 옆으로 붙이기, 하나의 레이어처럼 묶기
  • cbl = concatenate([hl1_1, hl1_2])

모델 사용

  • 모델 예측 시, 전처리 된 두 가지 입력을 리스트로 묶어서 사용
  • pred = model.predict([x_val1, x_val2]) 
# 모델 구성
input_1 = Input(shape=(nfeatures1,), name='input_1')
input_2 = Input(shape=(nfeatures2,), name='input_2')

# 첫 번째 입력을 위한 레이어
hl1_1 = Dense(10, activation='relu')(input_1)

# 두 번째 입력을 위한 레이어
hl1_2 = Dense(20, activation='relu')(input_2)

# 두 히든레이어 결합
cbl = concatenate([hl1_1, hl1_2])

# 추가 히든레이어
hl2 = Dense(8, activation='relu')(cbl)

# 출력 레이어
output = Dense(1)(hl2)

# 모델 선언
model = Model(inputs = [input_1, input_2], outputs = output)

model.summary()

 

시계열 데이터

ML 기반 시계열 모델링

  • 특정 시점 데이터들(1차원)과 예측대상시점(𝑦𝑡+1) 과의 관계로 부터 패턴을 추출하여 예측
  • 모델 구조 예 : 𝑦𝑡+1 = 𝑤1𝑥1𝑡 + 𝑤2𝑥2𝑡+ 𝑤3𝑥3𝑡 + 𝑤4𝑦𝑡 + 𝑤0
  • 시간의 흐름을 x변수로 도출하는 것이 중요.

DL 기반 시계열 모델링

  • 시간흐름 구간(timesteps) 데이터들(2차원)과 예측대상시점(𝑦𝑡+1) 과의 관계로 부터 패턴 추출
  • 어느정도 구간(timesteps)을 하나의 단위로 정할 것인가?
  • 분석 단위를 2차원으로 만드는 전처리 필요. ➔ 데이터셋은 3차원

 

잔차 분석

잔차(Residuals) = 실제 데이터 – 예측값

  • 시계열 모델 𝑦 = 𝑓(𝑥) + 𝜀
  • 모델이 잘 만들어 졌다면, 잔차𝜀는 White Noise에 가까워야 함.
  • 잔차𝜀가 White Noise에 가깝지 않다면 𝑓(𝑥)는 아직 𝑦 의 패턴을 제대로 반영하지 않음. ➔ 더 해야 할 일이 남아 있음.

잔차 분석

  • 시각화 : ACF, PACF
  • 검정
    • 정상성 검정(ADF Test, KPSS Test)
    • 정규성 검정(Shapiro-wilk Test)
    • 자기상관 검정(Ljung-Box Test)
    • 등분산성 검정(G-Q Test)

 

RNN(Recurrent Neural Networks)

 

RNN으로 시계열 데이터 모델링 하기

✓과거의 정보를 현재에 반영해 학습하도록 설계

 

RNN을 위한 데이터 전처리

  • 데이터 분할 1 : x, y
  • 스케일링
    • X 스케일링은 필수
    • Y 값이 크다면 최적화를 위해 스케일링 필요 ➔ 단, 모델 평가 시 원래 값으로 복원
  •  3차원 데이터셋 만들기 
  • 데이터 분할2 : train, val

 

SimpleRNN

  • 노드 수 1개 ➔ 레이어의 출력 형태 : timesteps * 노드 수
  • return_sequences : 출력 데이터를 다음 레이어에 전달할 크기 결정 ★ ★
    • True : 출력 크기 그대로 전달 ➔ timesteps * node수
    • False : 가장 마지막(최근) hidden state 값만 전달 ➔ 1 * node 수
    • 마지막 RNN Layer 를 제외한 모든 RNN Layer : True
    • 마지막 RNN Layer : False와 True 모두 사용 가능
    • 단, True를 사용하려면 Flatten으로 펼친 후 Dense Layer 로 연결

'<프로그래밍> > [python]' 카테고리의 다른 글

[python] 딥러닝 성능관리  (0) 2024.10.14
[python] 딥러닝 기초  (0) 2024.10.10
[python] 머신러닝의 기초3  (0) 2024.09.30
[python] 머신러닝의 기초2  (1) 2024.09.27
[python] 머신러닝의 기초  (0) 2024.09.26

모델의 복잡도와 과적합

모델의 복잡도

  • 너무 단순한 모델 : train, val 성능이 떨어짐
  • 적절히 복잡한 모델 : 적절한 예측력
  • 너무 복잡한 모델 : train 성능 높고, val 성능 떨어짐

과적합을 해결하기 위해서 여러 요소를 조절해야 됨

  • Epoch와 learning_rate
  • 모델 구조 : hidden layer 수, node 수
  • 미리 멈춤 Early Stopping
  • 임의 연결 끊기 Dropout
  • 가중치 규제하기 Regularization(L1, L2)

 

Early Stopping

반복 횟수(epoch)가 많으면 과적합 될 수 있음

  • 항상 과적합이 발생되는 것 X
  • 반복횟수가 증가할 수록 val error가 줄어들다가 어느 순간부터 다시 증가할 수 있음.
  • val error가 더 이상 줄지 않으면 멈춰라 ➔ Early Stopping
  • 일반적으로 train error는 계속 줄어듦

EarlyStopping 옵션

  • monitor : 기본값 val_loss
  • min_delta : 오차(loss)의 최소값에서 변화량(줄어드는 량)이 몇 이상 되어야 하는지 지정. (기본값 0)
  • patience : 오차가 줄어들지 않는 상황을 몇 번(epoch) 기다려줄 건지 지정. (기본값 0) ✓
    • from keras.callbacks import EarlyStopping
    • es = EarlyStopping(monitor = 'val_loss', min_delta = 0, patience = 0)
  • fit 안에 지정
  •  callbacks : epoch 단위로 학습이 진행되는 동안, 중간에 개입할 task 지정 
    • model.fit(x_train, y_train, epochs = 100, validation_split = .2, callbacks = [es])
from keras.callbacks import EarlyStopping

# 모델 선언
clear_session()

model2 = Sequential( [Input(shape = (nfeatures,)),
                      Dense(128, activation= 'relu'),
                      Dense(64, activation= 'relu'),
                      Dense(32, activation= 'relu'),
                      Dense(1, activation= 'sigmoid')] )
model2.compile(optimizer= Adam(learning_rate = 0.001), loss='binary_crossentropy')

# EarlyStopping 설정 ------------
min_de = 0.0005
pat = 7

es = EarlyStopping(monitor = 'val_loss', min_delta = min_de, patience = pat)

# 학습
hist = model2.fit(x_train, y_train, epochs = 100, validation_split=0.2,
                  callbacks = [es]).history

Dropout - 연결을 임의로 끊기 

Dropout

  • 과적합을 줄이기 위해 사용되는 규제(regularization) 기법 중 하나
  • 학습시, 신경망의 일부 뉴런을 임의로 비활성화 ➔ 모델을 강제로 일반화

학습 시 적용 절차

  • 훈련 배치에서 랜덤하게 선택된 일부 뉴런을 제거
  • 제거된 뉴런은 해당 배치에 대한 순전파 및 역전파 과정에서 비활성화
  • 이를 통해 뉴런들 간의 복잡한 의존성을 줄여 줌
  • 매 epochs 마다 다른 부분 집합의 뉴런을 비활성화 ➔ 앙상블 효과

 

Dropout Rate 옵션

  • Hidden Layer 다음에 Dropout Layer 추가
  • Import : from keras.layers import Dropout
  • ex) Dropout(0.4) : hidden layer의 노드 중 40%를 임의로 제외시킴. 
  • 보통 0.2 ~ 0.5 사이의 범위 지정
  • 조절하면서 찾아야 하는 하이퍼파라미터!
  • Feature가 적을 경우 rate를 낮추고, 많을 경우는 rate를 높이는 시도
from keras.layers import Dropout

# input_shape : feature 수 도출
nfeatures = x_train.shape[1]

# 메모리 정리
clear_session()

# Sequential 타입
model3 = Sequential( [Input(shape = (nfeatures,)),
                      Dense(128, activation= 'relu'),
                      Dropout(0.4),
                      Dense(64, activation= 'relu'),
                      Dropout(0.4),
                      Dense(32, activation= 'relu'),
                      Dropout(0.4),
                      Dense(1, activation= 'sigmoid')] )

# 컴파일
model3.compile(optimizer= Adam(learning_rate = 0.001), loss='binary_crossentropy')

# 학습
hist = model3.fit(x_train, y_train, epochs = 50, validation_split=0.2, verbose = 0).history

성능관리 요약

데이터

  • 입력 데이터 정제, 적절한 전처리
  • 데이터 늘리기 : 열(적절한 feature 추가), 행(데이터 건수 늘리기) 

모델 구조

  • 은닉층, 노드 수 늘리기 : 성능이 증가할 때 까지 
  • activation 

학습

  • epochs, learning_rate, optimizer  

과적합 문제

  • 모델링 목적 : 모집단 전체에서 두루 잘 맞추는 (적당한) 모델 만들기
  • 과적합 : 학습 데이터에서만 높은 성능, 다른 데이터에서는 낮은 성능

과적합 문제 해결

  • 데이터 건수 늘리기
  • 모델 복잡도 조절하기 ➔ 가중치 규제(Regularization)
  • 반복 학습 횟수(epochs) 적당히 ➔ early stopping

모델 저장하기

  • 최종 모델 저장
  • 체크포인트에서 모델 저장
  • 성능이 개선되면 저장하기 가능.

기본환경

jupyter lab / notebook 이 아닌 google colaboratory를 활용한다.

파일을 google drive에 업로드하여 연결 앱에서 지정해주는데 없다면 다음과 같이 진행하여 설치해 준다.

 

 

딥러닝 학습 절차

  1. 가중치 초기값을 할당한다. (초기 모델을 만든다. / 초기값은 random하게 할당됨)
  2. (초기)모델로 예측한다.
  3. 오차를 계산한다. (loss function)
  4. 가중치 조절 : 오차를 줄이는 방향으로 가중치를 적절히 조절한다.(optimizer)
    • 적절히 조절 → 얼마 만큼 조절할 지 결정하는 하이퍼파라미터 : learning rate (lr)
  5.  다시 처음으로 가서 반복한다.
    • 전체 데이터를 적절히 나눠서(mini batch) 반복 : batch_size
    • 전체 데이터를 몇 번 반복 학습할 지 결정 : epoch

 

딥러닝 모델링 : Regression

딥러닝 전처리 : 스케일링

Normalization(정규화) - 모든 값의 범위를 0 ~ 1로 변환

Standardization(표준화) - 모든 값을, 평균 = 0, 표준편차 = 1 로 변환

Dense

Input : Input(shape = ( , ))

  • 분석단위에 대한 shape
  • 1차원 : (feature 수, )
  • 차원 : (rows, columns)

Output : Dense( n )

  • 예측 결과가 1개 변수(y가 1개 변수)
  • 이진분류 : activation  = 'sigmoid'  / 0과 1 사이의 확률값으로 지
  • 다중분류 : activation  = 'softmax ' 

Hidden Layer  : Dense( n, activation = 'relu' )

  • activation  : 현재 레이어(각 노드)의 결과값을 다음 레이어(연결된 각 노드)로 어떻게 전달할지 결정/변환해주는 함수
    • Hidden Layer에서는 : 선형함수를 비선형 함수로 변환
    • Output Layer에서는 : 결과값을 다른 값으로 변환해 주는 역할

Hidden Layer에서 무슨 일이 일어나는가?

  • 기존 데이터를 받아들임.
  • (우리는 정확히 알기 어렵지만) 뭔가 새로운 특징(New Feature)을 만듬
  • 특징은 분명히 예측된 값과 실제 값 사이의 오차를 최소화 해주는 유익한 특징일 것으로 생각.
  • Hidden Layer에서는 기존 데이터가 새롭게 표현(Representation) 
  • Feature Engineering이 진행

Compile

컴파일(Compile)

  • 선언된 모델에 대해 몇 가지 설정을 한 후 컴퓨터가 이해할 수 있는 형태로 변환하는 작업

loss function(오차함수)

  • Cost Function, Objective Function 과 같은(유사한) 의미
  • 오차 계산을 무엇으로 할지 결정
  • 회귀모델 : mse 
  • 분류모델 : cross entropy

optimizer 

  • 오차를 최소화 하도록 가중치를 업데이트하는 역할 
  • Adam - 최근 딥러닝에서 가장 성능이 좋은 Optimizer로 평가 됨.
  • learning_rate - 업데이트 할 비율 / 기울기(gradient)에 곱해지는 조정 비율 (걸음걸이의 ‘보폭’을 조정한다고 표현)

 

학습

Epoch

  •  주어진 train set을 몇 번 반복 학습할 지 결정

validation_split = 0.2 

  • train 데이터에서 20%를 검증셋으로 분리

batch_size

  • 배치 단위로 학습(가중치 업데이트), 기본값 32
  • 전체 데이터를 적절히 나눠서(mini batch)

.history 

  • 학습을 수행하는 과정 중에 가중치가 업데이트 되면서 학습 시 계산된 오차 기록

 

학습 곡선

  • 모델 학습이 잘 되었는지 파악하기 위한 그래프
  • 정답은 아니지만, 학습 경향을 파악하는데 유용.
  • 각 Epoch 마다 train error와 val error가 어떻게 줄어들고 있는지 확인

바람직한 학습 곡선

  1. 초기 epoch에서는 오차가 크게 줄어듬.
  2. 오차 하락이 꺾이임. 
  3. 점차 완만해짐 - 그러나 학습곡선의 모양새는 다양함

바람직 하지 않은 학습 곡선

 

Case 1

  • 학습이 덜 됨
  • 오차가 줄어들다가 학습이 끝남
  • 조치 : 학습을 더! / epoch 수를 늘리거나 learning rate을 크게 한다.

 

 

 

 

 

Case 2

  • train_err가 들쑥날쑥
  • 가중치 조정이 세밀하지 않음
  • 조치 : 조금씩 업데이트 / learning rate을 작게

 

 

 

 

 

 

Case 3

  • 과적합
  • Train_error는 계속 줄어드는데, val_error는 어느 순간부터 커지기 시작
  • 너무 과도하게 학습이 된 경우
  • 조치 - Epoch 수 줄이기

 

 

 

# 라이브러리 로딩
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.model_selection import train_test_split
from sklearn.metrics import *
from sklearn.preprocessing import MinMaxScaler

from keras.models import Sequential
from keras.layers import Dense, Input
from keras.backend import clear_session
from keras.optimizers import Adam

#학습곡선 그래프 함수 만들기
def dl_history_plot(history):
    plt.figure(figsize=(10,6))
    plt.plot(history['loss'], label='train_err', marker = '.')
    plt.plot(history['val_loss'], label='val_err', marker = '.')

    plt.ylabel('Loss')
    plt.xlabel('Epoch')
    plt.legend()
    plt.grid()
    plt.show()

#데이터로딩
path = 'https://raw.githubusercontent.com/DA4BAM/dataset/master/Carseats.csv'
data = pd.read_csv(path)

#데이터 준비
target = 'Sales'
x = data.drop(target, axis=1)
y = data.loc[:, target]

#가변수화
cat_cols = ['ShelveLoc', 'Education', 'US', 'Urban']
x = pd.get_dummies(x, columns = cat_cols, drop_first = True)

#데이터분할
x_train, x_val, y_train, y_val = train_test_split(x, y, test_size=.2, random_state = 20)

#Scaling
scaler = MinMaxScaler()
x_train = scaler.fit_transform(x_train)
x_val = scaler.transform(x_val)

#모델 설계
nfeatures = x_train.shape[1]
model = Sequential([Input(shape = (nfeatures, )), Dense(7, activation = 'relu'), #선형을 비선형으로
                    Dense(1)])
model.summary()

#컴파일 + 학습
model.compile(optimizer = Adam(learning_rate = 0.05), loss = 'mse')
result = model.fit(x_train, y_train, epochs = 40, validation_split= 0.2).history

#학습곡선
dl_history_plot(result)

#검증
pred = model.predict(x_val)
print(mean_absolute_error(y_val, pred))

 

 

딥러닝 모델링 : 이진분류 / 다중분

Output Layer

  • 결과를 0, 1로 변환하기 위해 각 범주에 대한 결과를 범주별 확률 값으로 변환
  • 이진분류 : activation = 'sigmoid'
    • Loss Function : binary_crossentropy

 

 

  • 다중분류 : activation = 'softmax' - 0~1사이 확률 값으로 변환
    • Loss Function : sparse_categorical_crossentropy(정수 인코딩) 
    • Loss Function : categorical_crossentropy(one-hot 인코딩) / 기능적으로는 둘다 동일

독립변수 개수로 회귀분석을 단순 회귀와 다중 회귀로 분류 

Linear Regression

단순 회귀(Simple Regression) 

  • 독립변수 하나가 종속변수에 영향을 미치는 선형 회귀
  • 𝑥 값 하나만으로 𝑦값을 설명할 수 있는 경우 예) 행복지수가 연수입만으로 결정됨
  • 회귀식: 𝑦ො = 𝑤0 + 𝑤1𝑥1
  • 독립변수의 최선의 가중치와(w1)와 편향(w0)을 찾음
  • 단순 회귀의 회귀 계수
    • 모델 학습 후 회귀계수 확인 가능
    • model.coef_: 회귀계수(=가중치)
    • model.intercept_: 편향
    • y_hat = x * model.coef_ + model.intercept_

 

다중 회귀(Multiple Regression)

  • 여러 독립변수가 종속변수에 영향을 미치는 선형 회귀
  • 𝑦 값을 설명하기 위해서는 여러 개의 𝑥 값이 필요한 경우 예: 여러 요인들에 의해 보스턴 지역 집 값이 결정 됨
  • 회귀식: 𝑦ො = w0 + w1𝑥1 + w2𝑥2 + w3𝑥3 + ⋯ + w𝑛𝑥𝑛
  • 각 독립변수의 최선의 가중치와(w1, w2, w3, w4…)와 편향(w0)을 찾음
  • 단순 회귀의 회귀 계수
    • 회귀계수가 여럿이므로 독립변수 이름과 같이 확인하기를 권고
    • model.coef_: 회귀계수(=가중치)
    • model.intercept_: 편향
    • y_hat = x * model.coef_ + model.intercept_

 

K-Nearest Neighbor

  • k-Nearest Neighbor: k 최근접 이웃(가장 가까운 이웃 k개)
  • 학습용 데이터에서 k개의 최근접 이웃의 값을 찾아 그 값들로 새로운 값을 예측하는 알고리즘
  • 회귀와 분류에 사용되는 매우 간단한 지도학습 알고리즘
  • 다른 알고리즘에 비해 이해하기 쉽지만, 연산 속도가 느림
  • Regression - k개 값의 편균을 계산하여 값을 예측
  • Classification - 가장 많이 포함된 유형으로 분류
  • k(탐색하는 이웃 개수)에 따라 데이터를 다르게 예측할 수도 있음
    • k 값에 따라 예측 값이 달라지므로 적절한 k 값을 찾는 것이 중요(기본값=5)
    • 일반적으로 k를 1로 설정 안함 → 이웃 하나로 현재 데이터를 판단하기에는 너무 편향된 정보
    • k를 홀수로 설정 → 짝수인 경우 과반수 이상의 이웃이 나오지 않을 수 있음
  • MinMaxScaler를 사용하면 더 나은 결과값을 얻을 수 있다.
    • from sklearn.preprocessing import MinMaxScaler
    • 평가용 데이터에도 학습용 데이터를 기준으로 스케일링을 수행함(학습용 데이터의 최댓값, 최솟값, 평균 등을 사용)
scaler = MinMaxScaler()
x_train_s = scaler.fit_transform(x_train)
x_test_s = scaler.transform(x_test)
# x_train이 array형태로 저장됨 다시 DF로 바꿔주는 작업 필요
x_train = pd.DataFrame(x_train_s, columns = list(x))

#인덱스 지정을 해야된다면 다음과 같은 방법 활용 가능
# scaler = MinMaxScaler().set_output(transform="pandas")

 

Decision Tree

  • 결정 트리, 의사 결정 나무 등으로 번역
  • 특정 변수에 대한 의사결정 규칙을 나무 가지가 뻗는 형태로 분류해 나감
  • 분류와 회귀 모두에 사용되는 지도학습 알고리즘
  • 분석 과정이 직관적이며, 이해와 설명하기가 쉬움
  • 스케일링 등의 전처리 영향도가 크지 않음
  • 분석 과정을 실제로 눈으로 확인할 수 있음 → 화이트박스 모델
  • 스무고개처럼 의미 있는 질문을 먼저 하는 것이 중요
  • 훈련 데이터에 대한 제약 사항이 거의 없는 유연한 모델 → 과적합으로 모델 성능이 떨어지기 쉬움 → 트리 깊이를 제한하는(=가지치기) 튜닝이 필요

용어 정리

  • Root Node(뿌리 마디): 전체 자료를 갖는 시작하는 마디
  • Child Node(자식 마디): 마디 하나로부터 분리된 2개 이상의 마디
  • Parent Node(부모 마디): 주어진 마디의 상위 마디
  • Terminal Node(끝 마디): 자식 마디가 없는 마디(=Leaf Node)
  • Internal Node(중간 마디): 부모 마디와 자식 마디가 모두 있는 마디
  • Branch(가지): 연결되어 있는 2개 이상의 마디 집합
  • Depth(깊이): 뿌리 마디로부터 끝 마디까지 연결된 마디 개수(층을 연결한 선의 갯수라 생각하면 편함)

 

분류와 회귀

분류

  • 비용 함수 : 불순도
  • 마지막 노드에 있는 샘플들의 최빈값을 예측값으로 반환.
  • 불순도를 수치화 할 수 있는 지표(지니 불순도 / 엔트로피)
  • 지니 불순도(Gini Impurity)
    • 지니 불순도 = 1 − (양성 클래스 비율2+음성 클래스 비율2 )
    • 분류 후에 얼마나 잘 분류했는지 평가하는 지표
    • 얼마나 순도가 증가했는지, 불순도가 감소했는지
  • 지니 불순도 특징
    • 지니 불순도가 낮을수록 순도가 높음
    • 지니 불순도는 0~0.5 사이의 값(이진 분류의 경우)
      • 순수하게(완벽하게) 분류되면 → 0
      • 완벽하게 섞이면(50:50) → 0.5
    • 지니 불순도가 낮은 속성으로 의사결정 트리 노드 결정
     
  • 엔트로피(Entropy)
    • 엔트로피 = −음성클래스비율× 𝑙𝑜𝑔2 음성클래스비율 − 양성클래스비율 × 𝑙𝑜𝑔2(양성클래스비율)
    • 𝑝𝑖 : 집합 안에서 속성 i의 확률을 나타냄
      • 예를 들어 𝑝𝑖=1이면 집합 안의 모든 항목이 i 속성을 가진 경우
    • 엔트로피는 0~1 사이의 값
      • 순수하게(완벽하게) 분류되면 → 0
      • 완벽하게 섞이면(50:50) → 1

정보 이득(Information Gain)

  • Information Gain
  • 엔트로피는 단지 속성의 불순도를 표현
  • 우리가 알고 싶은 것 = 어떤 속성이 얼마나 많은 정보를 제공하는가!
  • 정보 이득 공식 • 정보 이득이 크다 = 어떤 속성으로 분할할 때 불순도가 줄어든다
  • 모든 속성에 대해 분할한 후 정보 이득 계산
  • 정보 이득이 가장 큰 속성부터 분할

가지치기

  • 가지치기를 하지 않으면 모델이 학습 데이터에는 매우 잘 맞지만, 평가 데이터에는 잘 맞지 않음
    • → 과대적합, 일반화되지 못함
  • 여러 하이퍼파라미터 값을 조정해 가지치기 할 수 있음
    • max_depth, min_samples_leaf, min_samples_split 등
  •  학습 데이터에 대한 성능은 낮아지나, 평가 데이터에 대한 성능을 높일 수 있음
  • 가장 적절한 하이퍼파라미터 값을 찾도록 노력해야 함

max_depth ☆

  • 트리의 최대 깊이(기본값: None)
  • 기본값으로 설정하면 완벽히 분류될 때 까지 분할하거나, 노드가 갖는 샘플 개수가 min_samples_split 설 정 값 보다 작아질 때 까지 계속 분할
  • 계속 분할되면 트리 깊이가 너무 깊어져 과적합이 발생할 수 있으니 적절한 값 설정 필요

min_samples_split

  • 노드를 분할하기 위한 최소한의 샘플 개수(기본값: 2)
  • 값을 작게 설정할 수록 계속 분할되어 트리 깊이가 깊어져 과적합 발생 가능
  • 적절한 값을 지정해 과적합을 방지할 필요가 있음

min_samples_leaf

  • 리프 노드가 되기 위한 최소한의 샘플 수(기본값: 1)
  • min_samples_split과 함께 과적합을 방지할 목적으로 사용
  • 불균형 클래스인 경우 이를 고려하여 작은 값을 설정할 필요가 있음

max_feature

  • 최선의 분할을 위해 고려할 Feature 수(기본값: None)
  • 기본값으로 설정하면 모든 Feature를 사용해서 분할 수행
  • 정수형으로 선언하면 Feature 수, 실수형으로 선언하면 Feature 비율
  • 'sqrt'로 선언하면 전체 Feature 수의 루트 값
  • 'auto'로 설정하면 'sqrt'와 같은 의미
  • 'log'로 선언하면 log2(전체 Feature 수

max_leaf_node

  • 리프 노드 최대 개수

 

Logistic Regression

  • 알고리즘은 분류모델에만 사용할 수 있음
  • 알고리즘 함수: sklearn.linear_model.LogisticRegression
  • 성능평가 함수: sklearn.metrics.confusion_matrix, sklearn.metrics.classification_report 등

 

로지스틱 함수

  • 시그모이드(sigmoid) 함수라고도 부름
  • 확률 값 𝑝 는 선형 판별식 값이 커지면 1, 작아지면 0에 가까운 값이 됨
  • (-∞, ∞) 범위를 갖는 선형 판별식 결과로 (0, 1) 범위의 확률 값을 얻게 됨
  • 기본적으로 확률 값 0.5를 임계값(Threshold)로 하여 이보다 크면 1, 아니면 0으로 분류함
  • 𝑥 데이터가 주어졌을 때 확률을 예측하는 로지스틱 회귀분석은 학습 데이터를 잘 설명하는 선형 판별식의 기울기(𝑎)와 절편(𝑏)을 찾는 문제
  • from sklearn.linear_model import LogisticRegression

K-Fold Cross Validation

  • 모든 데이터가 평가에 한 번, 학습에 k-1번 사용
  • K개의 분할(Fold)에 대한 성능을 예측 → 평균과 표준편차 계산 → 일반화 성능
  • 단, k는 2 이상이 되어야 함(최소한 한 개씩의 학습용, 검증용 데이터가 필요)

장점

  • 모든 데이터를 학습과 평가에 사용할 수 있음
  • 반복 학습과 평가를 통해 정확도를 향상시킬 수 있음
  • 데이터가 부족해서 발생하는 과소적합 문제를 방지할 수 있음
  • 평가에 사용되는 데이터의 편향을 막을 수 있음 
  • 좀 더 일반화된 모델을 만들 수 있음 

단점 

  • 반복 횟수가 많아서 모델 학습과 평가에 많은 시간이 소요

Hyperparameter 튜닝

Random Search

  1. 성능을 테스트할 파라미터 값의 범위를 지정(딕셔너리 형태)
  2. 위 파라미터 값 범위를 모두 사용하는 Grid Search 모델 선언 후 학습
  3. 학습 데이터에 대해 가장 좋은 성능을 보인 파라미터 값으로 자동으로 학습함
  4. 이후 예측 및 평가 과정을 바로 진행하면 됨
# 함수 불러오기
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import RandomizedSearchCV

# 파라미터 선언
param = {'n_neighbors': range(1, 500, 10), 'metric': ['euclidean', 'manhattan']}
# 기본모델 선언
knn_model = KNeighborsClassifier()
# Random Search 선언
model = RandomizedSearchCV(knn_model, param, cv=3, n_iter=20)

# 학습하기
model.fit(x_train, y_train)
# 수행 정보
model.cv_results_
# 최적 파라미터
model.best_params_
# 최고 성능
model.best_score_

 

Grid Search

  1. 성능을 테스트할 파라미터 값의 범위를 지정(딕셔너리 형태)
  2. 위 파라미터 값 범위에서 몇 개 선택할 지 정하여 Random Search 모델 선언 후 학습
  3. 학습 데이터에 대해 가장 좋은 성능을 보인 파라미터 값으로 자동으로 학습함
  4. 이후 예측 및 평가 과정을 바로 진행하면 됨
# 함수 불러오기
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
# 파라미터 선언
param = {'n_neighbors': range(1, 500, 10), 'metric': ['euclidean', 'manhattan']}
# 기본모델 선언
knn_model = KNeighborsClassifier()
# Grid Search 선언
model = GridSearchCV(knn_model, param, cv=3)

 

 

회귀

  • 비용 함수 : MSE(표준편차?)
  • 마지막 노드에 있는 샘플들의 평균을 예측값으로 반환

 

앙상블(Ensemble)

여러 개의 모델을 결합하여 훨씬 강력한 모델을 생성하는 기법

 

보팅(Voting)

  • 여러 모델들(다른 유형의 알고리즘 기반 )의 예측 결과투표를 통해 최종 예측 결과를 결정하는 방법
  • 하드 보팅: 다수 모델이 예측한 값이 최종 결괏값
  • 소프트 보팅: 모든 모델이 예측한 레이블 값의 결정 확률 평균을 구한 뒤 가장 확률이 높은 값을 최종 선택

배깅(Bagging)

  • Bootstrap Aggregating의 약자
  • 데이터로부터 부트스트랩 한 데이터로 모델들을 학습시킨 후, 모델들의 예측 결과를 집계해 최종 결과를 얻는 방법
  • 같은 유형의 알고리즘 기반 모델들을 사용
  • 데이터 분할 시 중복을 허용(복원 랜덤 샘플링 방식이라고 함)
  • 범주형 데이터(Categorical Data)는 투표 방식(Voting)으로 결과를 집계
  • 연속형 데이터(Continuous Data)는 평균으로 결과를 집계
  • 대표적인 배깅 알고리즘: Random Forest
    •  

부스팅(Boosting)

  • 같은 유형의 알고리즘 기반 모델 여러 개에 대해 순차적으로 학습을 수행
  • 이전 모델이 제대로 예측하지 못한 데이터에 대해서 가중치를 부여하여 다음 모델이 학습과 예측을 진행하는 방법
  • 계속하여 모델에게 가중치를 부스팅하며 학습을 진행해 부스팅 방식이라 함
  • 예측 성능이 뛰어나 앙상블 학습을 주도함
  • 배깅에 비해 성능이 좋지만, 속도가 느리고 과적합 발생 가능성이 있음 → 상황에 맞게 적절히 사용해야 함
  • 대표적인 부스팅 알고리즘: XGBoost, LightGBM

스태킹(Stacking)

'<프로그래밍> > [python]' 카테고리의 다른 글

[python] 딥러닝 성능관리  (0) 2024.10.14
[python] 딥러닝 기초  (0) 2024.10.10
[python] 머신러닝의 기초2  (1) 2024.09.27
[python] 머신러닝의 기초  (0) 2024.09.26
[python] 데이터 시각화2(단변량 분석)  (1) 2024.09.26

평가지표

 

성능평가

분류 모델 평가

  • 분류 모델은 0인지 1인지를 예측하는 것
  • 실제 값도 0과 1이고 예측 값도 0과 1임
  • 하지만 0을 1로 예측하거나 1을 0으로 예측할 수 있음
  • 예측 값이 실제 값과 많이 같을 수록 좋은 모델이라 할 수 있음  → 정확히 예측한 비율로 모델 성능을 평가

 

오분류표(Confusion Matrix)

  • TN(True Negative, 진음성): 음성으로 잘 예측한 것(음성을 음성이라고 예측한 것)
  • FP(False Positive, 위양성): 양성으로 잘 못 예측한 것(음성을 양성이라고 예측한 것)
  • FN(False Negative, 위음성): 음성으로 잘 못 예측한 것(양성을 음성이라고 예측한 것)
  • TP(True Positive, 진양성): 양성으로 잘 예측한 것(양성을 양성이라고 예측한 것)



정확도(Accuracy) - 1과 0을 정확히 예측한 비율

  • 정분류율 이라고 부르기도 함
  • 전체 중에서 Positive와 Negative 로 정확히 예측한(TN + TP) 비율 
  • Negative를 Negative로 예측한 경우도 옳은 예측임을 고려하는 평가지표
  • 가장 직관적으로 모델 성능을 확인할 수 있는 평가지표
  • from sklearn.metrics import accuracy_score
  • accuracy_score(y_test, y_pred)

 

정밀도(Precision) - 1이라 예측한 것 중에서 정말 1인 비율

  • Positive로 예측한 것(FP + TP) 중에서 실제 Positive(TP)인 비율
  • 예) 비가 내릴 것으로 예측한 날 중에서 실제 비가 내린 날의 비율
  • 예) 암이라 예측한 환자 중에서 실제 암인 환자의 비율
  • 정밀도가 낮을 경우 발생하는 상황
    • 비가 오지 않는데 비가 온다고 했으니 불필요한 우산을 챙기는 수고 발생
    • 암이 아닌데 암이라 했으니 불필요한 치료 발생
  • from sklearn.metrics import precision_score
  • precision_score(y_test, y_pred, average = None) - average는 생략가능 하지만 추천하지는 않음
    • average = [ 'binary' - 기본값 / 'macro' - 정밀도 평균 / 'weighted' - 정밀도 가중치 평균 ]

 

재현율(Recall) - 실제 1인 것을 1이라고 예측한 비율

  • 실제 Positive(FN + TP) 중에서 Positive로 예측한(TP) 비율
  • 민감도(Sensitivity)라고 부르는 경우가 많음 
  • 예) 실제 비가 내린 날 중에서 비가 내릴 것으로 예측한 날의 비율
  • 예) 실제 암인 환자 중에서 암이라고 예측한 환자의 비율
  • 재현율이 낮을 경우 발생하는 문제
    • 비가 내리는 날 내리지 않을 것이라 했으니 우산을 챙기지 않아 비를 맞음
    • 암인 사람에게 암이 아니라 했으니 심각한 결과 초래
  • from sklearn.metrics import recall_score
  • recall_score(y_test, y_pred, average = None)

특이도(Specificity) - 실제 Negative(TN + FP) 중에서 Negative로 예측한(TN) 비율

  • 예) 실제 비가 내리지 않은 날 중에서 비가 내리지 않을 것으로 예측한 날의 비율
  • 예) 실제 암이 아닌 환자 중에서 암이 아니라고 예측한 환자의 비율
  • 특이도가 낮을 경우 발생하는 문제
    • 비가 오지 않는데 비가 온다고 했으니 불필요한 우산을 챙기는 수고 발생
    • 암이 아닌데 암이라 했으니 불필요한 치료 발생

정밀도가 높으면 재현율이 낮을 수 있다.

 

F1-Score - 정밀도와 재현율의 조화 평균

  • 분자가 같지만 분모가 다를 경우, 즉 관점이 다른 경우 조화 평균이 큰 의미를 가짐
  • 정밀도와 재현율이 적절하게 요구 될 때 사용
  • from sklearn.metrics import f1_score
  • f1_score(y_test, y_pred, average = None)

 

이중 분류 성능 평가★

  • from sklearn.metrics import classification_report, confusion_matrix
  • confusion_matrix (y_test, y_pred) - 구조 확인 가능
  • classification_report(y_test, y_pred) - 모든 지표를 확인 가능

 

분류모델 머신러닝 예제

선언 및 데이터 읽어오기

# 라이브러리 불러오기
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'

# 데이터 읽어오기
path = 'https://raw.githubusercontent.com/Jangrae/csv/master/admission_simple.csv'
data = pd.read_csv(path)

 

데이터 확인

  • data.head()
  • data.tail()
  • data.info()
  • data.describe()
  • data.corr(numeric_only=True).style.background_gradient()

x와 y 분리

# target 확인
target = 'ADMIT'

# 데이터 분리
x = data.drop(target, axis=1)
y = data.loc[:, target]

# 모듈 불러오기
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 )

 

모델링

# 1단계: 불러오기
from sklearn.neighbors import KNeighborsClassifier

# 2단계: 선언하기
model = KNeighborsClassifier()

# 3단계: 학습하기
model.fit(x_train, y_train)

# 4단계: 예측하기
y_pred = model.predict(x_test)

 

분류 성능 평가

# 모듈 불러오기
from sklearn.metrics import confusion_matrix

# 성능 평가
print(confusion_matrix(y_test, y_pred))

plt.figure(figsize = (5, 2))
sns.heatmap(confusion_matrix(y_test, y_pred),
           annot = True, cbar = False, cmap = 'Purples',
           annot_kws = {'size' : 16})

plt.show()

# 모듈 불러오기
from sklearn.metrics import classification_report

# 성능 평가
print(classification_report(y_test, y_pred))
  • Accuracy
    • from sklearn.metrics import accuracy_score
    • print('정확도(Accuracy) =', accuracy_score(y_test, y_pred))
  • Precision  
    • from sklearn.metrics import precision_score
    • print('정밀도(Precision) =', precision_score(y_test, y_pred, average = None)) # 권고  
  • Recall
    • from sklearn.metrics import recall_score
    • print('재현율(Recall) =', recall_score(y_test, y_pred, average = None)
  • F1-Score
    • from sklearn.metrics import f1_score
    • print('F1_score) =', f1_score(y_test, y_pred, average = None))

 

회귀 모델 평가

  • 회귀 모델이 정확한 값을 예측하기는 사실상 어려움
  • 예측 값과 실제 값에 차이(=오차)가 존재할 것이라 예상
  • 예측 값이 실제 값에 가까울 수록 좋은 모델이라 할 수 있음 → 예측한 값과 실제 값의 차이(=오차)로 모델 성능을 평가

 

𝑦 : 실젯값

  • 우리가 실제로 예측하고 싶은 값, Target, 목푯값
  • 실제값과 비교해 모델의 성능을 평가
  • 우리가 관심을 갖는 오차는 이 값과 예측값의 차이

ȳ : 평균값

  • 이미 알고 있는, 이미 존재하고 있는 평균으로 예측한 값
  • 최소한 이 평균값 보다는 실젯값에 가까운 예측값을 원함
  • 우리 모델의 예측값이 평균값보다 오차를 얼마나 더 줄였는지 확인

y^ : 예측값

  • 우리 모델로 새롭게 예측한 값
  • 이 예측값이 얼마나 정확한지 알고 싶은 상황
  • 최소한, 평균값 보다는 좋아야 의미가 있음
  • 우리 모델이 평균값보다 얼마나 잘 예측했을지 검증

 

오차 합 구하기

오차 제곱의 합

  • SSE(Sum Squared Error) - 제곱해서 더함
  • MSE(Mean squared Error) - 제곱해서 더한것을 n(행수)으로 나눔 / 손실함수
  • RMSE(Root MSE) - MSE에 루트를 씌움 

 

오차 절대값의 합

  • MAE(Mean Absolute Error) - 오차의 절대값으로 더하고 n으로 나눔
  • MAPE(Mean Absolute Percentage Error) - 절대값의 합을 y로 나누어 퍼센테이지로 구함

 

 

 

  • SST(Sum Squared Total) - 전체 오차(최소한 평균 보다는 성능이 좋아야 하니, 우리에게 허용된(?) 오차)
    • 실제값과 평균값의 오차를 제곱
  • SSR(Sum Squared Regression) - 전체 오차 중에서 회귀식이 잡아낸 오차 (우리가 해결한 것 / 클수록 좋음)
    • 예측값과 평균값의 오차를 제곱
  • SSE(Sum Squared Error) - 전체 오차 중에서 회귀식이 여전히 잡아내지 못한 오차
    • 예측값과 실제값의 오차를 제곱
  • SST = SSR + SSE

결정계수 R^2 (R-Squared)

  • 모델 성능을 잘 해석하기 위해서 만든 MSE의 표준화된 버전이 결정 계수
  • 전체 오차 중에서 회귀식이 잡아낸 오차 비율(일반적으로 0 ~ 1 사이)
  • 오차의 비 또는 설명력이라고도 부름
  • 𝑅 2 = 1이면 𝑀𝑆𝐸 = 0이고 모델이 데이터를 완벽하게 학습한 것

 

회귀모델 머신러닝 예제

선언 및 데이터 읽어오기

# 라이브러리 불러오기
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'

# 데이터 읽어오기
path = 'https://raw.githubusercontent.com/Jangrae/csv/master/airquality_simple.csv'
data = pd.read_csv(path)

 

데이터 확인

  • data.head()
  • data.tail()
  • data.info()
  • data.describe()
  • data.corr(numeric_only=True).style.background_gradient()

전처리 - 결측치 처리, 변수 제

# 결측치 확인
data.isnull().sum()
Ozone      0
Solar.R    7
Wind       0
Temp       0
Month      0
Day        0
dtype: int64
# 전날 값으로 결측치 채우기
#data.fillna(method='ffill', inplace=True)
data.ffill(inplace = True)
# 확인
data.isnull().sum()
Ozone      0
Solar.R    0
Wind       0
Temp       0
Month      0
Day        0
dtype: int64

 

# 변수 제거
drop_cols = ['Month', 'Day']
# data.drop(drop_cols, axis=1, inplace=True)
data.drop(columns = drop_cols, inplace=True)
# 확인
data.head(1)

x와 y 분리

# target 확인
target = 'Ozone'

# 데이터 분리
x = data.drop(target, axis=1)
y = data.loc[:, target]

# 모듈 불러오기
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)
# stratify=y를 활용하면 일정한 기준으로 나뉘어진 y값으로 분리됨
  • stratify=y를 활용하면 일정한 기준으로 나뉘어진 y값으로 분리됨

모델링

# 1단계: 불러오기
from sklearn.linear_model import LinearRegression

# 2단계: 선언하기
model = LinearRegression()

# 3단계: 학습하기
model.fit(x_train, y_train)

# 4단계: 예측하기
y_pred = model.predict(x_test)

 

회귀 성능 평가

# 모듈 불러오기
from sklearn.metrics import mean_absolute_error

# 성능 평가
print('MAE =', mean_absolute_error(y_test, y_pred))
MAE = 13.976843190385708

 

  • MAE(Mean Absolute Error)
    • from sklearn.metrics import mean_absolute_error
    • print('MAE =', mean_absolute_error(y_test, y_pred))
  • MSE(Mean Squared Error)
    • from sklearn.metrics import mean_squared_error
    • print('MSE =', mean_squared_error(y_test, y_pred))
  • RMSE(Root Mean Squared Error)  
    • from sklearn.metrics import root_mean_squared_error
    • print('RMSE =', root_mean_squared_error(y_test, y_pred))
  • MAPE(Mean Absolute Percentage Error)
    • from sklearn.metrics import mean_absolute_percentage_error
    • print('MAPE =', mean_absolute_percentage_error(y_test, y_pred))
  • R2-Score
    • from sklearn.metrics import r2_score
    • print('R2 =', r2_score(y_test, y_pred))

머신러닝 개념과 관련 용어

 

머신러닝 이해

인간의 개념머신의 데이터이다.

우리가 일정한 패턴을 통해 스스로 학습하는 과정을 컴퓨터에 적용했다고 비유할 수 있다.

간단한 패턴이라면 사람의 두뇌로 해결할 수 있지만, 복잡한 패턴을 일일히 분석하는건 힘들고 비효율적인 일이다.

 

문제 해결 순서

  • 문제의 유형을 파악 > 알고리즘과 평가 방법을 선택 > 관련 함수를 사용해 모델링

지도학습

  • 학습 대상이 되는 데이터에 정답을 준다.
  • 규칙성, 즉 데이터의 패턴을 배우게 하는 학습 방법이다.
  • 분류문제
    • 적절히 분류된 데이터를 학습하여 분류 규칙을 찾는다.
    • 규칙을 기반으로 새롭게 주어진 데이터를 적절히 분류하는것이 목적이다.
    • 범주형 자료
    • A일까? B일까 고민하는 문제
  • 회귀문제
    • 결과값이 있는 데이터를 학습하여 입력 값과 결과 값의 연관성을 찾는다.
    • 연관성을 기반으로 새롭게 주어진 데이터에 대한 값을 예측하는것이 목적이다.
    • 숫자형 자료 - 연속적인 숫자 예측
      • 두 값 사이에 중간값이 의미가 있는가?
      • 두 값에 대한 연산 결과가 의미있는 숫자인가?
    • 얼마나 많이? 라고 질문을 던질 수 있는 문제

비지도 학습

  • 정답이 없는 데이터 만으로 배우게 하는 학습 방법
  • 클러스터링
    • 데이터를 학습하여 적절한 분류 규칙을 찾아 데이터를 분류하는 것이 목적.
    • 정답이 없으니 성능을 평가하기 어렵다.
  • 군집화 - 비슷한것을 그룹으로 묶음
  • 변환 - 쉽게 이해할 수 있는 형태로 데이터 표현
  • 연관 - 서로 연관된 특징을 찾음

강화 학습

  • 선택한 결과에 배해 보상을 받아 행동을 개선하면서 배우게 하는 학습 방법

 

용어정리

모델(model)

  • 데이터로부터 패턴을 찾아 수학식으로 정리해 놓는것
  • 모델링(Modeling): 오차가 적은 모델을 만드는 과정

모델의 목적( 모델을 만드는 과정 -> 모델링)

  • 샘플을 가지고 전체를 추정
    • 샘플: 표본, 부분집합, 일부, 과거의 데이터
    • 전체: 모집단, 전체집합, 현재와 미래의 데이터
    • 추정: 예측, 추론

독립변수(원인), 종속변수(결과)

  • x값이 변함에 따라 y값이 변한다. 라고 할때
  • 독립변수를 x, 종속변수를 y로 표시함 ex) y = ax + b

평균과 오차

  • 통계학에서 사용되는 가장 단순한 모델 중 하나가 평균이다.
  • 관측값(=실젯값)과 모델 예측값의 차이: 이탈도(Deviance) → 오차
  • 범주에서는 최빈값(가장 많이 나온 값)으로 예측할 수 있다.

데이터 분리

  • 데이터 셋을 학습용 검증용 평가용 데이터로 분리함
  • 실전에서 평가용 데이터는 별도로 제공되는 데이터일 경우가 많다.
  • 검증용 데이터로 평가 전에 모델 성능을 검증해 볼 수 있다.(튜닝시 사용)
  • x(독립변수)와 y(종속변수)를 분리 - DF의 열을 분리 : DF.drop(열이름, axis = 1) / DF.loc[ ]
  • 학습용, 편가용 분리 - DF의 행을 분리 : train_test_split(x, y, test_size = float) : size의 최대크기는 1

과대적합과 과소적합

  • 과대적합(Overfitting)
    • 학습 데이터에 대해서는 성능이 매우 좋은데, 평가 데이터에 대해서는 성능이 매우 좋지 않은 경우
    • 학습 데이터에 대해서만 잘 맞는 모델 실전에서 예측 성능이 좋지 않음
  • 과소적합(Underfitting)
    • 학습 데이터보다 평가 데이터에 대한 성능이 매우 좋거나, 모든 데이터에 대한 성능이 매우 안 좋은 경우
    • 모델이 너무 단순하여 학습 데이터에 대해 적절히 훈련되지 않은 경우

 

모델링 코드 구조

Scikit-Learn(사이킷런)

불러오기 - 사용할 알고리즘과 평가를 위한 함수 import

 

1. 알고리즘

  • from sklearn.linear_model import LinearRegression - 회귀
  • from sklearn.neighbors import KNeighborsClassifier - 분류 (0, 1로 분류)
  • from sklearn.tree import DecisionTreeClassifier - 분류 (str 형태의 분류)

2. 평가 

  • from sklearn.metrics import mean_absolute_error -  회귀  
  • from sklearn.metrics import accuracy_score - 분류 

3. 선언하기 - 사용할 알고리즘용 함수로 모델 선언

  • model = LinearRegression()  -  회귀
  • model =  KNeighborsClassifier() - 분류 
  • model =  DecisionTreeClassifier() - 분류 

4. 학습하기 - 모델.fit(x_train, y_train) 형태로 모델 학습 시키기

  • model.fit(x_train, y_train)

5. 예측하기 - 모델.predict(x_test) 형태로 예측한 결과 변수로 저장

  • y_pred = model.predict(x_test)

6. 평가하기 - 실젯값과 예측값을 평가 함수에 전달해 성능 평가

  • mean_absolute_error( y_test, y_pred )
  • mean_absolute_error( y_test, y_mean )
    • y_mean = [ y_train.mean() ] * len(y_test) - 평균값으로 Base Model을 만들어 기본오차를 구함 -회귀
  • mean_absolute_error( y_test, y_freq )
    • y_freq = [ y_train.mode()[0] ] * len(y_test) - 최빈값으로 Base Model을 만들어 기본오차를 구함 -분류

 

모델링 예제

자료준비

# 라이브러리 불러오기
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'

# 데이터 읽어오기
path = 'https://raw.githubusercontent.com/Jangrae/csv/master/airquality_simple.csv'
data = pd.read_csv(path)

 

데이터 구조 확인

data.tail(2)

 

변수확인 - Solar.R에 결측치가 존재함을 확인

# 변수 확인 #결측치 확인 Solar.R
data.info()

 

통계 확인

# 기술통계 확인
data.describe().T

 

상관 관계 분석 및 시각화

# 상관관계 확인
data.corr(numeric_only = True).style.background_gradient()
# 상관관계 시각화 Purples
sns.heatmap(data.corr(numeric_only = True), 
            annot = True, cmap = 'Blues', 
            cbar = False, square = True,
           fmt = '.3f', annot_kws = {'size' : 8})
plt.yticks(rotation = 0) #y측 
plt.show()

 

데이터 전처리

결측치 처리

# 결측치 확인
data.isna().sum()

# 위에값으로 결측치 채우기 / 아래값, bfill()
data['Solar.R'] = data['Solar.R'].ffill()
# data.ffill(inplace = True)
# 확인
data.isna().sum()

변수 제거

# 분석에 의미 없는변수 제거
drop_cols = ['Month', 'Day']
data.drop(columns = drop_cols, inplace = True)
# 확인
data.head(1)

x, y, 분리

알아내고자 하는것 = target = 오존 농도

# target 확인
target = 'Ozone'

# 데이터 분리
x = data.drop(target, axis = 1) #( columns = target)
y = data.loc[ :, target] #data['Ozone']

 

머신러닝을 위한 변수 생성

# 모듈 불러오기
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)
#random_state = n 으로 같은 random값을 준다면 같은 결과를 줌 seed와 같은 원리
#만약 회귀가 아닌 분류라면stratify = y 를 활용하여 일정한 데이터로 분리

 

모델링

# 1단계: 불러오기
from sklearn.linear_model import LinearRegression #회귀
from sklearn.metrics import mean_absolute_error

# 2단계: 선언하기
model = LinearRegression()

# 3단계: 학습하기
model.fit(x_train, y_train)

# 4단계: 예측하기
y_pred = model.predict(x_test)

# 5단계: 평가하기
mean_absolute_error(y_test, y_pred)
13.976843190385708

 

예측값과 실제값 비교 / 시각화

# 예측값과 실젯값 시각화 비교

print('실제값 :',y_test.values[:10])
print('예측값 :',y_pred[:10])
실제값 : [24 18 97 47 34 22 66 18 69 27]
예측값 : [13.84003067  5.82919112 81.93563027 58.41267418 50.86150737 31.52971121
 66.8083547  -8.56411529 50.2136544  39.13346172]

 

기본모델 오차와 비교

#기본 모델(Base Model) 오차
# 평가 데이터 행수 만큼 평균값 준비
y_mean = [y_train.mean()] * len(y_test)
print("MAE = ", mean_absolute_error(y_test, y_mean))

 

plot

plt.figure(figsize = (14, 4))
plt.plot(y_test.values, label = 'Actual')
plt.plot(y_pred, label = 'Predicted')
#plt.legend(['Actual', 'Predicted'])
plt.legend()
plt.show()

 

 

Graphvis

그래프를 좀더 시각적으로 좋게 볼 수 있다.

 

Graphvis > Downlod > 각자 환경에 맞는 버전 선택 > 기본 설정으로 설치 

 

설치 후 설정

내pc > 속성 > 고급시스템 설정

 

 

환경변서 > path > 편집 > 찾아보기

 

C드라이브 > Program Files >  Graphviz > bin 선택후 확인

시스템 변수도 마찬자기로 진행 > 재부팅

숫자형 변수

기초 통계량

  • 평균(mean)
  • 중앙값(median)
  • 최빈값(mode)
  • 사분위수(Quantile)
    • 데이터를 정렬(오름차순)
    • 전체를 4등분하고 각 분위는 결계의 값( 25%, 50%, 75%) 을 의미
    • ( 25%, 50%, 75%) 를 각각 1사분위수, 2사분위수, 3사분위수 라고 부름
    • DF.describe()를 통해 전체적으로 파악 가능
  • Box plot을 활용하여 데이터 분석 가능
  • Box Plot
    • plt.boxplot( DF['열 이름'] )
    • vert = 횡(False), 종(True, 기본값)
    • 사전에 반드시 NaN을 제외(sns.boxplot 은 NaN을 알아서 제거해 줌)
    • 수염 - 박스 -수염 의 형태를 가지고 있다.
    • 사분위수를 확인 가능
    • IQR > Q1(1사분위수) 에서 Q3(3사분위수) 까지의 길
    • 1.5*IQR 범위 이내의 최소, 최대값으로 결정

 

도수분포 (frequency table)

  • Histogram
    • plt.hist(DF.열이름, bins = 구간 수) / plt.hist(x = 열이름, data = DF, bins = 구간 수) - 그림1
    • edgecolor = bar의 윤곽선을 색으로 표시 ex) 'gray'
    • x, y 라벨이 없음으로 직접 지정
    • plt.xlabel('str') / plt.ylabel('str')
    • 밀집구간과 희박구간을 확인하고 비즈니스 의미를 파악
    • 단점 - 구간(bin)의 너비에 따라 모양이 달라지며 의미가 다르게 해석
    • sns.histplot(DF['열 이름'], bins = 구간수)
      • kde = True로 설정하면 kde도 같이 출력 - 그림2

그림1 / 그림2

  • Density plot(KDE)
    • sns.kdeplot(DF['열 이름'])
    • 데이터의 밀도 추정 - 측정된(관측된) 데이터로부터 전체 데이터 분포의 특성을 추정
    • 면적으로 구간에 대한 확률 추정

범주형 변수

 

범주형 데이터는 법주별 빈도수 / 범주별 비율 등으로 데이터를 가공해야된다.

  • 범주별 빈도수  - DF['열 이름'].value_counts() / 시리즈.value_counts()
  • 범주별 비율  - DF['열 이름'].value_counts(normalize = True) 
  • sns.countplot( DF['열 이름'] )
    • 알아서 범주 별 빈도수가 계산되고  bar plot으로 그려짐.
    • plt.bar( DF['열 이름'] )를 활용하려변 직접 범주별 빈도수를 계산해야 됨

 

  • plt.pie(시리즈.values, labels = 시리즈.index , autopct = '%/2f%%')  -  시리즈의 values, index를 기준으로한 원형 차트 생성, autopct = '%/2f%%'는 소수점 2자리까지 나타내게 함.
    • 시리즈 = DF['열 이름']
    • startangle = n :  차트를 n도 회전
    • counterclock = True/False : False = 시계 방향으로
    • explode = [0.05, 0.05, 0.05] : 중심으로 부터 각 차트요소(n개)를 얼마만큼 띄울지 지정
    • shadow = True : 그림자 추가

부동산웹에서 위도 경도를 활용해 geohash를 구하고 이를 활용해 매물id, 매물 정보를 가져와보자.

Z부동산 웹 > 원룸을 선택 > F12 개발자도구 >  Network > Fetch/XHR > 클리어 해주기 > 망원동 입력 > 망원동 클릭

위에 방식이 이해가 가지 않는다면 Web과 Web Scarping / Crawling1과 2를 보고오길 추천한다.

 

다음과 같이 검색 결과 Preview에서 lat, lng(위도, 경도)값을 확인하였다.

다음 Preview 에서 itemID, lat, lng를 확인할 수 있다. 

 

list에서는 POST방식으로 데이터를 response한 것을 확인하였다. 그리고 itemId가 저장되어있다.

Preview를 확인해보니 원룸에 대한 정보가 나와있는 것을 확인하였다.

 

마지막으로 geohash값을 확인해주고 데이터를 수집할 준비를 마쳤다.

geohach는 위도 경도값(점)에서 어느정도까지 떨어져있는지 나타내는 값이다.

 

위도, 경도값 > geohash값 > itemId, lat, lng > list안에 itemId 조회 > 데이터 수집

다음가 같은 과정을 통해 데이터를 수집해보자.

 

동이름으로 위도, 경도 구하기

다음 검색기록을 확인하여 request URL을 확인한다.

 

다음 url은 한글데이터를 숫자와 특수기호를 통해 전달하기 편한 형태로 되어있다.

url을 구하기 위해서는 아래 디코딩 사이트의 디코딩을 활용하여 사용가능한 url로 변환해주자.

 

URL Decoder/Encoder

 

meyerweb.com

 

Request Method가 GET방식임으로 requests.get()을 활용한다.

import requests
import pandas as pd


addr = '망원동'
url = f'https://apis.zigbang.com/v2/search?leaseYn=N&q={addr}&serviceType=원룸'
response = requests.get(url)
data = response.json()['items'][0]
lat, lng = data['lat'], data['lng']
lat, lng
(37.556785583496094, 126.9013442993164)

 

 

위도 경도로 geohash알아내기

얻은 url을 활용해 다음과 같이 lat과 lng을 구했다면 geohash2를 활용해 geohash를 구해보자

!pip install geohash2

우선 geohash2를 install해주자. 시간이 좀 걸릴 수 있다.

다음 코드를 활용해 geohash를 구해준다.

import geohash2
geohash = geohash2.encode(lat, lng, precision = 5)
geohash
  • wydjx

 

geohash로 매물 아이디 가져오기

마찬가지로 request URL을 확인하고 이를 디코딩해준다.

GET방식으로 response해야된다는 것을 확인하였다.

 

코드를 쓰면서 response를 찍어보고 데이터 구조를 파악하길 바란다. 그리고 왜 item_ids를 리스트 컴프리헨션을

사용해 짜게 되었는지 이해하길 바란다.

url = f'https://apis.zigbang.com/v2/items/oneroom?geohash={geohash}&depositMin=0&rentMin=0&salesTypes[0]=전세&salesTypes[1]=월세&domain=zigbang&checkAnyItemWithoutFilter=true'
response = requests.get(url)
item_ids = [data['itemId'] for data in response.json()['items']]
len(item_ids), item_ids[:5]
(372, [42196796, 42078100, 42149571, 42184803, 42204685])

 

매물 아이디로 매물 정보 가져오기

마지막은 POST방식으로 진행되었다.

url = 'https://apis.zigbang.com/v2/items/list'
params = {'domain': "zigbang", 'item_ids': item_ids}
response = requests.post(url, params)
response
<Response [200]>
data = response.json()['items']
df = pd.DataFrame(data)
df = df[df['address1'].str.contains(addr)].reset_index(drop=True)
df = df[['item_id','sales_title', 'deposit', 'rent', 'size_m2', 'floor', 'building_floor', 'title', 'address1']]
df.tail(2)

 

하나의 함수로 만들기

 

#5. functjon
def oneroom(addr):
    url = f'https://apis.zigbang.com/v2/search?leaseYn=N&q={addr}&serviceType=원룸'
    response = requests.get(url)
    data = response.json()['items'][0]
    lat, lng = data['lat'], data['lng']
    
    geohash = geohash2.encode(lat, lng, precision = 5)
    
    url = f'https://apis.zigbang.com/v2/items/oneroom?geohash={geohash}&depositMin=0&rentMin=0&salesTypes[0]=전세&salesTypes[1]=월세&domain=zigbang&checkAnyItemWithoutFilter=true'
    response = requests.get(url)
    item_ids = [data['itemId'] for data in response.json()['items']]
    
    url = 'https://apis.zigbang.com/v2/items/list'
    params = {'domain': "zigbang", 'item_ids': item_ids}
    response = requests.post(url, params)
    data = response.json()['items']
    df = pd.DataFrame(data)
    df = df[df['address1'].str.contains(addr)].reset_index(drop=True)
    return df[['item_id','sales_title', 'deposit', 'rent', 'size_m2', 'floor', 'building_floor', 'title', 'address1']]
    
df = oneroom('망원동')
df.tail(2)

'<프로그래밍> > [python-WebCrawling]' 카테고리의 다른 글

Web Crawling5  (0) 2024.09.23
Web과 Web Scarping / Crawling 2(NAVER API)  (1) 2024.09.21
Web과 Web Scraping / Crawling 1  (1) 2024.09.19

네이버 > 증권 > 리서치 > 종목분석 리포트

 

정적페이지인것을 확인

1page에서 새로고침으로 확인

 

 

ctrl+F로 원하는 데이터가 있는지 확인

 

 

우클릭

 

아래 둘이 다름

 

 

ctrl+F로 [ "128. ]을 검색 > 있는것을 확인 > [ "129. ]를 검색하고 바로 위에 있는 128버전을(가장 최신) 확인한다.

 

주소창에 붙여넣으면 다운 완료됨 > 그다음 exe파일만 폴더로 가져오기

 

 

 

 

 

 

 

------------------------------

 

 

다음 > 뉴스 > 

 

+ Recent posts