{"cells":[{"metadata":{"_uuid":"1634aad69553b73cfca7e59cf65518a934198a86"},"cell_type":"markdown","source":"# This kernel use simple transfer learning to detect ship exist or not\n*** For biginner, can get about 85% accuracy train on 10 epoch (~20min one epoch no GPU, ~100s one epoch have GPU)**\n* Use ResNet50 to do transfer learning \n* Load 5000 picture to be training data \n* Split 4000 training set , 1000 validate set  (0.2%)\n* Image size 256 x 256, RGB data\n* Using ImageGenerator to do data augumatation"},{"metadata":{"_uuid":"8dd5f64e5d8a9c8f05d60348dff63baa30b360fc"},"cell_type":"markdown","source":"## Load segmentation file"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\nimport gc\nprint(os.listdir(\"../input\"))\nimport numpy as np \nimport pandas as pd\nimport time","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6de6d2bae5755886b31604cfdd074e0768ce3360"},"cell_type":"code","source":"train = pd.read_csv('../input/train_ship_segmentations_v2.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3f17c5fca1c05816d5f5fef51c96c08471b578cb"},"cell_type":"code","source":"train.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"3c71c03554f932704ebf66c6811f3ee2ac21de15"},"cell_type":"markdown","source":"## Tranfer EncodedPixels to target \n* have ship ==> 1\n* No ship ==> 0"},{"metadata":{"trusted":true,"_uuid":"1e4661d18418f77cbe9e608a2916ad171694caf2"},"cell_type":"code","source":"train['exist_ship'] = train['EncodedPixels'].fillna(0)\ntrain.loc[train['exist_ship']!=0,'exist_ship']=1\ndel train['EncodedPixels']","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"7e6563b24a8c46962b5b9460c9da8faf703b20ab"},"cell_type":"markdown","source":"## We found there are some duplicate image in training data\n* groupby duplicate image "},{"metadata":{"trusted":true,"_uuid":"042cefd7a9a3a26fb67b3067c0618df8edbda6e4"},"cell_type":"code","source":"print(len(train['ImageId']))\nprint(train['ImageId'].value_counts().shape[0])\ntrain_gp = train.groupby('ImageId').sum().reset_index()\ntrain_gp.loc[train_gp['exist_ship']>0,'exist_ship']=1","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"1f04a80c515d5295d1f65efcbb15c9299c1ae762"},"cell_type":"markdown","source":"## Balance have chip and no chip data\n* Remove 100000 data of no chip"},{"metadata":{"trusted":true,"_uuid":"4b106073db3ce8ee7d27a3cdeeebd2c6855b52e6"},"cell_type":"code","source":"print(train_gp['exist_ship'].value_counts())\ntrain_gp= train_gp.sort_values(by='exist_ship')\ntrain_gp = train_gp.drop(train_gp.index[0:100000])","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2b3818001efbd28bf6b2e3079eab115a81c54420"},"cell_type":"markdown","source":"## Set Training set count\n* prevent large data cause much time "},{"metadata":{"trusted":true,"_uuid":"b3052c37f6b60b9ddc73fd52f99a1c5d56ca0ce0"},"cell_type":"code","source":"print(train_gp['exist_ship'].value_counts())\ntrain_sample = train_gp.sample(5000)\nprint(train_sample['exist_ship'].value_counts())\nprint (train_sample.shape)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f3df290c8e72ef71e02060ff7b8d76c74986e2eb"},"cell_type":"markdown","source":"## Load training data function\n* load training data to numpy array for training "},{"metadata":{"trusted":true,"_uuid":"fb283b096d5244c228549d3ccf477dd1e996794f"},"cell_type":"code","source":"Train_path = '../input/train_v2/'\nTest_path = '../input/test_v2/'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"77ade061a3070f84b8b16cf99c4a506ff2643953"},"cell_type":"code","source":"%%time\ntraining_img_data = []\ntarget_data = []\nfrom PIL import Image\ndata = np.empty((len(train_sample['ImageId']),256, 256,3), dtype=np.uint8)\ndata_target = np.empty((len(train_sample['ImageId'])), dtype=np.uint8)\nimage_name_list = os.listdir(Train_path)\nindex = 0\nfor image_name in image_name_list:\n    if image_name in list(train_sample['ImageId']):\n        imageA = Image.open(Train_path+image_name).resize((256,256)).convert('RGB')\n        data[index]=imageA\n        data_target[index]=train_sample[train_gp['ImageId'].str.contains(image_name)]['exist_ship'].iloc[0]\n        index+=1\n        \nprint(data.shape)\nprint(data_target.shape)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"04d0f83dbfe25e02e64c180339c9fef7170abc4b"},"cell_type":"markdown","source":"## Doing One hot on target\n* Set target to one hot target for classification problem"},{"metadata":{"trusted":true,"_uuid":"f4adca93a229ee7e418b1a70bb23874476f09a7b"},"cell_type":"code","source":"from sklearn.preprocessing import OneHotEncoder\ntargets =data_target.reshape(len(data_target),-1)\nenc = OneHotEncoder()\nenc.fit(targets)\ntargets = enc.transform(targets).toarray()\nprint(targets.shape)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2072d6a685db2d6e92273b87a918f3d206992781"},"cell_type":"markdown","source":"## Split Training data to training data and validate data to detect overfit "},{"metadata":{"trusted":true,"_uuid":"9ad67d24f997b669da87dc658aa7f63f854c7985"},"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nx_train, x_val, y_train, y_val = train_test_split(data,targets, test_size = 0.2)\nx_train.shape, x_val.shape, y_train.shape, y_val.shape","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"41053c75c247aa318d72faa20cf573376c36b934"},"cell_type":"markdown","source":"## Data augumatation\n* Using ImageDataGenerator"},{"metadata":{"trusted":true,"_uuid":"69bb2e22c30509e1ca478dcf361e61e1b3bbfddf"},"cell_type":"code","source":"from keras.preprocessing.image import ImageDataGenerator\nimg_gen = ImageDataGenerator(\n    rescale=1./255,\n    zca_whitening = False,\n    rotation_range = 90,\n    width_shift_range = 0.2,\n    height_shift_range = 0.2,\n    brightness_range = [0.5, 1.5],\n    shear_range = 0.2,\n    zoom_range = 0.2,\n    horizontal_flip = True,\n    vertical_flip = True\n    \n)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"fdfb4e5eaa90d1f8cceae27e513a16b87c9ca47a"},"cell_type":"markdown","source":"## Load ResNet50 model with Keras\n* on Kaggle kernel, please turn on the internet setting to Internet connect  on right window"},{"metadata":{"trusted":true,"scrolled":false,"_uuid":"2885ed2d5c354aa39844f5a5b3bf77e46731e602"},"cell_type":"code","source":"#from keras.applications.vgg16 import VGG16 as PTModel, preprocess_input\n#from keras.applications.densenet import DenseNet169 as PTModel, preprocess_input\nfrom keras.applications.resnet50 import ResNet50 as ResModel\n#from keras.applications.vgg16 import VGG16 as VGG16Model\nimg_width, img_height = 256, 256\nmodel = ResModel(weights = 'imagenet', include_top=False, input_shape = (img_width, img_height, 3))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"4aee83b25bb184f63600071aec8c1d8d1dd61f9d"},"cell_type":"markdown","source":"## Add fully connect layer\n* Freeze convolution layer and add fully connect layer\n* On this case, we only need predict 2 category (1. have ship, 2. no ship)\n* For transfer learning, we only need to train parametric on fully connect layer"},{"metadata":{"trusted":true,"_uuid":"228c794063d2275bf2ea11642e8a56fd4b495229"},"cell_type":"code","source":"from keras.layers import Dropout, Flatten, Dense, GlobalAveragePooling2D\nfrom keras.models import Sequential, Model \nfor layer in model.layers:\n    layer.trainable = False\n\nx = model.output\nx = Flatten()(x)\nx = Dense(1024, activation=\"relu\")(x)\nx = Dropout(0.5)(x)\nx = Dense(1024, activation=\"relu\")(x)\npredictions = Dense(2, activation=\"softmax\")(x)\n\n# creating the final model \nmodel_final = Model(input = model.input, output = predictions)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f0124e8f78246f34490f52c70072fd51b5148295"},"cell_type":"markdown","source":"##  Set Hyperparameter and Start training \n* SGD optimizer\n* Using categorical_crossentropy to be loss function\n* lrate set to 0.001 (Maybe we have better value, In here, I have no experence on this)"},{"metadata":{"trusted":true,"_uuid":"7d3aff1f92c38f26e7def6af1e0e216ea7ab4472","_kg_hide-output":true},"cell_type":"code","source":"from keras import optimizers\nepochs = 10\nlrate = 0.001\ndecay = lrate/epochs\n#adam = optimizers.Adam(lr=lrate,beta_1=0.9, beta_2=0.999, decay=decay)\nsgd = optimizers.SGD(lr=lrate, momentum=0.9, decay=decay, nesterov=False)\nmodel_final.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])\nmodel_final.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d0cd61fc35340eca01c59ad581d1f6f35480fdb4"},"cell_type":"code","source":"model_final.fit_generator(img_gen.flow(x_train, y_train, batch_size = 16),steps_per_epoch = len(x_train)/16, validation_data = (x_val,y_val), epochs = epochs )\nmodel_final.save('ResNet_transfer_ship.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"22ae52750c98b52a052f7838a9f3398453660f6d"},"cell_type":"code","source":"gc.collect()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a7f37debe22cc65a4763a2f71043578081f37bbd"},"cell_type":"markdown","source":"## Predict accuracy by random read training data"},{"metadata":{"_uuid":"e1f6230c85e7c2954391fb08a5f0d2d6c6420f0f"},"cell_type":"markdown","source":"* Get random 2000 data from training set"},{"metadata":{"trusted":true,"_uuid":"a4376fd74869c5c12986c8903a944b46d55ea7b1"},"cell_type":"code","source":"train_predict_sample = train_gp.sample(2000)\nprint(train_predict_sample['exist_ship'].value_counts())","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"76c49496df1f53e12bb057d1a96539d1795a2b18"},"cell_type":"markdown","source":"* Load predict data "},{"metadata":{"trusted":true,"_uuid":"a3d08d8775d770c62fc31608a7e3ff9d39b8113b","scrolled":true},"cell_type":"code","source":"%%time\nfrom PIL import Image\ndata_predict = np.empty((len(train_predict_sample['ImageId']),256, 256,3), dtype=np.uint8)\ndata_target_predict = np.empty((len(train_predict_sample['ImageId'])), dtype=np.uint8)\nimage_name_list = os.listdir(Train_path)\nindex = 0\nfor image_name in image_name_list:\n    if image_name in list(train_predict_sample['ImageId']):\n        imageA = Image.open(Train_path+image_name).resize((256,256)).convert('RGB')\n        data_predict[index]=imageA\n        data_target_predict[index]=train_predict_sample[train_gp['ImageId'].str.contains(image_name)]['exist_ship'].iloc[0]\n        index+=1\n        \nprint(data_predict.shape)\nprint(data_target_predict.shape)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"412b8d395b4f1e2946a5eca2d8a744fa17e863b8"},"cell_type":"markdown","source":"* Do one hot for predict target"},{"metadata":{"trusted":true,"_uuid":"e7889ae67802b9e5aa62a97520e65195175ef846"},"cell_type":"code","source":"from sklearn.preprocessing import OneHotEncoder\ntargets_predict =data_target_predict.reshape(len(data_target_predict),-1)\nenc = OneHotEncoder()\nenc.fit(targets_predict)\ntargets_predict = enc.transform(targets_predict).toarray()\nprint(targets_predict.shape)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"e6e658dffda8ff9e46d38082596408767a5ce978"},"cell_type":"markdown","source":"* Evaluate predict"},{"metadata":{"trusted":true,"_uuid":"bf8f72cd06c6b496eecae7451355adc9fcc4fc6d"},"cell_type":"code","source":"predict_ship = model_final.evaluate(data_predict,targets_predict)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"af76c584a241057e305b865b2385cb6d8deda468"},"cell_type":"markdown","source":"* Result"},{"metadata":{"trusted":true,"_uuid":"b81d55eeb2fdd6a2d2c55316b314cd721e4c1222"},"cell_type":"code","source":"print ('Accuracy of random data = '+ str(round(predict_ship[1]*100)) + \"%\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"9f38005faad8c144a0f263aca239a2f8794c1513"},"cell_type":"code","source":"image_test_name_list = os.listdir(Test_path)\ndata_test = np.empty((len(image_test_name_list),256, 256,3), dtype=np.uint8)\ntest_name = []\nindex = 0\nfor image_name in image_test_name_list:\n    imageA = Image.open(Test_path+image_name).resize((256,256)).convert('RGB')\n    test_name.append(image_name)\n    data_test[index]=imageA\n    index+=1\nprint (data_test.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f5b850df348d04e7601881d6c88efe7f4661ba34"},"cell_type":"code","source":"result = model_final.predict(data_test)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"722efb4c0b34f29eddfc3cfe7b6578c196be6f9e"},"cell_type":"code","source":"result_list={\n    \"ImageId\": test_name,\n    \"Have_ship\":np.argmax(result,axis=1)\n}\nresult_pd = pd.DataFrame(result_list)\nresult_pd.to_csv('Have_ship_or_not.csv',index = False)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"60a712058cd20954602d01b4335780764bc470c7"},"cell_type":"markdown","source":"## Conclution\n*  We can use tranfer learning to detect ship or not , and get higher accuracy on it \n*  If we get 95% accuracy up, we can merge it with Unet model to produce a final submission\n*  Like Iafoss kernel: https://www.kaggle.com/iafoss/fine-tuning-resnet34-on-ship-detection/notebook"}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}