{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# All the Required Import statements\nimport gc\nfrom tensorflow.keras.layers import Dense, Flatten, Conv2D,add, MaxPool2D,AveragePooling2D, Dropout, BatchNormalization,concatenate\nfrom tensorflow.keras import Input\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom PIL import Image\nimport pandas\nimport numpy\n\n\n# Collect Unrefereced Memory and Free them using gc.collect()\ngc.collect()\n\ndef convert_data(data,name = 'train'):\n    data.index = data['id_code']\n    data = data.drop(['id_code'],axis=1)\n    if name == 'test':\n        return data\n    data = data.astype(\"category\")\n    data = pandas.get_dummies(data)\n    return data\n\n# Hyperparameters\nurl = '/kaggle/input'\n\nshape = (224,224)\n\ntrain_data = convert_data(pandas.read_csv(url + '/train.csv'))\ntest_data = convert_data(pandas.read_csv(url + '/test.csv'), 'test')\n\n\n# This Method Splits the data depending on which set you want to choose from (i.e, train or test)\n# and giving a start and end point will give you the data required only upto that amount\ndef split_data(name, start=0, end=-1):\n\n    if name == 'train':\n        data = train_data\n\n    elif name == 'test':\n        data = test_data\n\n    else:\n        print('wrong split name')\n        return None\n\n    if end > data.shape[0] or end == -1:\n        end = data.shape[0]\n    \n    x = [(Image.open(url+f'/{name}_images/{img}.png')).resize(shape) for img in data.index[start:end]]\n    x = numpy.array([numpy.array(img_obj) for img_obj in x])\n    \n    if name == 'train':\n        return x, train_data.iloc[start:end,:]\n\n    elif name == 'test':\n        return x\n\ndef renet_block(x,filter_size=3,filters=32,stride=1):\n    conv1 = Conv2D(filters,kernel_size=filter_size,strides=stride,padding='same',activation='relu')(x)\n    conv1 = Conv2D(filters,kernel_size=filter_size,strides=stride,padding='same',activation='relu')(conv1)\n    res = add([ conv1, x])\n\n    return res\n    \ndef incep_resnetv2(x,filter_1x1,filter_1x1_3,filter_3x3,filter_1x1_5,filter_5x5):\n    conv_1x1 = Conv2D(filters = filter_1x1,\n                      kernel_size = (1,1),\n                      strides = (1,1),\n                      padding = 'same',\n                      activation = 'relu'\n                     )(x)\n    \n    conv_1x1_3 = Conv2D(filters = filter_1x1_3,\n                      kernel_size = (1,1),\n                      strides = (1,1),\n                      padding = 'same',\n                      activation = 'relu'\n                       )(x)\n    \n    conv_1x1_3 = Conv2D(filters = filter_3x3,\n                      kernel_size = (3,3),\n                      strides = (1,1),\n                      padding = 'same',\n                      activation = 'relu'\n                       )(conv_1x1_3)\n    # we apply the fact that 5x5 conv is 2.78 times more expensive than 3x3 conv\n    conv_1x1_5 = Conv2D(filters = filter_1x1_5,\n                      kernel_size = (1,1),\n                      strides = (1,1),\n                      padding = 'same',\n                      activation = 'relu'\n                       )(x)\n    conv_1x1_5 = Conv2D(filters = filter_5x5,\n                      kernel_size = (3,3),\n                      strides = (1,1),\n                      padding = 'same',\n                      activation = 'relu'\n                       )(conv_1x1_5)\n    \n    conv_1x1_5 = Conv2D(filters = filter_5x5,\n                      kernel_size = (3,3),\n                      strides = (1,1),\n                      padding = 'same',\n                      activation = 'relu'\n                       )(conv_1x1_5)\n        \n    concat = concatenate([conv_1x1,conv_1x1_3,conv_1x1_5])\n    return add([concat,x])\n\ndef create_model():\n    input_layer = Input(shape=(224,224,3))\n    \n    x = Conv2D(64,(5,5),(2,2),activation='relu')(input_layer)\n    x = Conv2D(64,(3,3),(1,1),padding='same',activation='relu')(x)\n    x = BatchNormalization()(x)\n    x = Dropout(0.2)(x)\n#     x = MaxPool2D(pool_size=(2,2),strides=(2,2))(x)\n    \n    res1 = renet_block(x,filters = 64,filter_size=(3,3))\n    x = Conv2D(72,(3,3),(1,1),padding='same',activation='relu')(res1)\n    x = Dropout(0.2)(x)\n    x = MaxPool2D(pool_size=(2,2),strides=(2,2))(x)\n    \n    res2 = renet_block(x,filters =72,filter_size=(3,3))\n    x = Conv2D(96,(1,1),(1,1),padding='same',activation='relu')(res2)\n    x = BatchNormalization()(x)\n    x = Dropout(0.2)(x)\n    \n    res3 = renet_block(x,filters=96,filter_size=(3,3))\n    x = MaxPool2D(pool_size=(2,2),strides=(2,2))(res3)\n    \n    x = Conv2D(128,(1,1),(1,1),padding='same',activation='relu')(x)\n    incep_res1 = incep_resnetv2(x,64,64,32,64,32)\n    \n    x = Conv2D(192,(1,1),(1,1),padding='same',activation='relu')(incep_res1)\n    incep_res2 = incep_resnetv2(x,64,64,64,64,64)\n    x = BatchNormalization()(incep_res2)\n    x = MaxPool2D(pool_size=(2,2),strides=(2,2))(x)\n    x = Dropout(0.2)(x)\n    \n    x = Conv2D(256,(3,3),(1,1),padding='same',activation='relu')(x)\n    incep_res3 = incep_resnetv2(x,128,32,64,32,64)\n    \n    x = Conv2D(300,(1,1),(1,1),padding='same',activation='relu')(incep_res3)\n    x = AveragePooling2D(pool_size = (2,2),strides=(2,2))(x)\n    \n    x = Flatten()(x)\n    x = Dense(1000,activation='relu')(x)\n    x = Dense(500,activation='relu')(x)\n    x = Dropout(0.2)(x)\n    output = Dense(5,activation='softmax')(x)\n\n    model = Model(input_layer,output)\n    model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])\n    \n    return model\n    \ndef model_fitting(model, batch_size=250, epochs=5, validation=False):\n\n        end = int(train_data.shape[0] * 0.9) if validation else train_data.shape[0]\n        data_generator1 = ImageDataGenerator(rotation_range = 90)\n                                            # shear_range = 0.2,\n                                            # zoom_range = 0.2)\n                                            # vertical_flip = True,\n                                            # width_shift_range = 0.25,\n                                            # height_shift_range = 2\n        data_generator2 = ImageDataGenerator(horizontal_flip = True,\n                                            shear_range = 0.2)\n        \n        for j in range(0, end, batch_size):\n            last = end if (j + batch_size) > end else (j + batch_size)\n            \n            x,y = split_data('train', j, last)\n            \n            print(\"without DataAug\")\n            model.fit(x, y, batch_size = 50, epochs = epochs, shuffle = True)\n            \n            imgs_augment = 30\n            print(\"applying DataAug\")\n            print(\" \"*2+\"DataGen1\")\n            train_gen = data_generator1.flow(x,y,\n                                            batch_size = imgs_augment)\n            \n            model.fit_generator(train_gen,\n                                steps_per_epoch=x.shape[0]/imgs_augment,\n                                epochs=epochs)\n            \n            print(\" \"*2+\"DataGen2\")\n            train_gen = data_generator2.flow(x,y,\n                                            batch_size = imgs_augment)\n            \n            model.fit_generator(train_gen,\n                                steps_per_epoch=x.shape[0]/imgs_augment,\n                                epochs=epochs)\n\n            del x, y,train_gen\n            gc.collect()\n\n            print(\"(\" + str(last) + \"/\" + str(end) + \") images have been Scanned!!\")\n\n        if validation:\n            validate_x, validate_y = split_data('train', end)\n            model.evaluate(validate_x,validate_y)\n            \n            del  validate_x, validate_y\n            \n        gc.collect()\n\n        return model\n\n# Submitting the predicted values can be done using this method\n# Since the test_y values are not given we have to submit the model to check for the accuracy achieved\ndef submit(model,batch_size = 300):\n    \n    end = test_data.shape[0]\n    final_data = pandas.DataFrame(columns=['id_code','diagnosis'])\n    \n    for i in range(0,end,batch_size):\n        last = end if (i+batch_size)>end else (i+batch_size)\n\n        test_x = split_data('test',i,last)\n        test_y = model.predict(test_x)\n\n        test_y = numpy.array([numpy.argmax(i) for i in test_y])\n\n        predicted_data = pandas.DataFrame({ 'id_code' : test_data.index[i:last].values, 'diagnosis' : test_y})\n        final_data = final_data.append(predicted_data,ignore_index=True)\n\n        del test_x, test_y\n        gc.collect()\n    \n    final_data.to_csv('submission.csv',index=False)\n\nif __name__ == '__main__':\n\n    print('Images are resized to', shape, '\\n\\n')\n    print(train_data.shape)\n    model = create_model()\n    print(model.summary())\n    model = model_fitting(model,batch_size = 300, epochs = 40, validation = False)\n    submit(model)","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":1}