이번 필사 주제는 Statoil/C-CORE Iceberg Classifier Challenge 이다.
이미지 데이터로 빙하(iceberg)인지, 선박(ship)인지 구분하는 이진 분류를 사용하는 주제이다.
데이터 설명을 보면, 주어진 데이터는 특정 발생 각도에서 신호 펄스를 전송한 다음 다시 신호 펄스를 재코딩하여 보낸 백스케터( backscatter) 계수라고 한다.
흠.. 데이터 설명부터가 어렵다고 지레 겁먹진 말고, 차근 차근 따라가보자.
In [2]:
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from os.path import join as opj
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import pylab
plt.rcParams['figure.figsize'] = 10,10
%matplotlib inline
import plotly.offline as py
import plotly.graph_objs as go
py.init_notebook_mode(connected=True)
# import keras
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Dense, Dropout, Input, Flatten, Activation
from keras.layers import GlobalAveragePooling2D
from keras.layers.normalization import BatchNormalization
from keras.layers.merge import Concatenate
from keras import initializers
from keras.optimizers import Adam
from keras.callbacks import ModelCheckpoint, Callback, EarlyStopping
데이터 불러오기
In [3]:
train = pd.read_json('../data/statoil-iceberg-classifier-challenge/train.json')
test = pd.read_json('../data/statoil-iceberg-classifier-challenge/test.json')
- Sentinet -1 sat는 지구 위 약 680Km에 있다. 특정 발생 각도에서 신호 펄스를 전송한 다음 다시 신호 펄스를 재코딩한다.기본적으로 그러한 반사신호를 백스케터라고 부른다. 우리가 받은 데이터는 backscatter 계수이다.
- ip : 특정 픽셀의 발생 각도
- ic : 이미 중심에 대한 입사각
- K : 상수
In [4]:
# RGB와 동등하게 3개의 채널을 만들기 위해 2개의 영역과 2개 영역의 평균으로 채널을 구성한다.
X_band_1 = np.array([np.array(band).astype(np.float32).reshape(75,75) for band in train ["band_1"]])
X_band_2 = np.array([np.array(band).astype(np.float32).reshape(75,75) for band in train ["band_2"]])
X_train = np.concatenate([X_band_1[:, :, :, np.newaxis], X_band_2[:,:,:,np.newaxis], ((X_band_1+X_band_2)/2)[:,:,:,np.newaxis]], axis=-1)
차트 확인
In [5]:
# iceberg를 가져온다.
def plotmy3d(c, name):
data=[
go.Surface(
z=c
)
]
layout = go.Layout(
title = name,
autosize= False,
width=700,
height=700,
margin=dict(
l=65,
r=50,
b=65,
t=90
)
)
fig= go.Figure(data=data, layout=layout)
py.iplot(fig)
plotmy3d(X_band_1[12,:,:], 'iceberg')
- 레이더 데이터에서 볼 때 빙산의 모양은 위에 보이는 것 처럼, 산과 같다.
- 이것은 실제 이미지가 아니라 레이더에서 산란하기 때문에 모양은 봉우리나 왜곡이 될 것이다. 배의 모양은 점처럼 될수도 있고, 길쭉한 점처럼 될 수도 있다.
- 여기서부터 구조적 차이가 발생하고 우리는 CNN을 이용하여 이러한 차이를 이용할 수 있다.
In [6]:
plotmy3d(X_band_1[14, :, :], 'Ship')
배는 길쭉한 점으로 보인다. 우리는 배의 형상을 시각화할 만한 이미지 해상도가 별로 없다. 그러나 CNN은 이런 것을 돕는다. 그래서 keras를 사용한 CNN으로 구축해보자
keras를 사용한 CNN 구축
In [11]:
def getModel():
# 모델 세우기
gmodel = Sequential()
# Conv Layer 1
gmodel.add(Conv2D(64, kernel_size=(3,3), activation='relu', input_shape=(75,75,3)))
gmodel.add(MaxPooling2D(pool_size=(3,3), strides=(2,2)))
gmodel.add(Dropout(0.2))
# Conv Layer 2
gmodel.add(Conv2D(128, kernel_size=(3,3), activation='relu'))
gmodel.add(MaxPooling2D(pool_size=(2,2), strides=(2,2)))
gmodel.add(Dropout(0.2))
# Conv Layer 3
gmodel.add(Conv2D(128, kernel_size=(3,3), activation='relu'))
gmodel.add(MaxPooling2D(pool_size=(2,2), strides=(2,2)))
gmodel.add(Dropout(0.2))
# Conv Layer 4
gmodel.add(Conv2D(64, kernel_size=(3,3), activation='relu'))
gmodel.add(MaxPooling2D(pool_size=(2,2), strides=(2,2)))
gmodel.add(Dropout(0.2))
# Flatten the data for upcoming dense layers
gmodel.add(Flatten())
#Dense Layer2
gmodel.add(Dense(256))
gmodel.add(Activation('relu'))
gmodel.add(Dropout(0.2))
#Sigmoid Layer
gmodel.add(Dense(1))
gmodel.add(Activation('sigmoid'))
mypotim=Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0)
gmodel.compile(
loss = 'binary_crossentropy',
optimizer=mypotim,
metrics=['accuracy'])
gmodel.summary()
return gmodel
def get_callbacks(filepath, patience=2):
es = EarlyStopping('val_loss', patience=patience, mode='min')
msave = ModelCheckpoint(filepath, save_best_only=True)
return [es, msave]
In [14]:
file_path = ".model_weights.hdf5"
callbacks = get_callbacks(filepath=file_path, patience=5)
In [16]:
target_train=train['is_iceberg']
X_train_cv, X_valid, y_train_cv, y_valid = train_test_split(X_train, target_train, random_state=1, train_size=0.75)
In [17]:
gmodel = getModel()
gmodel.fit(X_train_cv, y_train_cv,
batch_size=24,
epochs=50,
verbose=1,
validation_data=(X_valid, y_valid),
callbacks=callbacks)
Out[17]:
In [18]:
gmodel.load_weights(filepath=file_path)
score = gmodel.evaluate(X_valid, y_valid, verbose=1)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
제출용 데이터 생성
In [20]:
X_band_test_1 = np.array([np.array(band).astype(np.float32).reshape(75,75) for band in test["band_1"]])
X_band_test_2 = np.array([np.array(band).astype(np.float32).reshape(75,75) for band in test["band_2"]])
X_test = np.concatenate([X_band_test_1[:,:,:, np.newaxis], X_band_test_2[:,:,:, np.newaxis],((X_band_test_1+X_band_test_2)/2)[:,:,:,np.newaxis]], axis=-1)
predicted_test = gmodel.predict_proba(X_test)
In [26]:
submission = pd.DataFrame()
submission['id'] = test['id']
submission['is_iceberg'] = predicted_test.reshape((predicted_test.shape[0]))
submission.to_csv('sub.csv', index=False)
'Competition > Kaggle' 카테고리의 다른 글
[kaggle][필사] New York City Taxi Duration (1) (0) | 2020.10.02 |
---|---|
[kaggle][필사] Costa Rican Household Proverty (3) (0) | 2020.09.22 |
[kaggle][필사] Costa Rican Household Proverty (2) (0) | 2020.09.20 |