Multi-view image deep learing with CNN-LSTM
https://machinelearningmastery.com/cnn-long-short-term-memory-networks/
Objectives:
Axial, Sagittal, Coronal 3가지 Input을 동시에 받아, classification을 해야 할 일이 생김
1. 기존의 CNN은 하나의 이미지밖에 받지 못한다.
2. 3개의 Input을 동시에 받아 각자 처리하는 CNN을 ensemble로 묶기엔 모델이 너무 커진다.
# 3개의 Input을 받아서 Fully conntected layer단만 연결하여 loss를 주는 방법도 있는 것 같은데..
이미지 3장을 연속으로 받아서 RNN으로 Prediction 하면 더 편할 것 같아서
CNN-RNN을 공부해볼 겸 포스팅을 시작한다.
이 글에서 RNN은 GRU도 사용할 수 있지만, LSTM을 사용한다.
Input 데이터가 다수의 Image나 Video처럼,
time까지 고려했을 때 3차원인 데이터가 들어오는 경우 기본적인 RNN 알고리즘으로는 처리하기 어렵다.
따라서 CNN을 통해서 2-dimension 이미지를 1차원의 vector로 만들어준 후, RNN을 적용함으로써
RNN 분석을 가능하게 한다.
RNN의 데이터 구조는 아주 쉽게 말하면 다음과 같다.
- 하나의 샘플에 해당되는 x는 t개의 벡터를, y는 t개의 값을 가진다.
(t = time point)
따라서 한 point에 2개의 값을 가지는 경우의 예를 아래와 같이 들 수 있다.
sample_size = 12800
x_seed = [[1,1], [0,0], [0,0], [0,0], [0,0], [0,0]]
y_seed = [1, 0.8, 0.6, 0, 0, 0]
x_train = np.array( [[x_seed] * sample_size]).reshape(sample_size, len(x_seed), 1)
y_train = np.array( [[y_seed] * sample_size]).reshape(sample_size, len(y_seed), 1)
model = Sequential()
model.add(SimpleRNN(1, activation='tanh', return_sequences = True) )
model.add(TimeDistributed(Dense(1, activation = "sigmoid")))
model.compile(loss = "mse", optimizer = "rmsprop")
model.fit(x_train, y_train, epochs = 10, batch_size = 32, verbose = T)
결국 CNN-LSTM의 구조는
x_seed = [ [[1,1],[1,1]],
[[0,0], [0,0]],
[[0,0], [0,0]],
[[0,0], [0,0]],
[[0,0], [0,0]],
[[0,0], [0,0]]]
위와 같이 2차원의 matrix가 time-point 수 만큼 존재하는 Input에 대하여,
x_seed = [[1,1], [0,0], [0,0], [0,0], [0,0], [0,0]]
과 같이, 1차원 벡터가 t개 존재하는 RNN이 입력받을 수 있는 형태로 바꾸는 것이 목적이다.
위 이미지와 구조는 (https://machinelearningmastery.com/cnn-long-short-term-memory-networks/) 에서 가져옴.
결국 CNN Model은 time-step별 2D 이미지에서 1D feature vector로, Feature extraction의 역할을 수행하는 것이며
아래 LSTM (RNN)은 Feature를 time-step별 Feature들을 통해 Output을 내는 역할을 수행하게 되는 것이다.
가장 쉬운 방법은 CNN 모델을 따로 구성하고,
CNN 모델을 TimeDistributed() function으로 감싸는 것.
CNN = Sequential()
CNN.add(Conv2D(...))
CNN.add(MaxPooling2D(...))
CNN.add(Flatten())
# define LSTM model
model = Sequential()
model.add(TimeDistributed(CNN, ...))
model.add(LSTM(..))
model.add(Dense(...))
예를 들면, 다음과 같은 구성도 가능하다.
CNN = Sequential()
RESNET = keras.applications.resnet50.ResNet50(include_top=False,
weights='imagenet', input_tensor=None,
input_shape=(224,224,3), pooling=None, classes=2)
CNN.add(RESNET)
CNN.add(MaxPooling2D())
CNN.add( Flatten() )
model = Sequential()
model.add(TimeDistributed(CNN))
model.add(LSTM(7, activation='tanh', return_sequences = False) )
model.add(Dense(2, activation='relu'))
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])