블로그 이미지
Flying Mr.Cheon youGom

Recent Comment»

Recent Post»

Recent Trackback»

« 2025/7 »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

 
 

딥러닝을 위한 고급도구

데이터사이언스/Keras로 | 2020. 5. 7. 15:18 | Posted by youGom

 

7.1 Sequential 모델을 넘어서: 케라스의 함수형 API

 
Sequential
 
 
 
 
input
output
Sequential 모델: 차례대로 쌓은 층

이 책에서는 지금까지 위의 모델을 이용해서만 문제를 해결했습니다. 이런 가정은 많은 문제에 적용할 수 있지만, 아닌 경우도 존재합니다.

일부 네트워크는 개별 입력이 여러 개 필요하거나 출력이 여러 개 필요합니다. 층을 차례대로 쌓지 않고 층 사이를 연결하여 그래프처럼 만드는 네트워크도 있습니다.

예를 들어 어떤 작업은 다양한 종류의 입력이 필요합니다. 다양한 입력 소스에서 전달된 데이터를 다른 종류의 신경망 층을 사용하여 처리하고 합칩니다. 다음과 같은 모델이 만들어질 수 있는 것입니다.

 
 
 
 
 
 
 
모듈 병합
가격 예측
완전 연결 데이터
RNN 모듈
컨브넷 모듈
메타데이터
텍스트 설명
사진
다중 입력 모델

또한 다중 출력 모델도 가능합니다.

 
 
 
 
 
소설 텍스트
텍스트 처리 모듈
장르를 위한 분류 모델
시대를 위한 회귀 모델
장르
시대
다중 출력 모델

최근에 개발된 많은 신경망 구조는 선형적이지 않은 네트워크 토폴로지가 필요합니다. 비순환 유향 그래프(DAG) 같은 네트워크 구조입니다. 인셉션 모듈을 사용하는 인셉션 계열의 네트워크가 그 예시입니다. 이 모듈은 나란히 놓인 여러개의 합성곱 층을 거쳐 하나의 텐서로 출력이 합쳐집니다.

 
 
 
 
 
 
 
 
 
 
 
 
 
입력
Conv2D
1 * 1, strides=2
Conv2D
1 * 1
AvgPool2D
3 * 3, strides=2
Conv2D
1 * 1
Conv2D
3 * 3, strides=2
Conv2D
3 * 3
Conv2D
3 * 3
Conv2D
3 * 3, strides=2
concatenate
output
인셉션 모듈: 나란히 놓인 합성곱 층으로 구성된 서브그래프

최근에는 모델에 잔차 연결 을 추가하는 경향도 있습니다. ResNet 계열의 네트워크들이 이런 방식을 사용하기 시작했습니다. 잔차 연결은 하위 층의 출력 텐서를 상위 층의 출력 텐서에 더해서 아래층의 표현이 네트워크 위쪽으로 흘러갈 수 있도록 합니다. 하위 층에서 학습된 정보가 데이터 처리 과정에서 손실되는 것을 방지합니다.

 
 
 
 
잔차 연결
+
잔차 연결: 하위 층의 출력을 상위 층의 특성 맵에 더한다.

여러 경우에 다중 입력 모델, 다중 출력 모델, 그래프 구조를 띈 모델이 필요하지만 Sequential 모델로는 한계가 있습니다. 이런 경우 케라스의 함수형 API 를 사용할 수 있습니다.

7.1.1 함수형 API 소개

함수형 API(functional API) 에서는 직접 텐서들의 입출력을 다룹니다. 함수처럼 층을 사용하여 텐서를 입력받고 출력합니다.

간단한 예시 코드를 이용해서 Sequential과 비교해보겠습니다.

from keras.models import Sequential, Model
from keras import layers
from keras import Input

# Sequential model
seq_model = Sequential()
seq_model.add(layers.Dense(32, activation='relu', input_shape=(64,)))
seq_model.add(layers.Dense(32, activation='relu'))
seq_model.add(layers.Dense(10, activation='softmax'))

# Functianal API
input_tensor = Input(shape=(64,))
x = layers.Dense(32, activation='relu')(input_tensor)
x = layers.Dense(32, activation='relu')(x)
output_tensor = layers.Dense(10, activation='softmax')(x)

model = Model(input_tensor, output_tensor)

위 코드에서 주의할 점은 output 텐서는 반드시 input 텐서를 반복변환하여 만들 수 있어야 한다는 점입니다. 만약 그렇지 못한 입력을 줄 경우, Runtime Error가 발생합니다. 컴파일, 훈련, 평가는 다음과 같습니다.

# 컴파일
model.compile(optimizer='rmsprop', loss='categorical_crossentropy')

import numpy as np
x_train = np.random.random((1000, 64))
y_train = np.random.random((1000, 10))

# 훈련
model.fit(x_train, y_train, epochs=10, batch_size = 128)

# 평가
score = model.evalutate(x_train, y_train)

7.1.2 다중 입력 모델

함수형 API로 간단한 다중 입력 모델을 만들어봅시다. 일반적으로 이런 모델은 입력 가지를 합치기 위해 여러 텐서를 연결할 수 있는 층을 사용합니다.

예시의 모델은 질문-응답 모델입니다. 전형적인 질문-응답 모델은 2개의 입력을 가집니다.(자연어 질문, 답변에 필요한 정보가 담긴 텍스트) 그러면 모델은 답을 출력해야 합니다. 가장 간단한 구조는 미리 정의한 어휘 사전에서 소프트맥스 함수를 통해 한 단어로 된 답을 출력하는 것입니다.

 
 
 
 
 
 
 
 
참고 텍스트
Embedding
질문
Embedding
LSTM
LSTM
Concatenate
Dense
응답
질문-응답 모델

텍스트와 질문을 벡터로 인코딩하여 독립된 입력 2개를 정의합니다. 그다음 이 벡터를 연결하고 그 위에 소프트맥스 분류기를 추가합니다.

# 코드 7-1 2개의 입력을 가진 질문-응답 모델의 함수형 API 구현하기

from keras.models import Model
from keras import layers
from keras import Input

text_vocabulary_size = 10000
question_vocabulary_size = 10000
answer_vocabulary_size = 500

# 텍스트 입력은 길이가 정해지지 않은 정수 시퀀스입니다.
# 입력 이름은 지정할 수 있습니다.
text_input = Input(shape=(None, ), dtype='int32', name='text')
embedded_text = layers.Embedding(text_vocabulary_size, 64)(text_input)
encoded_text = layers.LSTM(32)(embedded_text)

# 질문도 동일한 변환을 취합니다.
question_input = Input(shape=(None, ), dtype='int32', name='question')
embedded_question = layers.Embedding(question_vocabulary_size, 64)(question_input)
encoded_question = layers.LSTM(32)(embedded_question)

# 연결합니다.
concatenated = layers.concatenate([encoded_text, encoded_question])

# softmax 분류기를 추가합니다.
answer = layers.Dense(answer_vocabulary_size, activation='softmax')(concatenated)

