{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"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":"1634aad69553b73cfca7e59cf65518a934198a86"}},{"cell_type":"markdown","source":"## Load segmentation file","metadata":{"_uuid":"8dd5f64e5d8a9c8f05d60348dff63baa30b360fc"}},{"cell_type":"code","source":"import os\nimport gc\nprint(os.listdir(\"../input\"))\nimport numpy as np \nimport pandas as pd\nimport time","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-10-08T16:16:06.354759Z","iopub.execute_input":"2023-10-08T16:16:06.355072Z","iopub.status.idle":"2023-10-08T16:16:06.367005Z","shell.execute_reply.started":"2023-10-08T16:16:06.355019Z","shell.execute_reply":"2023-10-08T16:16:06.366115Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.read_csv('../input/train_ship_segmentations_v2.csv')","metadata":{"_uuid":"6de6d2bae5755886b31604cfdd074e0768ce3360","execution":{"iopub.status.busy":"2023-10-08T16:16:07.055768Z","iopub.execute_input":"2023-10-08T16:16:07.056078Z","iopub.status.idle":"2023-10-08T16:16:07.694813Z","shell.execute_reply.started":"2023-10-08T16:16:07.056025Z","shell.execute_reply":"2023-10-08T16:16:07.693769Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.head()","metadata":{"_uuid":"3f17c5fca1c05816d5f5fef51c96c08471b578cb","execution":{"iopub.status.busy":"2023-10-08T16:16:07.696531Z","iopub.execute_input":"2023-10-08T16:16:07.697120Z","iopub.status.idle":"2023-10-08T16:16:07.712238Z","shell.execute_reply.started":"2023-10-08T16:16:07.697067Z","shell.execute_reply":"2023-10-08T16:16:07.711293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Tranfer EncodedPixels to target \n* have ship ==> 1\n* No ship ==> 0","metadata":{"_uuid":"3c71c03554f932704ebf66c6811f3ee2ac21de15"}},{"cell_type":"code","source":"train['exist_ship'] = train['EncodedPixels'].fillna(0)\ntrain.loc[train['exist_ship']!=0,'exist_ship']=1\ndel train['EncodedPixels']","metadata":{"_uuid":"1e4661d18418f77cbe9e608a2916ad171694caf2","execution":{"iopub.status.busy":"2023-10-08T16:16:09.909251Z","iopub.execute_input":"2023-10-08T16:16:09.909563Z","iopub.status.idle":"2023-10-08T16:16:10.002588Z","shell.execute_reply.started":"2023-10-08T16:16:09.909501Z","shell.execute_reply":"2023-10-08T16:16:10.001726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## We found there are some duplicate image in training data\n* groupby duplicate image ","metadata":{"_uuid":"7e6563b24a8c46962b5b9460c9da8faf703b20ab"}},{"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","metadata":{"_uuid":"042cefd7a9a3a26fb67b3067c0618df8edbda6e4","execution":{"iopub.status.busy":"2023-10-08T17:00:16.890350Z","iopub.execute_input":"2023-10-08T17:00:16.890703Z","iopub.status.idle":"2023-10-08T17:00:39.177247Z","shell.execute_reply.started":"2023-10-08T17:00:16.890634Z","shell.execute_reply":"2023-10-08T17:00:39.176468Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Balance have chip and no chip data\n* Remove 100000 data of no chip","metadata":{"_uuid":"1f04a80c515d5295d1f65efcbb15c9299c1ae762"}},{"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])","metadata":{"_uuid":"4b106073db3ce8ee7d27a3cdeeebd2c6855b52e6","execution":{"iopub.status.busy":"2023-10-08T16:16:19.129116Z","iopub.status.idle":"2023-10-08T16:16:19.129816Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Set Training set count\n* prevent large data cause much time ","metadata":{"_uuid":"2b3818001efbd28bf6b2e3079eab115a81c54420"}},{"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)","metadata":{"_uuid":"b3052c37f6b60b9ddc73fd52f99a1c5d56ca0ce0","execution":{"iopub.status.busy":"2023-10-08T16:16:19.130896Z","iopub.status.idle":"2023-10-08T16:16:19.131569Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Load training data function\n* load training data to numpy array for training ","metadata":{"_uuid":"f3df290c8e72ef71e02060ff7b8d76c74986e2eb"}},{"cell_type":"code","source":"Train_path = '../input/train_v2/'\nTest_path = '../input/test_v2/'","metadata":{"_uuid":"fb283b096d5244c228549d3ccf477dd1e996794f","execution":{"iopub.status.busy":"2023-10-08T16:16:19.132591Z","iopub.status.idle":"2023-10-08T16:16:19.133306Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\ntraining_img_data = []\ntarget_data = []\nfrom PIL import Image\n\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)","metadata":{"_uuid":"77ade061a3070f84b8b16cf99c4a506ff2643953","execution":{"iopub.status.busy":"2023-10-08T16:16:21.945079Z","iopub.execute_input":"2023-10-08T16:16:21.945387Z","iopub.status.idle":"2023-10-08T16:22:06.778822Z","shell.execute_reply.started":"2023-10-08T16:16:21.945332Z","shell.execute_reply":"2023-10-08T16:22:06.777871Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Doing One hot on target\n* Set target to one hot target for classification problem","metadata":{"_uuid":"04d0f83dbfe25e02e64c180339c9fef7170abc4b"}},{"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)","metadata":{"_uuid":"f4adca93a229ee7e418b1a70bb23874476f09a7b","execution":{"iopub.status.busy":"2023-10-08T16:22:13.482208Z","iopub.execute_input":"2023-10-08T16:22:13.482515Z","iopub.status.idle":"2023-10-08T16:22:13.826844Z","shell.execute_reply.started":"2023-10-08T16:22:13.482457Z","shell.execute_reply":"2023-10-08T16:22:13.825981Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Split Training data to training data and validate data to detect overfit ","metadata":{"_uuid":"2072d6a685db2d6e92273b87a918f3d206992781"}},{"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","metadata":{"_uuid":"9ad67d24f997b669da87dc658aa7f63f854c7985","execution":{"iopub.status.busy":"2023-10-08T16:22:15.581138Z","iopub.execute_input":"2023-10-08T16:22:15.581436Z","iopub.status.idle":"2023-10-08T16:22:16.381645Z","shell.execute_reply.started":"2023-10-08T16:22:15.581375Z","shell.execute_reply":"2023-10-08T16:22:16.380808Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Data augumatation\n* Using ImageDataGenerator","metadata":{"_uuid":"41053c75c247aa318d72faa20cf573376c36b934"}},{"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)","metadata":{"_uuid":"69bb2e22c30509e1ca478dcf361e61e1b3bbfddf","execution":{"iopub.status.busy":"2023-10-08T16:22:19.077160Z","iopub.execute_input":"2023-10-08T16:22:19.077482Z","iopub.status.idle":"2023-10-08T16:22:19.367428Z","shell.execute_reply.started":"2023-10-08T16:22:19.077414Z","shell.execute_reply":"2023-10-08T16:22:19.366591Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"_uuid":"fdfb4e5eaa90d1f8cceae27e513a16b87c9ca47a"}},{"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))","metadata":{"_uuid":"2885ed2d5c354aa39844f5a5b3bf77e46731e602","execution":{"iopub.status.busy":"2023-10-08T16:22:23.569201Z","iopub.execute_input":"2023-10-08T16:22:23.569497Z","iopub.status.idle":"2023-10-08T16:22:34.887878Z","shell.execute_reply.started":"2023-10-08T16:22:23.569438Z","shell.execute_reply":"2023-10-08T16:22:34.887112Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"_uuid":"4aee83b25bb184f63600071aec8c1d8d1dd61f9d"}},{"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)","metadata":{"_uuid":"228c794063d2275bf2ea11642e8a56fd4b495229","execution":{"iopub.status.busy":"2023-10-08T16:22:49.013747Z","iopub.execute_input":"2023-10-08T16:22:49.014049Z","iopub.status.idle":"2023-10-08T16:22:49.090010Z","shell.execute_reply.started":"2023-10-08T16:22:49.013994Z","shell.execute_reply":"2023-10-08T16:22:49.089054Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"_uuid":"f0124e8f78246f34490f52c70072fd51b5148295"}},{"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()","metadata":{"_uuid":"7d3aff1f92c38f26e7def6af1e0e216ea7ab4472","_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-10-08T16:28:34.113961Z","iopub.execute_input":"2023-10-08T16:28:34.114279Z","iopub.status.idle":"2023-10-08T16:28:34.188099Z","shell.execute_reply.started":"2023-10-08T16:28:34.114220Z","shell.execute_reply":"2023-10-08T16:28:34.187371Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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')","metadata":{"_uuid":"d0cd61fc35340eca01c59ad581d1f6f35480fdb4","execution":{"iopub.status.busy":"2023-10-08T16:28:41.845049Z","iopub.execute_input":"2023-10-08T16:28:41.845346Z","iopub.status.idle":"2023-10-08T16:41:00.406736Z","shell.execute_reply.started":"2023-10-08T16:28:41.845291Z","shell.execute_reply":"2023-10-08T16:41:00.405480Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gc.collect()","metadata":{"_uuid":"22ae52750c98b52a052f7838a9f3398453660f6d","execution":{"iopub.status.busy":"2023-10-08T16:47:02.281487Z","iopub.execute_input":"2023-10-08T16:47:02.281936Z","iopub.status.idle":"2023-10-08T16:47:02.718551Z","shell.execute_reply.started":"2023-10-08T16:47:02.281854Z","shell.execute_reply":"2023-10-08T16:47:02.717706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Predict accuracy by random read training data","metadata":{"_uuid":"a7f37debe22cc65a4763a2f71043578081f37bbd"}},{"cell_type":"markdown","source":"* Get random 2000 data from training set","metadata":{"_uuid":"e1f6230c85e7c2954391fb08a5f0d2d6c6420f0f"}},{"cell_type":"code","source":"train_predict_sample = train_gp.sample(2000)\nprint(train_predict_sample['exist_ship'].value_counts())","metadata":{"_uuid":"a4376fd74869c5c12986c8903a944b46d55ea7b1","execution":{"iopub.status.busy":"2023-10-08T16:47:04.676950Z","iopub.execute_input":"2023-10-08T16:47:04.677258Z","iopub.status.idle":"2023-10-08T16:47:04.688289Z","shell.execute_reply.started":"2023-10-08T16:47:04.677204Z","shell.execute_reply":"2023-10-08T16:47:04.687288Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* Load predict data ","metadata":{"_uuid":"76c49496df1f53e12bb057d1a96539d1795a2b18"}},{"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)","metadata":{"_uuid":"a3d08d8775d770c62fc31608a7e3ff9d39b8113b","scrolled":true,"execution":{"iopub.status.busy":"2023-10-08T16:47:06.456756Z","iopub.execute_input":"2023-10-08T16:47:06.457073Z","iopub.status.idle":"2023-10-08T16:49:43.870540Z","shell.execute_reply.started":"2023-10-08T16:47:06.457019Z","shell.execute_reply":"2023-10-08T16:49:43.869697Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* Do one hot for predict target","metadata":{"_uuid":"412b8d395b4f1e2946a5eca2d8a744fa17e863b8"}},{"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)","metadata":{"_uuid":"e7889ae67802b9e5aa62a97520e65195175ef846","execution":{"iopub.status.busy":"2023-10-08T16:52:15.187144Z","iopub.execute_input":"2023-10-08T16:52:15.187469Z","iopub.status.idle":"2023-10-08T16:52:15.202675Z","shell.execute_reply.started":"2023-10-08T16:52:15.187410Z","shell.execute_reply":"2023-10-08T16:52:15.201904Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* Evaluate predict","metadata":{"_uuid":"e6e658dffda8ff9e46d38082596408767a5ce978"}},{"cell_type":"code","source":"predict_ship = model_final.evaluate(data_predict,targets_predict)","metadata":{"_uuid":"bf8f72cd06c6b496eecae7451355adc9fcc4fc6d","execution":{"iopub.status.busy":"2023-10-08T16:52:16.911027Z","iopub.execute_input":"2023-10-08T16:52:16.911338Z","iopub.status.idle":"2023-10-08T16:52:23.699544Z","shell.execute_reply.started":"2023-10-08T16:52:16.911280Z","shell.execute_reply":"2023-10-08T16:52:23.698768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* Result","metadata":{"_uuid":"af76c584a241057e305b865b2385cb6d8deda468"}},{"cell_type":"code","source":"print ('Accuracy of random data = '+ str(round(predict_ship[1]*100)) + \"%\")","metadata":{"_uuid":"b81d55eeb2fdd6a2d2c55316b314cd721e4c1222","execution":{"iopub.status.busy":"2023-10-08T16:52:25.474666Z","iopub.execute_input":"2023-10-08T16:52:25.474973Z","iopub.status.idle":"2023-10-08T16:52:25.480605Z","shell.execute_reply.started":"2023-10-08T16:52:25.474914Z","shell.execute_reply":"2023-10-08T16:52:25.479857Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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)","metadata":{"_uuid":"9f38005faad8c144a0f263aca239a2f8794c1513","execution":{"iopub.status.busy":"2023-10-08T16:52:26.030692Z","iopub.execute_input":"2023-10-08T16:52:26.031011Z","iopub.status.idle":"2023-10-08T16:57:51.374657Z","shell.execute_reply.started":"2023-10-08T16:52:26.030952Z","shell.execute_reply":"2023-10-08T16:57:51.373418Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"result = model_final.predict(data_test)","metadata":{"_uuid":"f5b850df348d04e7601881d6c88efe7f4661ba34","execution":{"iopub.status.busy":"2023-10-08T16:57:51.376368Z","iopub.execute_input":"2023-10-08T16:57:51.376837Z","iopub.status.idle":"2023-10-08T16:58:42.390458Z","shell.execute_reply.started":"2023-10-08T16:57:51.376783Z","shell.execute_reply":"2023-10-08T16:58:42.389526Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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)","metadata":{"_uuid":"722efb4c0b34f29eddfc3cfe7b6578c196be6f9e","execution":{"iopub.status.busy":"2023-10-08T16:58:42.392192Z","iopub.execute_input":"2023-10-08T16:58:42.392654Z","iopub.status.idle":"2023-10-08T16:58:42.607141Z","shell.execute_reply.started":"2023-10-08T16:58:42.392587Z","shell.execute_reply":"2023-10-08T16:58:42.606358Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"_uuid":"60a712058cd20954602d01b4335780764bc470c7"}}]}