statoil iceberg classifier challenge
📌 데이터 탐색 -> 모델 구성 -> 모델 훈련 -> 평가 -> 예측
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
# notebook을 실행한 브라우저에서 바로 그림을 볼 수 있게 해주는 것
#Take a look at a iceberg
# plotly -> 시각화 툴, matplotlib보다 더 세련된 데이터 시각화 툴
# 코드가 더 간결
import plotly.offline as py
import plotly.graph_objs as go
from plotly import tools
#Ignore warnings
# 경고메시지 무시하고 숨기기
import warnings
warnings.filterwarnings('ignore')
py.init_notebook_mode(connected=True)
# plotly 를 jupyter notebook 에 사용하려면 이 커맨드를 입력해야 합니다
7z 으로 압축되어 있기 때문에 이것을 풀어주어야 한다.
!pip install py7zr
import py7zr
import os
if not os.path.exists('/kaggle/train/') :
os.makedirs('/kaggle/train/')
if not os.path.exists('/kaggle/test/') :
os.makedirs('/kaggle/test/')
with py7zr.SevenZipFile("/kaggle/input/statoil-iceberg-classifier-challenge/train.json.7z", 'r') as archive:
archive.extractall(path="/kaggle/train")
with py7zr.SevenZipFile("/kaggle/input/statoil-iceberg-classifier-challenge/test.json.7z", 'r') as archive:
archive.extractall(path="/kaggle/test")
for dirname, _, filenames in os.walk('/kaggle'):
for filename in filenames:
print(os.path.join(dirname, filename))
압축으로 풀어준 train, test data들을 각각 변수에 넣어준다.
train = pd.read_json('/kaggle/train/data/processed/train.json')
test = pd.read_json('/kaggle/test/data/processed/test.json')
이것을 head()를 통해 보여줄 수 있다.
train.head()
# Bar Charts로 보여주기
이를 통해 데이터에서 볼 수 있는 것을 알 수 있다.
=> id, band_1, band_2, inc_angle, is_iceberg
train['inc_angle'].value_counts()
value_count()는 개수를 카운트 한다
ex ) A A A B B C --> A 3 B 2 C 1
"na"로 누락된 데이터를 0으로 바꾸어 준다.
train.inc_angle = train.inc_angle.replace('na',0)
train['inc_angle'].value_counts()
band_1 과 band_2가 HH,HV 2채널로 이루어져 있기 때문에 3채널로 만들어준다.
# reshape(75 ,75)=> 75개줄로 75개씩
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"]])
#np.concatenate해서 새로운 채널을 하나더 만들어주는 것이다 컬러이미지이기 때문에
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)
#np.nexaxis = None, indexingㅇ로 길이가 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)
빙산일 때와 선박일 때 데이터가 어떻게 다른지 확인해 보아야 한다.
이때 0,1,3,4는 선박(0), 2번은 빙산(1)인 것을 확인할 수 있다.
시각화 하는 plot_contour_2d 함수를 만든다.
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_r',
scene='scene1', showscale=False), 1, 1)
fig.append_trace(dict(type='surface', z=band2, colorscale='RdBu_r',
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)
#여기 밑에 부분은 이제 z축 없이 위에서 보는 부분 보여주는 코드
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()
위에서 확인했던 선박인 0번과 빙산인 2번을 확인해보자
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)
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)
먼저 Keras를 import 해준다.
#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
모델을 만들어 주는 함수를 만든다.
#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)))
# 64 = 컨볼루션 필터 수(연결되어있는 뉴런 수)
# relu = 0보다 작으면 0반환, 0보다 크면 그 값 그대로 반환
# 사이즈 75*75 컬러사진 ==> 3
gmodel.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 2)))
# input size를 줄인다. 특징을 뽑아서
# overfitting 조절한다. 쓸데없는 파라미터 수 줄어들어서 train만 높은 성능x
# 특징 잘 뽑아낸다. pooling 했을 때 특정한 모양 더 잘 인식가능
gmodel.add(Dropout(0.2))
# overfitting해소, 일부로 덜 독똑하게 만든다
#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
#Adam 은 모델을 최적화 시켜주는 기능을 한다,
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)
이때 callback을 사용하여, loss가 더 줄지 않을 때 학습을 멈춰준다.
💡 EarlyStopping
: 더 이상 개선의 여지가 없을 때 학습을 종료시키는 콜백함수
- ‘val_loss’를 관찰한다.
- patience : 개선이 없다고 바로 종료 하지 않고 개선이 없는 에포크를 얼마나 기다려 줄 것인가
ex) patience = 10, 개선 없는 에포크 10번째 지속될 경우 학습 종료- mode : 관찰 대상에 대해 개선이 없다고 판단하기 위한 기준 지정
- min = 관찰하고 있는 항목이 감소되는 것을 멈출 때 종료
💡 ModelCheckpoint
: 모델을 저장할 때 사용되는 콜백함수
- filepath : 모델을 저장할 경로
- save_best_only : True, False
- True인 경우 ,monitor되고 있는 값을 기준으로 가장 좋은 값으로 모델 저장
- False인 경우, 매 에포크마다 모델이 filepath{epoch}으로 저장 (model0, model1, …)
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)
# train_test_split 으로 기존 train set을 train, vaild로 나누기
gmodel=getModel()
gmodel.fit(X_train, y_train,
batch_size=24,
epochs=10,
verbose=1,
validation_data=(X_valid, y_valid),
callbacks=callbacks)
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])
predicted_test = gmodel.predict_proba(X_test)
predicted_test
submission = pd.DataFrame()
submission['id']=test['id']
submission['is_iceberg']=predicted_test.reshape((predicted_test.shape[0]))
submission.to_csv('sub.csv', index=False)
sub.csv 파일을 열어보면
다음과 같은 값이 저장된다.
시각화 툴 plotly, matplotlib보다 간결
콜백 함수 EarlyStopping : 더 이상 개선 여지없을 때 학습 종료
콜백 함수 : Modelcheckpoint : 모델 저장할 때 사용
모델을 극단적으로 바꾸어 봤을 때 어떤 변화?
실행하는 것도 중요하지만 깊이 있게 분석