# 모델 객체를 만들고 2개의 입력과 출력을 주입합니다.
model = Model([text_input, question_input], answer)
model.complie(optimizer='rmsprop',loss='categorical_crossentropy',metricss=['acc'])

이렇게 입력이 2개인 모델은 2가지 방법을 훈련할 수 있습니다.

  1. 넘파이 배열의 리스트에 주입
  2. 입력 이름과 넘파이 배열로 이루어진 딕셔너리를 모델의 입력으로 주입 (입력 이름 설정시 가능)
# 코드 7-2 다중 입력 모델에 데이터 주입하기
import numpy as np
from keras.utils import to_categorical

num_samples = 1000
max_length = 100

text = np.random.randint(1, text_vocabulary_size, size=(num_samples, max_length))
question = np.random.randint(1, question_vocabulary_size, size=(num_samples, max_length))

answers = np.random.randomint(0, answer_vocabulary_size, size=num_samples)
answers = to_categorical(answers) # 원핫 인코딩

# 1.리스트 입력 사용
model.fit([text, question], answers, epochs=10, batch_size=128)
# 2. 딕셔너리 입력을 사용하여 학습
model.fit({'text':text, 'question':question}, answers, epochs=10, batch_size=128)

7.1.3 다중 출력 모델

다중 출력 모델의 예시는 소셜 미디어에서 익명 사용자의 포스트를 받아 나이, 성별, 소득을 예측하는 것입니다. 모델은 다음과 같이 생각해볼 수 있습니다.

 
 
 
 
 
 
 
소설 미디어 포스트
1D 컨브넷
Dense
Dense
Dense
나이
소득
성별
3개의 출력을 가진 소셜 미디어 모델
# 코드 7-3 3개의 출력을 가진 함수형 API 구현하기

from keras import layers
from keras import Input
from keras.models import Model

vocabulary_size = 50000
num_income_groups = 10

post_input = Input(shape=(None,), dtype='int32', name='posts')
embedded_posts = layers.Embedding(vocabulary_size,256)(posts_input)
x = layers.Conv1D(128, 5, activation='relu')(embedded_posts)
x = layers.MaxPooling1D(5)(x)
x = layers.Conv1D(256, 5, activation='relu')(x)
x = layers.Conv1D(256, 5, activation='relu')(x)
x = layers.MaxPooling1D(5)(x)
x = layers.Conv1D(256, 5, activation='relu')(x)
x = layers.Conv1D(256, 5, activation='relu')(x)
x = layers.GlobalMaxPooling1D()(x)
x = layers.Dense(128, activation='relu')(x)

# 출력 층에 이름 붙이기
age_prediction  = layers.Dense(1, name='age')(x)
income_prediction = layers.Dense(num_income_groups, activation='softmax', name='income')(x)
gender_prediction = layers.Dense(1, activation='sigmoid', name='gender')(x)

model= = Model(post_input, [age_prediction, income_prediction, gender_prediction])

이런 모델을 예측하기 위해서는 네트워크 출력마다 다른 손실 함수를 지정해야 합니다. 손실 값을 합치는 가장 간단한 방법은 모두 더하는 것입니다. 케라스에서는 compile 메서드에서 리스트나 딕셔너리를 사용하여 출력마다 다른 손실을 지정할 수 있습니다. 계산된 손실 값은 전체 손실 하나로 더해지고 훈련 과정에서 최소화됩니다.

# 코드 7-4 다중 출력 모델의 컴파일 옵션: 다중 손실

# 1. 리스트로 손실함수 지정
model.compile(optimizer='rmsprop', loss=['mse','categorical_crossentropy', 'binary_crossentroypy'])

# 2. 딕셔너리로 손실함수 지정
model.compile(optimizer='rmsprop', loss={'age':'mse', 'income':'categorical_crossentropy', 'gender':'binary_crossentroypy'})

하지만 단순한 합으로 하게 될 경우, 개별 손실이 가장 큰 작업 기준으로 최적화가 진행되기에 특정 값의 결과가 매우 부정확 해질 수 있습니다. 이를 해결하기 위해 가중치를 설정할 수 있습니다.

# 코드 7-5 다중 출력 모델의 컴파일 옵션: 손실 가중치
# 1. 리스트로 손실함수 지정 + 가중치
model.compile(optimizer='rmsprop', loss=['mse','categorical_crossentropy', 'binary_crossentroypy'], loss_weights=[0.25, 1., 10.])

# 2. 딕셔너리로 손실함수 지정 + 가중치
model.compile(optimizer='rmsprop', loss={'age':'mse', 'income':'categorical_crossentropy', 'gender':'binary_crossentroypy'}, loss_weights={'age':0.25, 'income':1., 'gender':10.})

다중 입력과 마찬가지로 입력 전달은 두 가지 방법으로 할 수 있습니다.

# 코드 7-6 다중 출력 모델에 데이터 주입하기

# 1. 리스트
model.fit(posts, [age_targets, income_targets, gender_targets], epochs=10, batch_size=64)

# 2. 딕셔너리
model.fit(posts, {'age' : age_targets, 'incomde' : income_targets, 'gender' : gender_targets}, epochs=10, batch_size=64)

7.1.4 층으로 구성된 비순향 유향 그래프

함수형 API는 내부 토폴로지가 복잡한 네트워크도 만들 수 있습니다. DAG에서 말이죠. 순환은 불가능합니다. 만들 수 있는 루프는 순환 층 내부에 있는 것만 가능합니다.

그래프로 구현된 몇 개의 신경망 컴포넌트가 널리 사용됩니다. 가장 유명한 2개가 앞서 언급한 인셉션 모듈과 잔차 연결입니다.

인셉션 모듈

인셉션 은 합성곱 신경망에서 인기 있는 네트워크 구조입니다. network-in-network 구조에 영감을 받은 구글러들이 만들었습니다. 가장 기본적인 인셉션 모듈 형태는 3~4개의 가지를 가집니다. 1by1 합성곱에서 3by3 합성곱이 뒤따르고 마지막에 전체 출력 특성이 합쳐집니다. 이런 구성은 네트워크가 따로따로 공간 특성과 채널 방향의 특성을 학습하도록 돕습니다. 한꺼번에 합성하는 것보다 효과가 좋습니다.

위에서 flowchart로 나타낸 모델은 인셉션V3로 케라스에서는 keras.applications.inception_v3.InceptionV3에 준비되어 있으며, ImageNet에서 사전 훈련된 가중치를 포함하고 있습니다. 이와 비슷한 엑셉션 모델도 케라스에 포함되어 있습니다. 이 합성곱 구조는 채널 방향의 학습과 공간 방향의 학습을 극단적으로 분리한다는 아이디어에 착안하여 인셉션 모듈을 깊이별 분리 합성곱으로 바꿉니다. 이 합성곱은 깊이별 합성곱 다음에 점별 합성곱이 뒤따릅니다. 인셉션 모듈의 극한 형태로 공간 특성과 채널 방향 특성을 완전히 분리합니다. 엑셉션은 인셉션V3와 거의 동일한 개수의 모델 파라미터를 가지지만 실행 속도가 더 빠르고 대규모 데이터셋에서 정확도가 더 높습니다. (효율적 사용)

