Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 번역
- autoencoder
- R #한글화프로젝트 #캐글코리아
- 한글화프로젝트
- Kaggle
- kaggle-kr
- 커리큘럼
- R #번역 #kaggle #캐글 #캐글코리아
- 캐글코리아
- 번역커널
- 한글화프로젝트 #캐글코리아
- 모각캐
- KGNG
- KaggleTip
- KQNG
- 필사
- Python
- 이유한
- kaggle korea
- 시계열
- timeseries
- Kaggle #Tips #Kaggle-KR
- 캐글
- Tips
Archives
- Today
- Total
Kaggle-KR
Statoil/C-CORE 튜토리얼 - Image recognition, binary classfication 본문
Kaggle 한글 커널 with Python/개인 커널
Statoil/C-CORE 튜토리얼 - Image recognition, binary classfication
알 수 없는 사용자 2018. 7. 1. 23:20- 안녕하세요!. 이번에는 빙하와 배를 구분하는 문제를 풀어보려고 합니다. 캐나다 동쪽 해안에서는 표류하는 빙하가 자칫 위험이 될 수 있다고 합니다. 그래서 많은 연구기관, 기업들이 이 위험을 피할 방방법을 찾기 위해 노력하고 있다고 하네요. 위성사진을 이용해 지속적으로 모니터링을 한다고 합니다. Statoil 이라는 국제 에너지 기업과 C-CORE 라는 위성 기업이 이 컴퍼티션을 주최하였는데, 이들이 제공한 위성사진을 가지고 배(ship)와 빙하(iceberg)를 잘 구분해내는 머신러닝, 딥러닝 모델을 세우는 게 목표입니다.
- 이번 컴퍼티션은 image classification 이며, binary classfication 입니다. 그래서 본 튜토리얼은 이 컴퍼티션을 공부하며 keras를 사용한 2-D convolutional neural network(CNN) 을 배울 것입니다. 그리고 plotly 도 만나보실 겁니다.
- plotly 는 interactive 한 visualization 을 가능케하는 라이브러리입니다. plotly 사이트에 가입하면, plotly 에서 관리하는 클라우드에 자신이 그린 이미지(graph, plot)을 관리할 수 있습니다.
- keras 는 유명한 딥러닝 프레임워크로, 딥러닝 모델을 쉽고 빠르게 구축하게 합니다. 그럼 시작하겠습니다.
In [1]:
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from matplotlib import pyplot as plt
#plt.rcParams['figure.figsize'] = 12, 8
%matplotlib inline
#Take a look at a iceberg
import plotly.offline as py
import plotly.graph_objs as go
from plotly import tools
py.init_notebook_mode(connected=True) # plotly 를 jupyter notebook 에 사용하려면 이 커맨드를 입력해야 합니다.
- 본 컴퍼티션의 데이터는 json 형태로 주어져 있습니다. pandas 는 json type 의 데이터도 쉽게 읽어낼 수 있습니다.
In [2]:
#Load data
train = pd.read_json("../input/data/processed/train.json")
test = pd.read_json("../input/data/processed/test.json")
train.inc_angle = train.inc_angle.replace('na', 0)
train.inc_angle = train.inc_angle.astype(float).fillna(0.0)
print("done!")
In [3]:
train.head()
Out[3]:
- 보시게 되면, id가 있고, feature 로는 band_1, band_2, inc_angle 이 있습니다. 우리가 맞추려는 target 은 is_iceberg 이며 1 == iceberg, 0 == ship 입니다.
- https://www.kaggle.com/c/statoil-iceberg-classifier-challenge#Background 에 보시면 대략적인 데이터 설명이 있습니다. 위성사진은 위성에서 쏜 radar 가 특정 object 를 만나면 bounce 하여 다시 돌아오게 되는 데 이를 image로 저장한 것이라고 합니다.
- 이 때, object 가 solid 할수록(land, islands, sea ice, icebergs, ships) 더 강한 rader energy 가 reflection 하므로 실제 이미지에서 밝게 나온다고 하네요. 이 이너지를 backscatter 라고 합니다.
- 이 backscatter 는 주변 환경에 영향을 받는데, 주변에 바람이 강할수록 이미지가 밝아지고, 바람이 약할수록 이미지가 어두워진다고 하는 군요. 아마 강한 바람에 담긴 여러 분자들의 운동에너지가 reflection 되는 radar 에 담기나 봅니다.
- 지금 주어진 이미지를 찍는 위성은 Sentinel-1 인데 측방 감시 레이더라고 합니다. 즉 특정 angle 로 이미지를 보는 것이죠. 주어진 inc_angle 은 band_1, band_2(이미지) 를 바라보는 angle을 의미합니다. 그러니까 band_1, band_2 는 상대적인 이미지라고 볼 수 있겠네요.
- 일반적으로 높은 incidence angle 일수록, ocean background 가 어두워진다고 합니다.
- band_1 과 band_2 는 HH(transmit/receive horizontally)와 HV(transmit horizontally and receive vertically) 로 얻어진 radar 데이터를 정제하여 얻은 coefficient 들이며, 이미지로 생각하시면 됩니다.
- 당연한 이야기지만, 어떤 컴퍼티션이든 domain knowledge 가 필요하긴 합니다. 아래 커널에 보시면, 관련 정보가 모여있으니 한번 확인해보셔도 좋을 듯 합니다. https://www.kaggle.com/dimitrif/domain-knowledge
- 캐글을 하게 되면, domain knowlegde가 있으면 도움이 되는 경우가 많습니다. 하지만 없다고 해서 못하는 것이 아닙니다. domain knowledge를 잘 몰라도 데이터 속에서 domain knowledge 를 찾아내는 것도 재미니까요!.
- 이제 band_1과 band_2를 75x75 로 바꾸고, 2D CNN 학습을 위하여 [N, height, width, channel]의 차원을 가지게 바꿔줍니다. np.newaxis 를 사용하면 쉽게 할 수 있습니다.
In [4]:
#Generate the training data
#Create 3 bands having HH, HV and avg of both
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)
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)
- 이제 한번 ship, iceberg 가 가지는 band_1, 2가 어떻게 다른지 확인해봅시다.
- plotly 의 surface plot 을 활용하면, 멋진 3-D plot 을 얻을 수 있으며, 마우스로 이리저리 움직여볼 수 있습니다.
- plotly 경우 다른 튜토리얼에서 한번 다뤄보도록 하겠습니다. 처음에는 사용법이 어려워보이지만, documentation 및 example 이 잘 되어 있어서 반복해 따라하다보면 익숙해집니다. https://plot.ly/api/ 에 들어가시면 python, matlab, R, javascript 로 plotly를 쓰는 방법이 잘 나와 있습니다.
- 그리고 동일한 band_1 과 band_2 를 2D 로도 그려보겠습니다. 이것은 matplotlib 의 imshow 로 쉽게 그릴 수 있습니다.
- Python visualization 은 matplotlib, seaborn, plotly 가 대표적인데, 셋다 다룰 줄 아시면 이쁘고 멋진 데이터 분석 보고서를 작성하실 수 있습니다.
In [17]:
def plot_contour_2d(band1, band2, label):
fig = tools.make_subplots(rows=1, cols=2, specs=[[{'is_3d': True}, {'is_3d': True}]])
fig.append_trace(dict(type='surface', z=band1, colorscale='RdBu',
scene='scene1', showscale=False), 1, 1)
fig.append_trace(dict(type='surface', z=band2, colorscale='RdBu',
scene='scene2', showscale=False), 1, 2)
fig['layout'].update(title='3D surface plot for "{}" (left is from band1, right is from band2)'.format(label), titlefont=dict(size=30), height=800, width=1200)
py.iplot(fig)
fig, ax = plt.subplots(1, 2, figsize=(16, 10))
ax[0].imshow(X_band_1[num, :, :])
ax[0].set_title('Image from band_1', fontsize=15)
ax[1].imshow(X_band_2[num, :, :])
ax[1].set_title('Image from band_2', fontsize=15)
plt.show()
- 아래 두 band_1, band_2 는 ship 을 나타냅니다.
- 현재 이미지는 75x75 인데, 그래프는 x, y 축으로 75 x 75 grid 가 그려지고, 각 점의 z value 가 band_1 또는 band_2 가 됩니다.
- 빨간색 봉우리가 ship 의 모양을 나타내며, HH, HV 에 따라 radar 를 보는 방향이 달라 조금 다르게 나오지만, 결국 같은 것을 나타냄을 알 수 있습니다.
- 제법 깔끔한 이미지가 나옵니다.
In [19]:
num = 0
label = 'iceberg' if (train['is_iceberg'].values[num] == 1) else'ship'
plot_contour_2d(X_band_1[num,:,:], X_band_2[num,:,:], label)
In [7]:
num = 100
label = 'iceberg' if (train['is_iceberg'].values[num] == 1) else'ship'
plot_contour_2d(X_band_1[num,:,:], X_band_2[num,:,:], label)
- 아래 두 set 은 iceberg 를 나타냅니다.
- 붉은 봉우리 이외에도 여러 뾰족한 봉우리들이 보입니다. iceberg 옆에 떠다니는 자그마한 iceberg 일 수도 있겠네요.
In [8]:
num = 2
label = 'iceberg' if (train['is_iceberg'].values[num] == 1) else'ship'
plot_contour_2d(X_band_1[num,:,:], X_band_2[num,:,:], label)
In [9]:
num = 125
label = 'iceberg' if (train['is_iceberg'].values[num] == 1) else'ship'
plot_contour_2d(X_band_1[num,:,:], X_band_2[num,:,:], label)
- 자 이제, 본격적으로 딥러닝을 해봅시다. 데이터셋이 준비되어 있으니, 신경망 모델을 설계하면 됩니다.
- 이미지니까 2D CNN 을 가지고 해보겠습니다. keras 에는 딥러닝에 사용되는 여러 layer 들이 내장되어 있어서 우리는 그저 블록처럼 쌓기만 하면 됩니다.
- 김태영의 케라스 블로그 https://tykimos.github.io/ 에 가면 케라스에 대해 배워볼 수 있으며, 케라스 본 documentation 도 자세한 설명 및 예제가 많으므로 공부하기 좋습니다. 구글링하시면 많은 깃허브들도 있으니 마음껏 즐기세요!
In [10]:
#Import Keras.
from matplotlib import pyplot
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 GlobalMaxPooling2D
from keras.layers.normalization import BatchNormalization
from keras.layers.merge import Concatenate
from keras.models import Model
from keras import initializers
from keras.optimizers import Adam
from keras.callbacks import ModelCheckpoint, Callback, EarlyStopping
- 본격적으로 모델을 만듭니다. 한번 훑어보세요. 일관적인 패턴이 보이시지 않나요? 용어만 아셔도 어떤 네트워크를 만들었는 지 감이 오실 수 있습니다.
- callback 을 사용하여, loss 가 더 줄지 않을 때 학습을 멈춰줍니다.
In [11]:
#define our model
def getModel():
#Building the model
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 Layers
gmodel.add(Dense(512))
gmodel.add(Activation('relu'))
gmodel.add(Dropout(0.2))
#Dense Layer 2
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]
file_path = ".model_weights.hdf5"
callbacks = get_callbacks(filepath=file_path, patience=5)
- 더 나은 모델을 위하여 바로 test를 하는 것이 아니라, 기존 train set 을 train, valid로 나눠서 먼저 모델을 평가해봅니다.
- Sklearn 내장 함수인 train_test_split 을 이용하면 쉽게 할 수 있습니다.
In [12]:
target_train=train['is_iceberg']
X_train, X_valid, y_train, y_valid = train_test_split(X_train, target_train, random_state=1, train_size=0.8)
- 학습을 진행하겠습니다. 블로그에 게시해야하니 epoch 은 10으로 하겠습니다. 실제로 실습하실 때는 더 큰 epoch 으로 하셔서 좋은 결과 얻으세요!
In [13]:
#Without denoising, core features.
gmodel=getModel()
gmodel.fit(X_train, y_train,
batch_size=24,
epochs=10,
verbose=1,
validation_data=(X_valid, y_valid),
callbacks=callbacks)
Out[13]:
- 저장된 weight 를 다시 불러와서 validation set 에 대한 loss 와 accuracy 를 확인합니다.
In [14]:
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 [15]:
predicted_test = gmodel.predict_proba(X_test)
In [16]:
submission = pd.DataFrame()
submission['id']=test['id']
submission['is_iceberg']=predicted_test.reshape((predicted_test.shape[0]))
submission.to_csv('sub.csv', index=False)
- 고생하셨습니다. 이제 제출하시면 됩니다. 더 공부할 것들이 커널에 많습니다. 즐겁게 배웁시다.
- 이 커널은 https://www.kaggle.com/devm2024/keras-model-for-beginners-0-210-on-lb-eda-r-d 과 https://www.kaggle.com/kmader/exploring-the-icebergs-with-skimage-and-keras 를 참고해서 만들었습니다. 두 캐글러분들께 감사드립니다.
'Kaggle 한글 커널 with Python > 개인 커널' 카테고리의 다른 글
Bike Sharing Demand @h0609zxc (2) | 2019.05.19 |
---|---|
Quora Question Pair - Data Analysis & XGBoost Starter (0.35460 LB) (0) | 2018.07.15 |
타이타닉 튜토리얼 2 - Exploratory data analysis, visualization, machine learning (9) | 2018.06.28 |
타이타닉 튜토리얼 1 - Exploratory data analysis, visualization, machine learning (7) | 2018.06.28 |
PUBG-SR-GunSound Classification Tutorial (7) | 2018.06.03 |
Comments