{"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":"# **Plant Pathology Analysis with transfer learning(DenseNet 169)**\n* *Data Visualization*\n* *Data Augmentation*\n* *Model training: DenseNet 169*\n* *Prediction*\n* *Submission*","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\nimport os\nimport cv2\nimport pandas as pd\nimport seaborn as sns","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-11-02T07:06:04.95517Z","iopub.execute_input":"2021-11-02T07:06:04.955714Z","iopub.status.idle":"2021-11-02T07:06:05.591657Z","shell.execute_reply.started":"2021-11-02T07:06:04.955625Z","shell.execute_reply":"2021-11-02T07:06:05.590601Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"^import 하는 부분","metadata":{}},{"cell_type":"code","source":"df=pd.read_csv(\"../input/plant-pathology-2021-fgvc8/train.csv\")\ndf","metadata":{"execution":{"iopub.status.busy":"2021-11-02T07:06:05.593132Z","iopub.execute_input":"2021-11-02T07:06:05.593399Z","iopub.status.idle":"2021-11-02T07:06:05.650408Z","shell.execute_reply.started":"2021-11-02T07:06:05.593373Z","shell.execute_reply":"2021-11-02T07:06:05.649688Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"대회에서 제공하는 파일 읽기","metadata":{}},{"cell_type":"markdown","source":"# *Data Visualization*","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(25,10))\nplt.xlabel(\"labels\",fontsize=15)\nplt.xticks(rotation=15,fontsize = 12,fontweight = \"bold\")\nplt.ylabel(\"count\",fontsize=15)\nplt.yticks(fontsize=15)\nsns.barplot(data=df,x=df.value_counts(\"labels\").index,y=df.value_counts(\"labels\").values)","metadata":{"execution":{"iopub.status.busy":"2021-11-02T07:06:05.652991Z","iopub.execute_input":"2021-11-02T07:06:05.653828Z","iopub.status.idle":"2021-11-02T07:06:05.971311Z","shell.execute_reply.started":"2021-11-02T07:06:05.653775Z","shell.execute_reply":"2021-11-02T07:06:05.970248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_path=\"../input/plant-pathology-2021-fgvc8/train_images\"\nplt.figure(figsize=(20,40))\ni=1\nfor idx,s in df.head(9).iterrows():\n    img_path = os.path.join(train_path,s['image'])\n    img=cv2.imread(img_path)\n    img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)\n    \n    fig=plt.subplot(9,3,i)\n    fig.imshow(img)\n    fig.set_title(s['labels'])\n    i+=1","metadata":{"execution":{"iopub.status.busy":"2021-11-02T07:06:05.973268Z","iopub.execute_input":"2021-11-02T07:06:05.973674Z","iopub.status.idle":"2021-11-02T07:06:18.038914Z","shell.execute_reply.started":"2021-11-02T07:06:05.973629Z","shell.execute_reply":"2021-11-02T07:06:18.037947Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Since each leaves may have more than one disease(e.g.the second leaf in the above image is *scab,frog_eye_leaf_spot,complex*), so it can be a ***multilabel classification***.","metadata":{}},{"cell_type":"code","source":"df['labels'].unique()\n# 1.healthy\n# 2.scab\n# 3.complex\n# 4.rust\n# 5.fog_eye_leaf_spot\n# 6.powdery_mildew","metadata":{"execution":{"iopub.status.busy":"2021-11-02T07:06:18.040035Z","iopub.execute_input":"2021-11-02T07:06:18.040435Z","iopub.status.idle":"2021-11-02T07:06:18.046528Z","shell.execute_reply.started":"2021-11-02T07:06:18.040405Z","shell.execute_reply":"2021-11-02T07:06:18.045629Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['labels']=df['labels'].apply( lambda string: string.split(' ') )\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2021-11-02T07:06:18.047792Z","iopub.execute_input":"2021-11-02T07:06:18.048357Z","iopub.status.idle":"2021-11-02T07:06:18.078806Z","shell.execute_reply.started":"2021-11-02T07:06:18.048312Z","shell.execute_reply":"2021-11-02T07:06:18.077724Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.preprocessing import MultiLabelBinarizer\nmlb = MultiLabelBinarizer()\nhot_labels = mlb.fit_transform(df['labels'])\nprint(mlb.classes_)\nprint(hot_labels)","metadata":{"execution":{"iopub.status.busy":"2021-11-02T07:06:18.080236Z","iopub.execute_input":"2021-11-02T07:06:18.0807Z","iopub.status.idle":"2021-11-02T07:06:18.20253Z","shell.execute_reply.started":"2021-11-02T07:06:18.080655Z","shell.execute_reply":"2021-11-02T07:06:18.201422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"^라벨 이진화","metadata":{}},{"cell_type":"code","source":"df_labels = pd.DataFrame(hot_labels,columns=mlb.classes_,index=df.index)\ndf_labels","metadata":{"execution":{"iopub.status.busy":"2021-11-02T07:06:18.203849Z","iopub.execute_input":"2021-11-02T07:06:18.204166Z","iopub.status.idle":"2021-11-02T07:06:18.218477Z","shell.execute_reply.started":"2021-11-02T07:06:18.204135Z","shell.execute_reply":"2021-11-02T07:06:18.217182Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(25,10))\nsns.barplot(x=df_labels.columns,y=df_labels.sum().values)","metadata":{"execution":{"iopub.status.busy":"2021-11-02T07:06:18.221582Z","iopub.execute_input":"2021-11-02T07:06:18.222147Z","iopub.status.idle":"2021-11-02T07:06:18.395831Z","shell.execute_reply.started":"2021-11-02T07:06:18.222098Z","shell.execute_reply":"2021-11-02T07:06:18.394759Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# *Data Augmentation*\n데이터의 양을 늘리기위해 원본 이미지에 각종 변환을 적용시켜 개수를 증강시키는 기법\n","metadata":{}},{"cell_type":"code","source":"from keras.preprocessing.image import ImageDataGenerator\n\ndatagen = ImageDataGenerator(rescale=1/255.0,\n                            rotation_range=5,\n                            zoom_range=0.1,\n                            shear_range=0.05,\n                            horizontal_flip=True,\n                            validation_split=0.2)\n\ntrain_generator = datagen.flow_from_dataframe(\n    df,\n    directory='../input/resized-plant2021/img_sz_256',\n    subset='training',\n    x_col='image',\n    y_col='labels',\n    target_size=(224,224),\n    color_mode='rgb',\n    class_mode='categorical',\n    batch_size=32,\n    shuffle=True,\n    seed=444\n    )\n#'../input/plant-pathology-2021-fgvc8/train_images'\nvalid_generator = datagen.flow_from_dataframe(\n    df,\n    directory='../input/resized-plant2021/img_sz_256',\n    subset='validation',\n    x_col='image',\n    y_col='labels',\n    target_size=(224,224),\n    color_mode='rgb',\n    class_mode='categorical',\n    batch_size=32,\n    shuffle=True,\n    seed=444\n    )","metadata":{"execution":{"iopub.status.busy":"2021-11-02T07:06:18.39777Z","iopub.execute_input":"2021-11-02T07:06:18.398387Z","iopub.status.idle":"2021-11-02T07:06:30.558699Z","shell.execute_reply.started":"2021-11-02T07:06:18.398338Z","shell.execute_reply":"2021-11-02T07:06:30.557695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# *Transfer Learning: DenseNet 169*","metadata":{}},{"cell_type":"code","source":"from keras.applications import InceptionResNetV2\nfrom keras.applications import MobileNetV2\nfrom keras.applications import DenseNet121\nfrom keras.applications import DenseNet169\n\nimport keras\nfrom keras.layers import Dense,Dropout,Flatten\nfrom tensorflow.keras.layers import GlobalAveragePooling2D\nfrom keras.models import Model\nfrom tensorflow.keras.callbacks import EarlyStopping\nimport tensorflow_addons as tfa\n\nweight_path='../input/tf-keras-pretrained-model-weights/No Top/densenet169_weights_tf_dim_ordering_tf_kernels_notop.h5'\nbase_model=DenseNet169(weights=weight_path,include_top=False, input_shape=(224,224,3))\nx=base_model.output\nx=GlobalAveragePooling2D()(x)\nx=Dense(128,activation='relu')(x)\nx=Dropout(0.2)(x)\nx=Dense(64,activation='relu')(x)\npredictions=Dense(6,activation='sigmoid')(x)\n\nmodel=Model(inputs=base_model.input,outputs=predictions)\n\nfor layer in base_model.layers:\n    layer.trainable=False\n","metadata":{"execution":{"iopub.status.busy":"2021-11-02T07:06:30.560151Z","iopub.execute_input":"2021-11-02T07:06:30.560417Z","iopub.status.idle":"2021-11-02T07:06:36.275296Z","shell.execute_reply.started":"2021-11-02T07:06:30.560391Z","shell.execute_reply":"2021-11-02T07:06:36.274271Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"trian the last few layers and the ouput layers first","metadata":{}},{"cell_type":"code","source":"f1 = tfa.metrics.F1Score(num_classes=6,average='macro')\n\nmodel.compile(optimizer='adam', loss='binary_crossentropy',metrics=['accuracy',f1])\nes=EarlyStopping(patience=4,monitor=f1,mode='max',restore_best_weights=True)\nhist = model.fit_generator(generator=train_generator,\n                    validation_data=valid_generator,\n                    epochs=20,\n                    steps_per_epoch=train_generator.samples//128,\n                    validation_steps=valid_generator.samples//128,\n                    callbacks=[es])","metadata":{"execution":{"iopub.status.busy":"2021-11-02T07:06:36.276536Z","iopub.execute_input":"2021-11-02T07:06:36.276835Z","iopub.status.idle":"2021-11-02T09:52:39.225485Z","shell.execute_reply.started":"2021-11-02T07:06:36.276803Z","shell.execute_reply":"2021-11-02T09:52:39.223472Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"freeze the trained layers, then train the second and the third dense block in DenseNet169","metadata":{}},{"cell_type":"code","source":"#the third dense block:\n# model.layers[143:595]","metadata":{"execution":{"iopub.status.busy":"2021-11-02T09:52:39.22966Z","iopub.execute_input":"2021-11-02T09:52:39.230062Z","iopub.status.idle":"2021-11-02T09:52:39.236456Z","shell.execute_reply.started":"2021-11-02T09:52:39.230025Z","shell.execute_reply":"2021-11-02T09:52:39.23543Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.layers[595:]","metadata":{"execution":{"iopub.status.busy":"2021-11-02T09:52:39.238186Z","iopub.execute_input":"2021-11-02T09:52:39.238755Z","iopub.status.idle":"2021-11-02T09:52:39.257355Z","shell.execute_reply.started":"2021-11-02T09:52:39.238709Z","shell.execute_reply":"2021-11-02T09:52:39.256618Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for layer in model.layers[:595]:\n    layer.trainable=False\n\nfor layer in model.layers[143:]:\n    layer.trainable=True\n\nfor layer in model.layers[595:]:\n    layer.trainable=False\n\nmodel.compile(optimizer='adam', loss='binary_crossentropy',metrics=['accuracy',f1])\nhistory = model.fit_generator(generator=train_generator,\n                    validation_data=valid_generator,\n                    epochs=15,\n                    steps_per_epoch=train_generator.samples//128,\n                    validation_steps=valid_generator.samples//128,\n                    callbacks=[es])","metadata":{"execution":{"iopub.status.busy":"2021-11-02T09:52:39.258549Z","iopub.execute_input":"2021-11-02T09:52:39.259136Z","iopub.status.idle":"2021-11-02T13:49:32.271663Z","shell.execute_reply.started":"2021-11-02T09:52:39.259068Z","shell.execute_reply":"2021-11-02T13:49:32.269459Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# accuracy\nplt.figure(figsize=(15,6))\nepoch_list = list(range(1, len(history.history['accuracy']) + 1))\nplt.plot(epoch_list, history.history['accuracy'],label='accuracy')\nplt.plot(epoch_list, history.history['val_accuracy'],label='val_accuracy')\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-11-02T13:49:32.275918Z","iopub.execute_input":"2021-11-02T13:49:32.276376Z","iopub.status.idle":"2021-11-02T13:49:32.559328Z","shell.execute_reply.started":"2021-11-02T13:49:32.27633Z","shell.execute_reply":"2021-11-02T13:49:32.55808Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# f1  score\nplt.figure(figsize=(15,6))\nepoch__list = list(range(1,len(history.history['f1_score'])+1))\nplt.plot(epoch__list, history.history['f1_score'],label='f1_score')\nplt.plot(epoch__list, history.history['val_f1_score'],label='val_f1_score')\nplt.xlabel('epoches')\nplt.ylabel('f1')\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-11-02T13:49:32.560795Z","iopub.execute_input":"2021-11-02T13:49:32.561113Z","iopub.status.idle":"2021-11-02T13:49:32.753714Z","shell.execute_reply.started":"2021-11-02T13:49:32.561084Z","shell.execute_reply":"2021-11-02T13:49:32.752827Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#model.save('plant_incepresnetv2.h5')","metadata":{"execution":{"iopub.status.busy":"2021-11-02T13:49:32.755039Z","iopub.execute_input":"2021-11-02T13:49:32.755318Z","iopub.status.idle":"2021-11-02T13:49:32.759998Z","shell.execute_reply.started":"2021-11-02T13:49:32.75529Z","shell.execute_reply":"2021-11-02T13:49:32.758857Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# *Prediction*","metadata":{}},{"cell_type":"code","source":"test_path=\"../input/plant-pathology-2021-fgvc8/sample_submission.csv\"\ntest = pd.read_csv(test_path)\ntest","metadata":{"execution":{"iopub.status.busy":"2021-11-02T13:49:32.7613Z","iopub.execute_input":"2021-11-02T13:49:32.761598Z","iopub.status.idle":"2021-11-02T13:49:32.817843Z","shell.execute_reply.started":"2021-11-02T13:49:32.761568Z","shell.execute_reply":"2021-11-02T13:49:32.816831Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_data = datagen.flow_from_dataframe(\n    test,\n    directory='../input/plant-pathology-2021-fgvc8/test_images',\n    x_col='image',\n    y_col=None,\n    color_mode='rgb',\n    target_size=(224,224),\n    class_mode=None,\n    shuffle=False\n)\npredictions = model.predict(test_data)\nprint(predictions)\n\nclass_idx=[]\nfor pred in predictions:\n    pred=list(pred)\n    temp=[]\n    for i in pred:\n        if (i>0.4):\n            temp.append(pred.index(i))\n    if (temp!=[]):\n        class_idx.append(temp)\n    else:\n        temp.append(np.argmax(pred))\n        class_idx.append(temp)\nprint(class_idx)","metadata":{"execution":{"iopub.status.busy":"2021-11-02T13:49:32.8194Z","iopub.execute_input":"2021-11-02T13:49:32.819946Z","iopub.status.idle":"2021-11-02T13:49:37.590851Z","shell.execute_reply.started":"2021-11-02T13:49:32.819908Z","shell.execute_reply":"2021-11-02T13:49:37.590022Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_dict = train_generator.class_indices\ndef get_key(val):\n    for key,value in class_dict.items():\n        if (val==value):\n            return key\nprint(class_dict)\n\nsub_pred=[]\nfor img_ in class_idx:\n    img_pred=[]\n    for i in img_:\n        img_pred.append(get_key(i))\n    sub_pred.append( ' '.join(img_pred))\nprint(sub_pred)","metadata":{"execution":{"iopub.status.busy":"2021-11-02T13:49:37.592113Z","iopub.execute_input":"2021-11-02T13:49:37.592515Z","iopub.status.idle":"2021-11-02T13:49:37.599558Z","shell.execute_reply.started":"2021-11-02T13:49:37.592482Z","shell.execute_reply":"2021-11-02T13:49:37.598829Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# *Submission*","metadata":{}},{"cell_type":"code","source":"sub = test[['image']]\nsub['labels']=sub_pred\nsub","metadata":{"execution":{"iopub.status.busy":"2021-11-02T13:49:37.600724Z","iopub.execute_input":"2021-11-02T13:49:37.601185Z","iopub.status.idle":"2021-11-02T13:49:37.621611Z","shell.execute_reply.started":"2021-11-02T13:49:37.60115Z","shell.execute_reply":"2021-11-02T13:49:37.620544Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub.to_csv('submission.csv',index=False)","metadata":{"execution":{"iopub.status.busy":"2021-11-02T13:49:37.623423Z","iopub.execute_input":"2021-11-02T13:49:37.624085Z","iopub.status.idle":"2021-11-02T13:49:37.637216Z","shell.execute_reply.started":"2021-11-02T13:49:37.624039Z","shell.execute_reply":"2021-11-02T13:49:37.636058Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}