잔차 연결

잔차 연결residual connection) 은 엑셉션을 포함하여 2015년 이후 등장한 많은 네트워크 구조에 있는 그래프 형태의 네트워크 컴포넌트입니다. 대규모 딥러닝 모델에서 흔히 나타나는 두 가지 문제인 그래디언트 소실과 표현 병목(representational bottleneck)을 해결했습니다. 일반적으로 10개 층 이상을 가진 모델에 잔차 연결을 추가하면 도움이 됩니다.

잔차 연결은 하위 층의 출력을 상위 층의 입력으로 사용합니다. 순서대로 놓인 네트워크를 질러가는 연결이 만들어집니다. 하위 층의 출력이 상위 층의 출력에 연결되는 것이 아니라 더해집니다. 따라서 두 출력의 크기가 동일해야 합니다. 크기가 다르면 선형 변환을 사용하여 하위 층의 활성화 출력을 목표 크기로 변환합니다.

7.1.5 층 가중치 공유

함수형 API의 중요한 또 하나의 기능은 층 객체를 여러 번 재사용할 수 있다는 것입니다. 층 객체를 두 번 호출하면 새로운 객체를 만들지 않고 각 호출에 동일한 가중치를 재사용합니다. 이런 기능 때문에 공유 가지를 가진 모델을 만들 수 있습니다.

7.1.6 층과 모델

함수형 API에서는 모델을 층처럼 사용할 수 있습니다. Sequential 클래스와 Model 클래스에서 모두 동일합니다.

7.1.7 정리

생략

7.2 케라스 콜백과 텐서보드를 사용한 딥러닝 모델 검사와 모니터링

model.fit()이나 model.fit_generator을 사용하면 실행과 동시에 결과는 제어할 방법이 없습니다. 이 절에서는 위 함수의 호출을 스스로 판단하고 동적으로 결정하는 방법을 살펴봅니다.

7.2.1 콜백을 사용하여 모델의 훈련 과정 제어하기

1장부터 6장까지 예제들을 진행하면서 가장 의문인 점은 ‘왜 과대적합이 되고난 후에도 에포크를 훈련하는가’ 였습니다. 심지어 최적의 에포크 횟수로 처음부터 새로운 훈련을 시작했습니다. 이런 방법은 낭비가 많습니다.

더 좋은 방법은 검증 손실을 관측하여 더 이상 향상되지 않는 지점에서 훈련을 멈추는 것입니다. 이를 케라스의 콜백을 이용해서 구현할 수 있습니다. 콜백(callback) 은 모델의 fit() 메서드가 호출된 때 전달되는 객체입니다. 훈련하는 동안 모델은 여러 지점에서 콜백을 호출합니다. 콜백은 모델의 상태와 성능에 대한 모든 정보에 접근하고 훈련 중지, 모델 저장, 가중치 적재 또는 모델 상태 변경 등을 처리할 수 있습니다. 다음의 사례들에서 사용할 수 있습니다.

  • 모델 체크포인트 저장 : 훈련하는 동안 어떤 지점에서 모델의 현재 가중치를 저장합니다.
  • 조기 종료(early stopping) : 검증 손실이 더 이상 향상되지 않을 때 훈련을 중지합니다.
  • 훈련하는 동안 하이퍼파라미터 값을 동적으로 조정합니다. : 옵티마이저의 학습률 같은 경우입니다.
  • 훈련과 검증 지표를 로그에 기록하거나 모델이 학습한 표현이 업데이트될 때마다 시각화합니다. : 진행 표시줄이 하나의 콜백입니다.

이제 이 예들을 살펴보겠습니다.

ModelCheckpoint와 EarlyStopping 콜백

EarlyStopping 콜백을 사용하면 정해진 에포크 동안 모니터링 지표가 향상되지 않을 때 훈련을 중지할 수 있습니다. 예를 들면 과대적합 등에서 사용할 수 있습니다. 일반적으로 이 콜백은 훈련하는 동안 모델을 계속 저장해주는 ModelCheckpoint와 함께 사용합니다. (지금까지 가장 좋은 모델만 저장가능)

import keras

# fit() 메서드의 callbacks 매개변수를 사용하여 원하는 개수만큼 콜백을 모델로 전달
callback_list = [
  keras.callbacks.EarlyStopping(
    monitor='val_acc', # 모델의 검증 정확도 모니터링
    patience=1, # 1 에포크보다 더 길게 향상되지 않으면 중단
  ),
  keras.callbacks.ModelCheckpoint(
    filepath='my_model.h5', # 저장
    monitor='val_loss',
    save_best_only=True, # 가장 좋은 모델
  )
]

model.compile(optimizer='rmsprop', loss='binary_crossentroypy', metrics['acc'])
model.fit(x,y, epochs=10, batch_size=32, callbacks=callback_list, validation_data=(x_val, y_val))

ReduceLRONPlateau 콜백

이 콜백을 사용하면 검증 손실이 향상되지 않을 때 학습률을 작게 할 수 있습니다. 손실 곡선이 평탄할 때 학습률을 작게 하거나 크게 하면 훈련 도중 지역 최솟값에서 효과적으로 빠져나올 수 있습니다.

callback_list = [
  keras.callbacks.ReduceLRONPlateau(
    monitor='val_acc',
    factor=0.1, # 콜백이 호출되면 학습률을 10배로 줄임
    patience=10,
  )
]

자신만의 콜백 만들기

내장 콜백에서 제공하지 않는 경우 필요에 따라 콜백을 만들 수 있습니다. 콜백은 keras.callbacks.Callback 클래스를 상속받아 구현합니다. 그다음 훈련하는 동안 호출될 여러 지점을 나타내기 위해 약속된 다음 메서드를 구현합니다.

method 설명
on_epoch_begin 각 에포크가 시작할 때 호출합니다.
on_epoch_end 각 에포크가 끝날 때 호출합니다.
on_batch_begin 각 배치 처리가 시작되기 전에 호출합니다.
on_batch_end 각 배치 처리가 끝난 후에 호출합니다.
on_train_begin 훈련이 시작될 때 호출합니다.
on_train_end 훈련이 끝날 때 호출합니다.

이 메서드들은 모두 log 매개변수와 함께 호출됩니다. 이 매개변수에는 이전 배치, 에포크에 대한 훈련과 검증 측정값이 담겨 있는 딕셔너리가 전달됩니다. 콜백은 다음 속성을 참조할 수 있습니다.

  • self.model: 콜백을 호출하는 모델 객체
  • self.validation_data: fit() 메서드에 전달된 검증 데이터

다음은 매 에포크의 끝에서 검증 세트의 첫 번째 샘플로 모델에 있는 모든 층의 활성화 출력을 계산하여 디스크에 저장하는 자작 콜백의 예입니다.

from keras
import numpy as np

class ActivationLogger(keras.callbacks.Callback):
  def set_model(self, model):
    self.model = model
    layer_output = [layer.output for layer in model.layers ]
    self.activation_model = keras.models.Model(model.input, layer_outputs)

  def on_epoch_end(self, epoch, log=None):
    if self.validation_data is None:
      raise RuntimeError('Requires validation_data.')
    validation_sample = self.validation_data[0][0:1]
    activation = self.activations_model.predict(validation_sample)
    f = open('activaions_at_epoch_' + str(epoch) + '.npz', 'wb')
    np.savez(f, activations)
    f.close()

7.2.2 텐서보드 소개: 텐서플로의 시각화 프레임워크

본 장의 예제 코드는 embeddings_data 매개변수의 에러로 실행을 하지 못했습니다. 링크에 같은 오류가 있음에도 원하는 결과를 찾지 못하였고, 이는 후에 수정하도록 하겠습니다.

이 장에서는 실험 결과를 처리하는 효율적인 도구인 텐서보드 를 소개하고자 합니다. 텐서플로로 백엔드를 설정하면 케라스 모델에서 사용가능합니다. 텐서보드의 핵심 목적은 훈련 모델의 내부에서 일어나는 모든 것을 시각적으로 모니터링할 수 있도록 돕는 것입니다. 모델의 최종 손실 외에 더 많은 정보를 모니터링하면 모델 작동에 대한 명확한 그림을 그릴 수 있고, 개선을 빠르게 할 수 있습니다. 텐서보드는 여러 가지 멋진 기능을 제공합니다. (모든 브라우저에서 작동)

  • 훈련하는 동안 측정 지표를 시각적으로 모니터링
  • 모델 구조를 시각화
  • 활성화 출력과 그래디언트의 히스토그램
  • 3D로 임베딩 표현

예시로 IMDB 감성 분석 문제를 위해 1D 컨브넷을 훈련합니다. 이번엔 빈도가 높은 2,000개 단어만 사용합니다.

# 코드 7-7 텐서보드를 사용한 텍스트 분류 모델
import keras
from keras import layers
from keras.datasets import imdb
from keras.preprocessing import sequence

max_features = 2000
max_len = 500

(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
x_train = sequence.pad_sequences(x_train, maxlen=max_len)
x_test = sequence.pad_sequences(x_test, maxlen=max_len)

model = keras.models.Sequential()
model.add(layers.Embedding(max_features, 128, input_length=max_len, name='embed'))
model.add(layers.Conv1D(32, 7, activation='relu'))
model.add(layers.MaxPooling1D(5))
model.add(layers.Conv1D(32, 7, activation='relu'))
model.add(layers.GlobalMaxPooling1D())
model.add(layers.Dense(1))
model.summary()
model.compile(optimizer="rmsprop",loss="binary_crossentroypy",metrics=['acc'])

텐서보드 시작하기 전에 로그 파일이 저장될 디렉터리를 만들어야 합니다.

# 코드 7-8 텐서보드 로그 파일을 위한 디렉터리 생성하기
mkdir my_log_dir

텐서보드 콜백 객체와 함께 훈련을 진행합니다. 이 콜백은 지정된 디스크 위치에 로그 이벤트를 기록할 것입니다.

callbacks = [
  keras.callbacks.TensorBoard(
    log_dir='my_log_dir', # 저장될 path
    histogram_freq=1, # 1 에포크마다 활성화 출력의 히스토그램을 기록
    embeddings_freq=1, # 1 에포크마다 임베딩 데이터를 기록
  )
]
hitory = model.fit(x_train, y_train, epochs=20, batch_size=128, validation_split=0.2 callbacks=callbacks)

이제 명령행에서 콜백이 사용하는 로그 디렉터리를 지정하여 텐서보드 서버를 실행합니다. 텐서플로 설치시에 자동으로 설치됩니다.

tensorboard --logdir=my_log_dir

이 부분은 좀 더 공부해봐야곘습니다. :-(

7.2.3 정리

생략

7.3 모델의 성능을 최대로 끌어올리기

7.3.1 고급 구조 패턴

이전 절에서 본 잔차 연결 외에 알아야 할 디자인 패턴이 2개가 더 있습니다. 정규화와 깊이별 분리 합성곱입니다. 고성능 심층 컨브넷을 만들 때 유용합니다.

배치 정규화

정규화(normalization) 는 머신 러닝 모델에 주입되는 샘플들을 균일하게 만드는 광범위한 방법입니다. 이미 이전 예제에서 많이 사용한 방법이 있습니다. 평균을 빼고, 표준 편차로 나누어 분산을 1로 만듭니다.

normalized_data = (data - np.mean(data, axis=...)) / np.std((data, axis=...))

이전 예제에는 모델에 데이터를 주입하기 전에 정규화했습니다. 하지만 데이터 정규화는 네트워크에서 일어나는 모든 변환 후에도 고려되어야 합니다. Dense나 Conv2D 층에 들어가는 데이터의 평균이 0이고 분산이 1이라도 출력되는 데이터가 동일한 분포를 가질 것이라고 기대하기는 어렵습니다.

배치 정규화는 2015년에 아이오페와 세게디가 제안한 층의 한 종류입니다. 케라스는 BatchNormalization 클래스로 제공합니다. 훈련한는 동안 평균과 분산이 바뀌더라도 이에 적응하여 데이터를 정규화합니다. 훈련 과정에서 사용된 배치 데이터의 평균과 분산에 대한 지수 이동 평균을 내부에 유지합니다. (momentum 기본값 0.99)

배치 정규화의 주요 효과는 잔차 연결과 매우 흡사하게 그래디언트의 전파를 도와주는 것입니다. (입력과 출력의 분포가 유지) 그렇기에 더 깊은 네트워크를 구성할 수 있습니다. ResNet50, 인셉션 V3, 엑셉션 등이 있습니다. 다음은 사용하는 예시입니다.

# Conv2D 층
conv_model.add(layers.Conv2D(32, 3 activation='relu'))
conv_model.add(layers.BatchNormalization())
# Dense 층
dense_model.add(layers.Dense(32, activation='relu'))
dense_model.add(layers.BatchNormalization())

BatchNormalization 클래스에는 정규화할 특성 축을 지정하는 axis 매개변수가 있습니다. 이 매개변수의 기본값은 입력 텐서의 마지막 축을 나타내는 -1 입니다. (data_format"chanels_last"인 경우, "chanels_first"인 경우는 매개변수를 1로 설정)

2017년에는 배치 재정규화 라는 방법이 소개되었습니다. 정규화에 대해서 보다 recent한 논문을 주제로 포스팅해도 재밌을 것 같습니다.

깊이별 분리 합성곱

Conv2D를 대체하면서 더 가볍고 더 빨라 모델의 성능을 높일 수 있는 층을 소개합니다. 깊이별 분리 합성곱(depthwise separable convolution) 층은 입력 채널별로 따로따로 공간 방향의 합성곱을 수행합니다. (SeparableConv2D으로 사용합니다.) 그리고 점별 합성곱을 통해 출력 채널을 합칩니다. 공간 특성과 채널 방향 특성을 독립적으로 인식하여 학습하고, 모델 파라미터와 연산수를 줄여줍니다. 더 빠르고 효율적인 학습을 할 수 있습니다.

제한된 데이터로 작은 모델을 처음부터 훈련시킬 때 특히 더 중요합니다. 작은 데이터셋에서 이미지 분류 문제를 위한 가벼운 깊이별 분리 컨브넷을 만드는 예입니다.

 
깊이별합성곱
 
 
 
 
 
 
 
 
 
채널 분리
3 * 3 합성곱
3 * 3 합성곱
3 * 3 합성곱
합침
 
1 * 1 합성곱
 
깊이별 분리 합성곱: 깊이별 합성곱 다음에 합성곱이 뒤따른다.
from keras.models import Sequential, Model
from keras import layers

height = 64
width = 64
channels = 3
num_classes = 10

model = Sequential()
model.add(layers.SeparableConv2D(32, 3, activation='relu', input_shape=(height. width, channels,)))
model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layer.MaxPooling2D(2))

model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.SeparableConv2D(128, 3, activation='relu'))
model.add(layers.MaxPooling2D(2))

model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.SeparableConv2D(128, 3, activation='relu'))
model.add(layers.GlobalAveragePooling2D())

model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(num_classes, activation='softmax'))

model.compile(optimizer='rmsprop', loss='categorical_crossentropy')

대규모 모델은 엑셉션이 그 예시이다.

7.3.2 하이퍼파라미터 최적화

딥러닝 모델은 무작위 선택의 연속입니다. 층의 수, 유닛과 필터 수, 활성화 함수의 종류 등 설계자의 이유있는 랜덤한 선택의 연속입니다. 이런 구조에 관련된 파라미터를 역전파로 훈련되는 모델 파라미터와 구분하여 하이퍼파라미터(hyperparameter) 라고 합니다.

하이퍼파라미터 튜닝에 공식적인 규칙은 없습니다. 직관은 있을 수 있으나 정해를 찾을 수는 없습니다. 그렇다고 하이퍼파라미터 튜닝을 모두 사람이 하고 있을 수는 없기에 이것도 기계의 힘을 빌립니다. 가능한 결정 공간을 자동적, 조직적, 규칙적 방법으로 탐색해야합니다. 전형적인 최적화 과정은 다음과 같습니다.

  1. 일련의 하이퍼파라미터를 자동으로 선택합니다.
  2. 선택된 하이퍼파라미터로 모델을 만듭니다.
  3. 훈련 데이터에 학습하고 검증 데이터에서 최종 성능을 측정합니다.
  4. 다음으로 시도할 하이퍼파라미터를 자동으로 선택합니다.
  5. 이 과정을 반복합니다.
  6. 마지막으로 테스트 데이터에서 성능을 측정합니다.

주어진 하이퍼파라미터에서 얻은 검증 성능을 사용하여 다음 번에 시도할 하이퍼파라미터를 선택하는 알고리즘이 핵심입니다. 베이지안 최적화, 유전 알고리즘, 간단한 랜덤 탐색 등을 사용할 수 있습니다. 하지만 선택하는 것은 실로 어려운 일입니다. 비용이 너무 많이 들기 때문입니다. 그렇기에 가장 간단하게 하는 방법은 랜덤 탐색입니다.

랜덤 탐색보다 나은 방법으로는 파이썬 라이브러리인 Hyperopt, Hyperas 를 사용하는 것입니다. 아직은 조금 부족할 수 있는 도구지만 앞으로 발전될 가능성이 큽니다.

7.3.3 모델 앙상블

모델 앙상블(model ensemble) 은 여러 개 다른 모델의 예측을 합쳐 더 좋은 예측을 만드는 기법입니다. 캐글 같은 머신 러닝 경연 대회에서는 우승자들이 대규모 모델 앙상블을 사용합니다. 단일 모델보다 성능이 좋기 때문이죠.

가장 기본적인 앙상블은 추론에 나온 예측을 평균내는 방법입니다. 이제 더 나아가서는 가중치를 주고 평균을 내는 방법도 있습니다. 좋은 앙상블 가중치는 랜덤 서치나 넬더-미드 방법 같은 간단한 최적화 방법이 있습니다. 이외에도 지수 값을 평균할 수 있겠습니다.

앙상블이 잘 작동하게 만드는 핵심은 분류기의 다양성입니다. 모델이 서로 다른 방향으로 편향되어 있다면 상쇄를 통해 더 정확한 모델이 되는 것입니다.

모든 문제에 적용하지 못하지만 실전에서 잘 작동하는 한 가지 방법은 트리 기반 모델(랜덤 포레스트나 그래디언트 부스팅 트리)이나 심층 신경망을 앙상블하는 것입니다. 최근에 실전에서 매우 성공적으로 사용되는 기본 앙상블 스타일은 딥러닝과 얕은 모델을 섞은 넓고 깊은 모델입니다. 이런 모델은 심층 신경망과 많은 선형 모델을 함께 훈련합니다. 다양한 종류의 모델들을 함께 훈련하는 것은 모델 앙상블을 만드는 또 다른 방법입니다.

7.3.4 정리

생략

7.4 요약

생략

 

 

출처 : https://subinium.github.io/Keras-7/

 

"케라스 창시자에게 배우는 딥러닝" 에 있는 책 내용의 그림이 많이 담겨있어서 담아둠,

그런데.. 그림이 좀 깨지니.. 출처로 가서 살펴보는게 어쩌면 더 나을 수도 있음,

간단히 코드 볼때는 문제 없는 듯..

 

:

LSTM을 사용해보려고 하는데 입력과 출력에 대해서 자세히 나온 부분이 없어서 정리해 보았습니다.
기본적인 내용은 아래 참조 링크를 사용하였습니다.

참조 링크 : https://medium.com/@shivajbd/understanding-input-and-output-shape-in-lstm-keras-c501ee95c65e

 

참조 링크 : https://towardsdatascience.com/predicting-stock-price-with-lstm-13af86a74944

위 링크 저자도 처음에 혼란스러웠다고 되어있네요.

LSTM을 하기 위해서는 3차원적 데이터가 필요합니다. (대부분의 예제의 경우 batch(일괄처리)값 설정없이 input_shape을 사용합니다. 만약 batch를 설정하려면 batch_input_shape 값에 batch값을 추가하여 차원을 추가한 입력을 사용해야합니다.)

[data_size, time_steps, features] 3차원 array로 구성됩니다.

Keras input_shape 예제

model = keras.models.Sequential() model.add(keras.layers.LSTM(unit=3, input_shape=(3, 5)))


위 예에서 (2,10)은 time_steps=3, features=5 가 됩니다. data_size는 따로 넘기지 않습니다. data_size 정보는 없어도 넘어오는 크기로 부터 전체 data size를 알 수 있기 때문입니다.

이것을 그림으로 그려보면 다음과 같습니다.


time_steps는 Network에 사용할 시간 단위입니다. 이 값은 LSTM에서 과거의 몇개 데이터를 볼것인가 가지고 결정합니다. 위 그림에서 녹색 box부분을 보면 3개 데이터를 이용해서 다음 한개를 추론 하기 때문에 time_steps:3 이 됩니다.
data_size는 데이터의 크기 입니다. 위 그림에서는 N으로 표시 하였습니다. 커다란 박스의 개수가 3개 있고, 추가로 2개 더 그릴수 있으므로 데이터는 5개가 될 것입니다.
Features 는 일반적인 경우 X의 차원을 의미합니다. LSTM에서는 input이 time_steps에 의해서 여러개의 입력 나타내지는데 그것의 속성의 수가 됩니다. 여기에서는 Open, High, Low, Close, Volume 이렇게 5개가 들어갑니다.

Batch에 대하여

Batch는 일괄 처리되는 작업의 양이다. 위에서 설명된 data_size를 한번에 처리하는 갯수를 의미하며, batch크기에 의해 weight 변화가 일어나며 batch크기 단위로 data loading 함수도 구현이 가능하다. 주의할점은 data_size/batch_size일때 나머지가 없어야 한다.

batch 되는 양이 있다면 아래와 같이 설정할 수도 있습니다.

Keras batch_input_shape 예제 

model = keras.models.Sequential() model.add(keras.layers.LSTM(unit=4, batch_input_shape=(3, 4, 6)))

batch_size, time_steps, features 각각은 3,4,6이 됩니다.

 

실제 데이터의 크기는 [6,4,6]으로 준비가 된 모습입니다. batch_size로 차원을 구성하는것이 아닙니다. batch_size = 3으로 6/3이 되므로 나머지가 없기 때문에 문제가 없습니다. 나머지가 생기게 되면 batch 작업시 문제가 생깁니다.


unit=4 은 해당 layer의 출력 크기가 된다.

출처 : http://swlock.blogspot.com/2019/04/keras-lstm-understanding-input-and.html

:

brunch 데이터를 활용해 사용자의 취향에 맞는 글을 예측할 수 있을까?

다양한 미디어 매체를 통해 콘텐츠의 가치가 나날이 높아지고 있습니다.
양질의 콘텐츠가 늘어남에 따라 손쉽고 편하게 나에게 맞는 콘텐츠를 추천받길 원하는 사용자도 늘어나고 있습니다.
그만큼 추천을 통해 글이 가치 있게 읽히는 경험은 창작자에게도, 독자에게도 매우 중요한 일입니다.

브런치 역시 매번 더 나은 해결책을 고민하고 있습니다.
브런치에 담긴 아름다운 글을 원하는 독자가 충분히 감상할 수 있도록 추천을 통해 잘 연결해주세요.

이번 대회는 보다 정밀하게 사용자 개개인이 좋아할 만한 글을 예측하는 것이 목표입니다.
사용자의 과거 활동 정보를 기반으로 취향을 분석하고 모델링하여 미래 소비 결과를 예측해보는 실험입니다

이 대회를 통해 다루게 될 데이터 구성은 아래와 같습니다.

  • 콘텐츠
  • 작가/독자 정보
  • 행태 정보

대회 참가자는 주어진 데이터로 사용자의 취향 저격 글을 예측하고 그 결과를 제출하여 성능을 확인해볼 수 있습니다.
카카오 아레나에서 세상을 즐겁게 변화시킬 기회에 도전하세요.

베이스 코드는 추후 공개됩니다.

 

출처 : https://arena.kakao.com/c/6

 

:

대회 설명

다음쇼핑에는 수억개의 상품이 존재합니다. 사용자에게 효과적으로 상품을 노출하기 위해서는 체계적인 분류가 필요하지만, 상품을 제공하는 업체마다 기준이 다르거나 분류 정보가 없는 경우가 많기 때문에 일관된 분류 체계로 만드는 작업이 필요합니다.

이 대회는 더 정확한 상품 분류기를 만드는 것이 목표입니다. 상품은 최대 4개까지의 분류 값을 갖는데, 각 분류는 계층적인 구조입니다. 예를 들어 아이디 L3203227501 상품은 맛있는 제주차 3종세트 ...인데, 이 상품의 카테고리는 아래와 같습니다.

  • 대분류: 음료/생수/커피
  • 중분류: 차/티백
  • 소분류: 차 선물세트
  • 세분류 : 없음

대/중/소/세는 카테고리 분류 체계를 말하며 앞선 카테고리가 상위 카테고리입니다.

이 대회에서 다루게될 데이터는 아래와 같습니다.

  • 약 천만건의 데이터: 제목, 브랜드, 이미지 피쳐, …
  • 57개의 대분류 카테고리, 552개의 중분류 카테고리, 3190개의 소분류 카테고리, 404개의 세분류 카테고리

대회 참가자는 주어진 데이터로 분류기를 만든 후에 평가 데이터에 대해 예측한 결과를 제출하고 결과를 확인할 수 있습니다.

기초 코드

데이터 구조, 제출 포맷 확인등 원활한 참가를 돕기 위해 베이스라인 솔루션을 제공하고 있습니다. github의 코드를 참고하세요.

 

출처 : https://arena.kakao.com/c/5

:

Ensemble 1/2 (앙상블)

데이터사이언스/MachineLearning | 2020. 4. 23. 17:56 | Posted by youGom

Part 1. What is Ensemble Learning?

0. Intro

머신러닝 튜토리얼에 Advanced 알고리즘을 보면 항상 앙상블 학습이라는 내용이 포함되어 있습니다. 최근 캐글 우승자의 인터뷰를 보면 대다수가 앙상블 기법 중 하나를 이용했다고 합니다.

이는 앙상블을 알아야 캐글에서 좋은 성적을 받을 수 있다는 말이기도 합니다.

앙상블 알고리즘에 대해 포스팅은 3개 정도로 나누어 올리겠습니다. 예상으로는 다음과 같이 나눌 수 있을 것 같습니다.

  • Part 1. What is Ensemble Learning
  • Part 2. Voting & Bagging with Code
  • Part 3. Boosting with Code
  • Part 4. Stacking with Code

(포스팅을 적으며 목록을 수정했습니다.)

첫 번째 포스팅은 종류와 개념에 대해 다뤄보겠습니다. 구체적인 방법에 대한 내용은 다음 포스팅에서 다루겠습니다.

1. What is Ensemble Learning?

Coursera의 How to Win a Data Science Competition: Learn from Top Kagglers의 코스에서 실전 전의 마지막 강의 | 출처 :
https://www.coursera.org/learn/competitive-data-science

앙상블(Ensemble) 학습은 여러 개의 학습 알고리즘을 사용하고, 그 예측을 결합함으로써 보다 정확한 최종 예측을 도출하는 기법입니다. 하나의 강한 머신러닝 알고리즘보다 여러 개의 약한 머신러닝 알고리즘이 낫다 라는 아이디어를 가지고 이해하면 좋습니다.

이미지, 영상, 음성 등의 비정형 데이터의 분류는 딥러닝이 뛰어난 성능을 보이고 있지만, 대부분의 정형 데이터 분류 시에는 앙상블이 뛰어난 성능을 나타내고 있습니다.

문제와 데이터에 따라 단일 모델의 성능이 더 좋은 경우도 있습니다. 하지만 앙상블 기법을 사용하면 더 유연성있는 모델을 만들며 더 좋은 예측 결과를 기대할 수 있습니다.

캐글에서는 높은 성적을 얻기 위해서 시도해볼 수 있는 테크닉 중 하나이며, 최근 많은 winning solution에서 앙상블 기법이 사용되었습니다.

앙상블 학습의 유형은 가장 많이 알려진 Voting, Bagging, Boosting, Stacking 등이 있으며, 그 외에도 다양한 앙상블 학습의 유형이 있습니다.

2. Voting & Averaging

모델들의 투표가 최종 결과가 된다! | 출처 :
https://facingtoday.facinghistory.org

보팅(Voting) 또는 에버리징(Averaging) 은 가장 쉬운 앙상블 기법입니다. 이 둘은 서로 다른 알고리즘을 가진 분류기를 결합하는 방식입니다. Voting은 분류 에서 사용하며 Averaging은 회귀 에서 사용합니다. (categorical인 경우에는 voting, numerical인 경우에는 averaging이기도 합니다.)

단어 그대로 투표, 평균의 방식으로 진행이 됩니다. 좀 더 구체적으로 서술하면 다음과 같은 과정으로 진행이 됩니다.

  1. 일정 수의 base model과 predict를 만듭니다.
    • 1-1. 훈련 데이터를 나누어 같은 알고리즘을 사용하거나
    • 1-2. 훈련 데이터는 같지만 다른 알고리즘을 사용하거나
    • 1-3. 등등의 방법을 사용합니다.
  2. 여기서 여러가지 방법으로 voting을 진행합니다.

base model은 Linear Regression, KNN, SVM 등 여러 머신러닝 모델을 사용하면 됩니다. Voting과 Averaging은 다음과 같은 분류로 나눌 수 있습니다.

2-1. Majority Voting (Hard Voting)

각 모델은 test 데이터셋(또는 인스턴스)의 결과를 예측합니다. 그리고 예측값들의 다수결로 예측값을 정합니다. 이진 분류에 있어서는 과반수 이상이 선택한 예측값을 최종 예측으로 선택하는 것입니다.

이런 다수결의 성격때문에 max voting, plurality voting 라고도 부릅니다.

2-2. Weighted Voting (Soft Voting)

위의 보팅 방법과 다르게, 좀 더 유연한 보팅 방법입니다.

이번에는 test 데이터셋(또는 인스턴스)의 결과 가능성을 예측합니다. 그리고 이 가능성(가중치)를 특정 연산을 하여 분류 label의 확률값을 계산합니다. 이 방법에서 가중치의 연산은 원하는 방식으로 할 수 있고, 보통 평균을 사용합니다.

보통 Majority Voting보다 유연한 결과를 얻을 수 있으며, 예측 성능이 좋아 더 많이 사용합니다.

2-3. Simple Averaging

회귀 문제에서 사용하는 방법으로, 각 예측값을 평균내어 사용합니다. 이 방법은 경우에 따라 과대적합을 줄여주고, 더 부드러운 회귀모델을 만들어줍니다.

2-4. Weighted Averaging

위에서 평균을 낼 때, 각 모델별 가중치를 두어 평균내는 방식입니다.

3. Bagging

Bagging의 대표 알고리즘 중 하나인 Random Forest를 시각화한 이미지 ㅣ 출처 :
https://towardsdatascience.com/random-forest-learning-essential-understanding-1ca856a963cb

배깅(Bagging) 은 Bootstrap Aggregating의 약자입니다. 배깅의 핵심은 평균을 통해 분산(variance)값을 줄여 모델을 더 일반화시킨다는 점입니다.

배깅은 보팅과 유사한 방식으로 진행이 됩니다. 정확히는 최종적으로는 보팅을 사용합니다.

  1. 일정 수의 base model을 만듭니다.
  2. 모델들의 알고리즘은 모두 같습니다.
  3. 각각의 모델은 훈련데이터셋에서 랜덤으로 만든 서브 데이터셋을 각각 사용합니다.

3에서 서브 데이터셋을 만드는 과정을 부트스트래핑(Bootstrapping) 분할 방식이라고 합니다. 각각의 서브 데이터셋은 중첩이 가능합니다. 즉 다음과 같은 식이 만족될 수 있습니다.

StotS1S2SkStot≠S1∪S2∪⋯∪Sk

배깅의 경우에는 데이터 생성과 훈련이 개별 모델에서 진행되므로, 병렬 연산이 가능합니다.

배깅의 대표적인 알고리즘은 랜덤 포레스트(Random Forest) 입니다. 그 외에도 Bagging meta-estimator가 있습니다.

3-1. Bagging meta-estimator

Bagging meta-estimator는 랜덤 포레스트의 모체가 되는 알고리즘입니다. 위에서 언급한 방식을 그대로 사용하는 알고리즘입니다.

3-2. Random Forest

랜덤 포레스트 알고리즘은 여러 결정 트리(Decision Tree) 를 사용하여 보팅(soft voting)을 통해 예측을 결정하는 것입니다.

Bagging meta-estimator과 다르게 결정트리만 사용하고, 특성(feature)을 랜덤으로 선택하여 Bagging을 진행한다는 점이 다릅니다.

tree가 모여 forest라니 너무 귀엽지 않나요 :-)

결정 트리의 경우, 쉽고 직관적인 성격때문에 다른 앙상블 알고리즘에서도 많이 채택하고 있습니다. 랜덤 포레스트는 앙상블 알고리즘 중 비교적 빠른 속도를 가지고 있으며, 다양한 분야에서 좋은 성능을 낸다는 점에서 매우 장점이 많은 알고리즘입니다.

단점은 트리 기반의 앙상블 알고리즘은 하이퍼파라미터가 많아 튜닝을 위한 시간이 많이 소모된다는 것입니다. (속도 자체는 다른 알고리즘에 비해 빠릅니다.) 또한 하이퍼파라미터의 조정을 통한 성능의 향상이 비교적 미비하다는 단점을 가지고 있습니다.

4. Boosting

부스팅(Boosting) 알고리즘은 여러 개의 약한 학습기(weak learner)를 순차적으로 학습-예측하며 잘못 예측한 데이터에 가중치 부여를 통해 오류를 개선해 나가면서 학습하는 방식입니다.

계속해서 분류기에게 가중치를 부스팅하면서 학습을 진행하기에 부스팅 방식으로 불립니다.

기존 Boosting 방법은 순차적인 연산이 필수적이므로 병렬 연산이 불가능합니다. 그렇기에 대용량 데이터셋에서는 학습 시간이 매우 많이 필요할 수 있습니다.

부스팅의 대표적인 알고리즘은 AdaBoostGradient Boost 가 있고, 최근 성능면에서 인정을 받아 가장 많이 사용하는 부스팅 계열 알고리즘으로 XGBoostLightGBM 이 있습니다. 그 외에도 CatBoost와 같은 알고리즘이 있습니다.

4-1. AdaBoost

에이다 부스트(AdaBoost) 는 Adaptive boosting의 약자로 오류 데이터에 가중치를 부여하며 부스팅을 수행하는 대표적인 알고리즘입니다.

메인 아이디어는 잘못 분류한 데이터에 가중치를 부여하여, 다음 분류기는 이를 더 잘 분류하게 만드는 것입니다. 최종적으로는 이 분류기를 합쳐 최종 분류기를 만듭니다. (분류 문제에 대하여)

오류 데이터에 가중치를 부여하기 때문에 이상치(outlier)에 민감합니다.

4-2. Gradient Boost

그래디언트 부스트(Gradient Boost Machine) 알고리즘은 AdaBoost와 거의 유사합니다. 하지만 가중치 업데이트를 경사하강법(Gradient Descent) 로 한다는 점이 다릅니다.

평균적으로 랜덤 포레스트보다 좋은 예측 성능을 가지지만, 하이퍼파라미터 튜닝 노력이 필요하고 그만큼 수행 시간이 오래걸린다는 단점도 있습니다. 순차적인 진행때문에 병렬 수행이 불가능하다는 단점도 있습니다. 성능면에 초점을 두어 많은 GBM 기반 알고리즘이 연구되었고, 그 중 가장 많이 사용하는 것이 아래 두 알고리즘입니다.

4-3. XGBoost

XGBoost(eXtra Gradient Boost) 는 GBM에 기반하는 알고리즘이며, 여러 가지 장점을 가진 알고리즘입니다. GBM에 비해 빠르고, 과적합 규제 등의 장점을 가집니다. 그 외에도 분류/회귀 모두 예측 성능이 우수하고, 자체 내장 교차 검증, 결손값 처리 등의 장점이 있습니다.

병렬 CPU를 이용하여 GBM보다 빠른 수행을 합니다. 반대로 말하면 속도를 기대하려면 multi-CPU core가 필요합니다. 이 외에도 tree pruning 등의 다양한 기능을 통해 속도를 향상시켰습니다.

XGBoost는 GBM보다는 빠르지만 여전히 느린 알고리즘입니다. 심지어 GridSearchCV를 이용하여 하이퍼파라미터 튜닝을 수행하면 시간이 너무 오래 걸립니다.

4-4. LightGBM

LightGBM 은 이름에서 알 수 있듯이 Light한 GBM입니다.

XGBoost에 비해 훨씬 빠르며, 메모리 사용량도 상대적으로 적습니다. 예측 성능 자체도 큰 차이는 없습니다. 하지만 적은 수의 데이터셋에는 과대적합이 발생하기 쉽다는 단점이 있습니다. 적다는 기준은 애매하나 공식 문서에는 10000건 이하의 데이터셋이라고 기술하고 있습니다.

알고리즘의 메인 아이디어는 GBM 계열의 트리 분할 방법에서 트리 균형 맞추는 과정을 생략하며 성능을 높였다는 점입니다. 대부분의 트리 기반 알고리즘은 트리의 깊이를 효과적으로 줄이기 위해 균형 트리 분할(Level Wise) 방식을 사용합니다. 균형 잡힌 트리는 과대적합에 강하지만 시간 비용이 큽니다.

LightGBM에서는 리프 중심 트리 분할(Leaf Wise) 방식을 사용해 비대칭이지만 예측 오류 손실 값을 줄이는 방식을 선택하여 트리를 분할합니다. 그렇기에 빠르고, 좋은 성능을 가질 수 있는 것입니다.

4-5. CatBoost

CatBoost 는 범주형 변수를 위해 만든 Boosting 알고리즘입니다. 범주형 변수의 경우에는 원-핫 인코딩을 할 경우에 많은 수의 특성이 생기기에 부스팅 알고리즘을 사용하는 경우, 매우 오랜 시간이 걸립니다. 그렇기에 범주형 변수를 자동으로 처리하기 위해 만든 알고리즘입니다.

아직 경험이 부족해서 사용하는 컴페티션을 본 적은 없습니다.

5. Stacking & Blending

Stacking과 Blending은 거의 같지만, 분류하는 경우도 있어 따로 서술했습니다.

5-1. Stacking (Stacked generalization)

스태킹 알고리즘 시각화 | 출처 :
http://supunsetunga.blogspot.com/

스태킹(Stacking) 또는 stacked generalization으로 알려진 기법입니다.

현실 모델에 적용하는 경우는 적으나, 대회에서 높은 순위를 위해 많이 사용됩니다.

가장 핵심 아이디어는 머신러닝 알고리즘으로 훈련 데이터셋을 통해 새로운 데이터셋을 만들고, 이를 데이터셋으로 사용하여 다시 머신러닝 알고리즘을 돌리는 것입니다. 보통은 서로 다른 타입의 모델들 을 결합합니다.

스태킹에는 총 2가지 종류의 모델이 필요합니다.

  1. 개별적인 기반 모델 : 성능이 비슷한 여러 개의 모델
  2. 최종 메타 모델 : 기반 모델이 만든 예측 데이터를 학습 데이터로 사용할 최종 모델

다시 정리해서 말하면 여러 개의 개별 모델들이 생성한 예측 데이터를 기반으로 최종 메타 모델이 학습할 별도의 학습 데이터 세트와 예측할 테스트 데이터 세트를 재 생성하는 기법입니다.

모델을 통해 input을 만들고, 다시 모델에 넣는 구조때문에 meta-model 이라고도 부릅니다.

Stacking에는 다양한 유형이 있고, 내용 자체가 직관적으로 이해하기 힘듭니다. 이 부분에 대해 자세한 내용은 2부에 다루겠습니다.

5-2. Blending

Blending 은 스태킹과 매우 유사한 방법입니다. 하지만 보다 간단하고, 정보누설의 위험을 줄입니다. 일부는 Stacking과 Blending을 혼용해서 사용합니다. (대부분은 스태킹과 같은 의미로 사용하는 것 같습니다.)

과정 자체는 거의 같습니다. 차이점이 있다면 Stacking에서는 cross-fold-validation을 사용하고, Blending은 holdout validation을 사용합니다.

그렇기 때문에 Blending의 결과는 holdout set에 과대적합이 된 결과를 얻을 가능성이 높습니다.

6. Conclusion

결과를 높이기에는 좋은 방법이지만, 해석 가능성을 낮추는 방법이기도 합니다. 그렇기에 과정을 중시하는 곳에서는 선호하지 않는 방법입니다.

하지만 컴페티션에 있어서는 정확도가 높다는 것은 매우 중요합니다. 캐글을 해보신 분이라면 0.1%의 정확도 향상도 얼마나 대단한 것인지 아실겁니다. 또한 의료 분야 등 정확도가 반드시 높아야 하는 경우에는 필요합니다. 과정보다는 결과가 중요한 곳이 있기 때문입니다.

다음 포스팅에서는 분야별로 구체적인 내용에 대해서 다뤄보겠습니다. Part2에서 뵙겠습니다. :-)

Reference

세상에는 좋은 자료가 너무 많습니다. 시간이 된다면 아래 링크와 책 모두 읽는 것을 추천합니다.

 

 

( 위 쪽에 출처가 써지지 않아서 하단부에 붙입니다. )

 출처 : https://subinium.github.io/introduction-to-ensemble-1/

'데이터사이언스 > MachineLearning' 카테고리의 다른 글

Ensemble 2/2 (앙상블)  (0) 2020.04.23
: