{"cells":[{"metadata":{},"cell_type":"markdown","source":"# 진행과정과 생각 정리"},{"metadata":{},"cell_type":"markdown","source":"1. 문제 인식\n\n문제에 제시된 설명을 읽고난 후 손그림을 분류 340개의 클래스로 훈련시켜 줘야한다는 것을 알았다.\n평가 매기는 방식은 key_id칼럼의 테스트 세트에 대해 word값중 acc가 높은 3개의 클래스를 넣어 csv로 만들어주는 것이고\nword에 들어있는 공백은 '_'로 치환하여 제출하라고 되어있었다.\n데이터 탭으로 들어가 데이터에 대한 설명을 읽었다.\nraw데이터와 simplified데이터가 있는데 모두 사용할수 있다고 했으나\nsimplified데이터가 동일안 정보를 효과적으로 제공한다고 써있어서 사용하였다 (raw도 확인하려 했으나 안들어가졌다.)\n그 후 sample_submission에서 제출 양식을 확인할 수 있었다.\n\n2. 데이터 확인\n\n그 후에 제공된 데이터 확인을 하였다.\ncsv의 갯수 즉 클래스의 갯수는 340개였고, \nbird.csv를 읽어와서 확인해봤더니 countrycode,drawing,key_id,recognized,timestamp,word 칼럼이 있었다.\nbird.csv의 데이터의 갯수는 12만개 정도 였고, 누락값은 없었다.\n그림에 대한 이상치데이터는 recognized 칼럼 부분이 True와 False로 나타내고 있었는데 \nbird.csv데이터 2000개를 기준으로 True가 1659개 False가 341개 였다.\n처음에는 test에도 False데이터가 있을거라고 판단하여 데이터 전체를 사용하였다.\n그 후 문제에 제시된 word 열의 공백을 모두 '_'로 replace 해주었다.\n\n3. 첫번째 난관\n\ndrawing이 이미지를 나타내는 칼럼이었는데 pandas로 읽었기 때문에 모두 string으로 반환되었다\n그래서 검색 결과 np.matrix를 통해 변환할 수 있다는 것을 알았고 matrix를 사용하여\n변환해 보았지만 가장안쪽 배열의 구조는 유지 되지 않은채 값들을 전부 1차원으로 반환하였다.\n문자열이라 shape도 1차원으로 나오는 탓에 고민을 많이 했다.\n그 후에 ast.literal_eval이라는 함수가 시퀀스형 데이터로 만들어진 문자열을 시퀀스 데이터 그대로변환할수있는걸 알았고\nast.literal_eval 함수를 이용하여 시퀀스형 데이터로 변환해 주었다.\n\n4. 두번째 난관\n\n배열은 변환 하였으나 이미지가 NxN형태의 배열이 아니었다. \n꽤나 오랫동안 고민끝에 홈페이지의 문제를 다시 인식하기로 했고 dataset에 대한 깃허브페이지가 있었다.\n깃허브 페이지를 보아 x,y,t로 이루어져있고 t에대한 정보를 제거해서 사용한다고 써있었는데\ncsv로 주어진 대회 데이터는 t는 이미 지워진 형태였다. bird[0]을 뽑아서 2가지의 배열만 있다는 것을 확인할 수 있었다.\n그 후에 plt.plot을 이용하여 xy배열을 넣어 확인해보니 그림의 형태가 그려졌다.\n\n5. 세번째 난관\n\n그림은 그렸으나 이것을 이미지로 만들어야만 훈련데이터에 집어넣어 훈련을 해볼 수 있었는데 \nplt에서 그린그림을 그대로 사용하기에는 색깔도 있고 정확한 형태가 아니었다.\n그래서 pillow 모듈을 이용하여 이미지를 직접 그려넣어 주었다.\n이미지를 확인하는 과정에서 True data와 False data를 확인해보았는데 \nFalse데이터는 그림이 아닌것들도 있고 (예를들면 airplane 데이터의 그림의 대부분이 AIRPLANE이라고 영어로 손글씨로 적어논 그림들이 있다.)\n제대로 그려지지 않았기 때문에 True data만 사용하기로 하였다.\n\n6. 네번째 난관\n\n전처리 알고리즘을 끝내고 training data를 만드는데 1개의 클래스 (1개의 csv파일)당 약 1분30초가량걸렸다.\n데이터를 모두 읽어오기에는 전체 데이터의 갯수가 약 3000만개 이므로 RAM 메모리에 올릴수가 없어 물리적 문제가 생기고 \n1개의 파일(클래스)당 1분30초가 걸리기 때문에 340개의 클래스를 모두 읽기에는 시간적으로도 문제가 있었다.\n일단 훈련이 되고 accuracy확인한 후에 데이터의 갯수를 정해는게 맞다고 생각이 들어 \n클래스당 1000개의 데이터로 먼저 진행을 하였다.\n\n7. 다섯번째 난관\n\nCNN모델을 설계하여 바로 집어넣어 봤으나 전에 배웠던 1.9.0 버전이라 문법오류가 났다. \nkaggle kernel에서 제공하는 tf버전은 2.0임을 확인한 후에 tensorflow와 keras중 고민하다가\n아직 사용해보지 않은 keras를 공부하는 목적에서 keras책을 구입하여 keras로 모델을 설계했다.\n\n8. keras공부 후\n\nCNN 초기모델을 먼저 설계해서 넣어보았다 그러나 Training data의 loss가 전혀 떨어 지지않았다.\nVGG16 모델 또한 직접 설계하여 넣어 보았는데 CNN 과 같이 역시 loss가 떨어지지 않는 문제가 생겼다.\n그 후 데이터 전처리의 문제인지 모델의 문제인지 확인하기 위해 \n검증된 모델인 ResNet모델을 넣어 보았는데 작동이 되기 시작했다 그러나 22epoch기준으로 \nacc가 훈련데이터는 평균 :0.7 최고 : 0.98 , 검증데이터는 평균 :0.5 최고 :0.83 에서 그쳤다.\nepoch을 늘리기엔 훈련시간이 약 5시간정도 걸렸기 때문에 클래스를 줄여서 모델별로 acc를 확인하며 진행을 해보기로 하였다.\n\n9. 실험 과정\n\n3클래스 CNN은 loss가 떨어지지않아 acc도 오르지 않음 \n       VGG16 도 CNN과 같은 결과\n       ResNet은 50 epoch결과 val데이터를 0.97까지 구분해 냈다.\n\n50클래스 CNN 위와 비슷한결과\n        VGG16 역시 비슷한결과\n        ResNet은 오르긴 하지만 일정구간에서 val데이터셋의 loss가 떨어지지 않고 오버피팅이 일어났다.\n\nrecognized 가True인 것으로 실험\n위의 5번에서 말한것과 같이 False데이터를 제외하고 다시 훈련을 시켜 보았다.\n\n50클래스 CNN도 작동하기 시작했고 평균 acc가 83 , top acc가 95까지 줄었다. 훈련시간이 매우 적었다.\n        VGG는 역시 작동하지 않았다.(이유는 convolution이 여러번 쌓여 5x5나 7x7필터처럼 작용하는것 때문으로 생각 한다.)\n        ResNet은 12epoch때 까지는 loss가 충분히 감소하고 평균 acc가 87 , top3 acc가 98 까지 나왔다.\n하지만 모든 모델들이 에포크 초반에 오버피팅이 되어 val loss가 발산을 하는 것을 확인할 수가 있었다.\n\n먼저 오버피팅을 막기위해 CNN초기모델을 커스텀하여 모델을 만들어 보고자 하였다.\nbatch nomalization노드를 넣어 주고 실험을 다시했다. 그러나 아직도 오버피팅으로\nloss가 발산해서 발산하지 않게 하는것을 목표로 했다 dropout을 추가해서 다시 해보았더니 loss는 발산하지 않았지만\n전체 acc가 높게 나오지 않았다. 그래서 데이터의 형태를 다시 보고 일정한패턴은 있지만 유일무이한 패턴이\n없다고 생각하고 averagepooling을 사용해보았더니 loss가 안정되고 acc가 향상 되었다.\n\n그 후 Accuracy를 높이기 위해 전처리된 이미지 데이터를 바꿔보기로 하였다.\n처음 그렸던 그림은 배경이 255 그림이 0 값을 가지고 있었기에 배경을 0으로 그림을 1로 바꿔주어서 확인 해보았다.\n50클래스 반전 이미지 CNN val loss 0.58 val 평균 acc 87 \n                  CNN_average val_loss 0.5 평균 acc 0.88 \n                  ResNet val_loss 0.49 평균 acc 0.89\n\nResNet은 성능이 제일 좋게 나왔지만 그냥 짜여진 모델을 사용하는 것보다는 직접 설계해본 모델로 제출하기로 마음 먹고\n설계한 모델로 340클래스당 데이터 2000개씩 훈련시켜 분류 해보기로 하였다. \n\n340클래스 average pooling사용 -> val acc 75 top3 acc 91\n         Max pooling사용 -> val acc 69 top3 acc 89\n\n최종적으로 average pooling을 사용한 모델로 결정하여 제출하기로 하였다."},{"metadata":{},"cell_type":"markdown","source":"# 사용할 패키지 모듈 import"},{"metadata":{"trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport matplotlib.pyplot as plt\nfrom PIL import Image , ImageDraw\nfrom sklearn.preprocessing import *\nimport time\nimport ast\nimport os\nimport tensorflow as tf\nfrom keras import models, layers\nfrom keras import Input\nfrom keras.models import Model, load_model\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras import optimizers, initializers, regularizers, metrics\nfrom keras.callbacks import ModelCheckpoint, EarlyStopping\nfrom keras.layers import BatchNormalization, Conv2D, Activation , AveragePooling2D\nfrom keras.layers import Dense, GlobalAveragePooling2D, MaxPooling2D, ZeroPadding2D, Add\nfrom keras.models import Sequential\nfrom keras.metrics import top_k_categorical_accuracy\nfrom keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping\nfrom tqdm import tqdm\n\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        fpath = os.path.join(dirname, filename)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 폴더이름과 파일 이름 확인"},{"metadata":{"trusted":true},"cell_type":"code","source":"print(dirname)\nprint(filenames[0])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# pandas를 이용하여 데이터 확인"},{"metadata":{"trusted":true},"cell_type":"code","source":"df = pd.read_csv(dirname+'/'+'bird.csv')\ndf['word'] = df['word'].replace(' ','_',regex = True)\nprint(type(df['recognized'][0]))\n\nidx= df.iloc[:5].index\nprint(df.loc[idx,'recognized'].values)\n\nfor i in range(len(df.loc[idx,'drawing'].values)) :\n    if df.loc[idx,'recognized'].values[i] == True :\n        print(i, end=' ')\n\nidx= df.iloc[:2000].index\nT_cnt = 0\nF_cnt = 0\nfor i in range(len(df.loc[idx,'drawing'].values)) :\n    if df.loc[idx,'recognized'].values[i] == True :\n        T_cnt += 1\n    else : F_cnt += 1\n\nprint('\\nTrue Count :',T_cnt)\nprint('False Count :',F_cnt)\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# pyplot을 이용하여 그림 확인"},{"metadata":{"trusted":true},"cell_type":"code","source":"def check_draw(img_arr) :\n    k=3\n    for i in range(len(img_arr[k])):\n        img = plt.plot(img_arr[k][i][0],img_arr[k][i][1])\n        plt.scatter(img_arr[k][i][0],img_arr[k][i][1])\n    plt.xlim(0,256)\n    plt.ylim(0,256)\n    plt.gca().invert_yaxis()\n\nten_ids = df.iloc[:10].index\nimg_arr = [ast.literal_eval(lst) for lst in df.loc[ten_ids,'drawing'].values]  #ast.literal_eval is squence data made string to array\nprint(img_arr[3])\ncheck_draw(img_arr)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# vector로 표현된 데이터를 이미지로 만들기위해 이미지로 그려준다"},{"metadata":{"trusted":true},"cell_type":"code","source":"def make_img(img_arr) :\n    image = Image.new(\"P\", (256,256), color=255)\n    image_draw = ImageDraw.Draw(image)\n    for stroke in img_arr:\n        for i in range(len(stroke[0])-1):\n            image_draw.line([stroke[0][i], \n                             stroke[1][i],\n                             stroke[0][i+1], \n                             stroke[1][i+1]],\n                            fill=0, width=5)\n    return image\nimg = make_img(img_arr[3])\nimg = img.resize((64,64))\nplt.imshow(img)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 전처리시 데이터가 전처리되는 과정을 확인할 퍼센트바"},{"metadata":{"trusted":true},"cell_type":"code","source":"bar = '□□□□□□□□□□'\nsw = 1\ndef percent_bar(array,count,st_time):   #퍼센트를 표시해주는 함수\n    global bar\n    global sw\n    length = len(array)\n    percent = (count/length)*100\n    spend_time = time.time()-st_time\n    if count == 1 :\n        print('preprocessing...')\n    print('\\r'+bar+'%3s'%str(int(percent))+'% '+str(count)+'/'+str(length),'%.2f'%(spend_time)+'sec',end='')\n    if sw == 1 :\n        if int(percent) % 10 == 0 :\n            bar = bar.replace('□','■',1)\n            sw = 0\n    elif sw == 0 :\n        if int(percent) % 10 != 0 :\n            sw = 1","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 위 함수들을 이용하여 전처리를 하여 Train데이터를 추출"},{"metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","trusted":true},"cell_type":"code","source":"def preprocessing(filenames) :\n    img_batch = 2000\n    X= []\n    Y= []\n    class_label = []\n    st_time = time.time()\n    class_num = 340\n    Y_num = 0\n    for fname in filenames[0:class_num] :\n        percent_bar(filenames[0:class_num],Y_num+1,st_time)\n        df = pd.read_csv(os.path.join(dirname,fname))\n        df['word'] = df['word'].replace(' ','_',regex = True)\n        class_label.append(df['word'][0])\n        keys = df.iloc[:img_batch].index\n        #print(len(keys))\n        \n        for i in range(len(df.loc[keys,'drawing'].values)) :\n            if df.loc[keys,'recognized'].values[i] == True :\n                drawing = ast.literal_eval(df.loc[keys,'drawing'].values[i])\n                img = make_img(drawing)\n                img = np.array(img.resize((64,64)))\n                img = img.reshape(64,64,1)\n                X.append(img)\n                Y.append(Y_num)\n        Y_num += 1\n        \n    tmpx = np.array(X)\n\n    Y = np.array([[i] for i in Y])\n    enc = OneHotEncoder(categories='auto')\n    enc.fit(Y)\n    tmpy = enc.transform(Y).toarray()\n    \n    del X\n    del Y     #RAM메모리 절약을 위해 사용하지 않는 변수 삭제\n    \n    return tmpx , tmpy , class_label , class_num\n\ntmpx , tmpy , class_label , class_num = preprocessing(filenames)\nprint('\\n',tmpx.shape, tmpy.shape, '\\n5th class : ',class_label[0:5])\n#df.head()\n#print(drawing[0])\n#img = make_img(drawing[1])\n#plt.imshow(img)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 모델에서 확인할 train과 test를 나누어줌"},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nX_train, X_val, Y_train, Y_val = train_test_split(tmpx,tmpy, test_size = 0.1,random_state = 0)\ndel tmpx\ndel tmpy     #RAM메모리 절약을 위해 사용하지 않는 변수 삭제\n\nprint(X_train.shape,X_val.shape,Y_train.shape,Y_val.shape)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 모델설계"},{"metadata":{},"cell_type":"markdown","source":"**CNN 모델"},{"metadata":{"trusted":true},"cell_type":"code","source":"#CNN\ninputs = (64,64,1)\nst_filter = 32\nfilter_size = (3,3) \nCNN = Sequential()\nCNN.add(layers.Conv2D(st_filter,filter_size, input_shape = inputs ,padding= 'same'))\nCNN.add(BatchNormalization())\nCNN.add(Activation('relu'))\nCNN.add(layers.MaxPooling2D((2,2),padding= 'same'))\nCNN.add(layers.Dropout(0.5))\nCNN.add(layers.Conv2D(st_filter*2,filter_size, input_shape = inputs,padding= 'same'))\nCNN.add(BatchNormalization())\nCNN.add(Activation('relu'))\nCNN.add(layers.AveragePooling2D((2,2),padding= 'same'))\nCNN.add(layers.Dropout(0.5))\nCNN.add(layers.Conv2D(st_filter*4,filter_size, input_shape = inputs,padding= 'same'))\nCNN.add(BatchNormalization())\nCNN.add(Activation('relu'))\nCNN.add(layers.AveragePooling2D((2,2),padding= 'same'))\nCNN.add(layers.Dropout(0.25))\nCNN.add(layers.Conv2D(st_filter*8,filter_size, input_shape = inputs,padding= 'same'))\nCNN.add(BatchNormalization())\nCNN.add(Activation('relu'))\nCNN.add(layers.AveragePooling2D((2,2),padding= 'same'))\nCNN.add(layers.Dropout(0.25))\nCNN.add(layers.Conv2D(st_filter*16,filter_size, input_shape = inputs,padding= 'same'))\nCNN.add(BatchNormalization())\nCNN.add(layers.AveragePooling2D((2,2),padding= 'same'))\nCNN.add(layers.Flatten())\nCNN.add(layers.Dense(2*2*512,activation = 'relu'))\nCNN.add(layers.Dropout(0.5))\nCNN.add(layers.Dense(class_num, activation = 'softmax'))\n\nCNN.summary()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**VGG16 모델"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"markdown","source":"****VGG16****\n\n    inputs = (64,64,1)\n    st_filter = 32\n    filter_size = (3,3) \n\n    VGG16 = Sequential()\n    VGG16.add(layers.Conv2D(st_filter,filter_size, activation = 'relu', input_shape = inputs ,padding= 'same'))\n    VGG16.add(layers.Conv2D(st_filter,filter_size, activation = 'relu', input_shape = inputs ,padding= 'same'))\n    VGG16.add(layers.MaxPooling2D((2,2),padding= 'same'))\n    VGG16.add(layers.Conv2D(st_filter*2,filter_size, activation = 'relu', input_shape = inputs,padding= 'same'))\n    VGG16.add(layers.Conv2D(st_filter*2,filter_size, activation = 'relu', input_shape = inputs ,padding= 'same'))\n    VGG16.add(layers.MaxPooling2D((2,2),padding= 'same'))\n    VGG16.add(layers.Conv2D(st_filter*4,filter_size, activation = 'relu', input_shape = inputs,padding= 'same'))\n    VGG16.add(layers.Conv2D(st_filter*4,filter_size, activation = 'relu', input_shape = inputs ,padding= 'same'))\n    VGG16.add(layers.Conv2D(st_filter*4,filter_size, activation = 'relu', input_shape = inputs ,padding= 'same'))\n    VGG16.add(layers.MaxPooling2D((2,2),padding= 'same'))\n    VGG16.add(layers.Conv2D(st_filter*8,filter_size, activation = 'relu', input_shape = inputs,padding= 'same'))\n    VGG16.add(layers.Conv2D(st_filter*8,filter_size, activation = 'relu', input_shape = inputs ,padding= 'same'))\n    VGG16.add(layers.Conv2D(st_filter*8,filter_size, activation = 'relu', input_shape = inputs ,padding= 'same'))\n    VGG16.add(layers.MaxPooling2D((2,2),padding= 'same'))\n    VGG16.add(layers.Conv2D(st_filter*16,filter_size, activation = 'relu', input_shape = inputs ,padding= 'same'))\n    VGG16.add(layers.Conv2D(st_filter*16,filter_size, activation = 'relu', input_shape = inputs ,padding= 'same'))\n    VGG16.add(layers.Conv2D(st_filter*16,filter_size, activation = 'relu', input_shape = inputs ,padding= 'same'))\n    VGG16.add(layers.MaxPooling2D((2,2),padding= 'same'))\n    VGG16.add(layers.Flatten())\n    VGG16.add(layers.Dense(2*2*512,activation = 'relu'))\n    VGG16.add(layers.Dropout(0.5))\n    VGG16.add(layers.Dense(class_num, activation = 'softmax'))\n\n    VGG16.summary()"},{"metadata":{},"cell_type":"markdown","source":"**ResNet50"},{"metadata":{"trusted":true},"cell_type":"markdown","source":"    #ResNet50\n    K = class_num\n\n    input_tensor = Input(shape=(64, 64, 1), dtype='float32', name='input')\n\n    def conv1_layer(x):    \n        x = ZeroPadding2D(padding=(3, 3))(x)\n        x = Conv2D(64, (7, 7), strides=(2, 2))(x)\n        x = BatchNormalization()(x)\n        x = Activation('relu')(x)\n        x = ZeroPadding2D(padding=(1,1))(x)\n\n        return x   \n\n    def conv2_layer(x):         \n        x = MaxPooling2D((3, 3), 2)(x)     \n\n        shortcut = x\n\n        for i in range(3):\n            if (i == 0):\n                x = Conv2D(64, (1, 1), strides=(1, 1), padding='valid')(x)\n                x = BatchNormalization()(x)\n                x = Activation('relu')(x)\n\n                x = Conv2D(64, (3, 3), strides=(1, 1), padding='same')(x)\n                x = BatchNormalization()(x)\n                x = Activation('relu')(x)\n\n                x = Conv2D(256, (1, 1), strides=(1, 1), padding='valid')(x)\n                shortcut = Conv2D(256, (1, 1), strides=(1, 1), padding='valid')(shortcut)            \n                x = BatchNormalization()(x)\n                shortcut = BatchNormalization()(shortcut)\n\n                x = Add()([x, shortcut])\n                x = Activation('relu')(x)\n\n                shortcut = x\n\n            else:\n                x = Conv2D(64, (1, 1), strides=(1, 1), padding='valid')(x)\n                x = BatchNormalization()(x)\n                x = Activation('relu')(x)\n\n                x = Conv2D(64, (3, 3), strides=(1, 1), padding='same')(x)\n                x = BatchNormalization()(x)\n                x = Activation('relu')(x)\n\n                x = Conv2D(256, (1, 1), strides=(1, 1), padding='valid')(x)\n                x = BatchNormalization()(x)            \n\n                x = Add()([x, shortcut])   \n                x = Activation('relu')(x)  \n\n                shortcut = x        \n\n        return x\n\n    def conv3_layer(x):        \n        shortcut = x    \n\n        for i in range(4):     \n            if(i == 0):            \n                x = Conv2D(128, (1, 1), strides=(2, 2), padding='valid')(x)\n                x = BatchNormalization()(x)\n                x = Activation('relu')(x)        \n\n                x = Conv2D(128, (3, 3), strides=(1, 1), padding='same')(x)\n                x = BatchNormalization()(x)\n                x = Activation('relu')(x)  \n\n                x = Conv2D(512, (1, 1), strides=(1, 1), padding='valid')(x)\n                shortcut = Conv2D(512, (1, 1), strides=(2, 2), padding='valid')(shortcut)\n                x = BatchNormalization()(x)\n                shortcut = BatchNormalization()(shortcut)            \n\n                x = Add()([x, shortcut])    \n                x = Activation('relu')(x)    \n\n                shortcut = x              \n\n            else:\n                x = Conv2D(128, (1, 1), strides=(1, 1), padding='valid')(x)\n                x = BatchNormalization()(x)\n                x = Activation('relu')(x)\n\n                x = Conv2D(128, (3, 3), strides=(1, 1), padding='same')(x)\n                x = BatchNormalization()(x)\n                x = Activation('relu')(x)\n\n                x = Conv2D(512, (1, 1), strides=(1, 1), padding='valid')(x)\n                x = BatchNormalization()(x)            \n\n                x = Add()([x, shortcut])     \n                x = Activation('relu')(x)\n\n                shortcut = x      \n\n        return x\n\n    def conv4_layer(x):\n        shortcut = x        \n\n        for i in range(6):     \n            if(i == 0):            \n                x = Conv2D(256, (1, 1), strides=(2, 2), padding='valid')(x)\n                x = BatchNormalization()(x)\n                x = Activation('relu')(x)        \n\n                x = Conv2D(256, (3, 3), strides=(1, 1), padding='same')(x)\n                x = BatchNormalization()(x)\n                x = Activation('relu')(x)  \n\n                x = Conv2D(1024, (1, 1), strides=(1, 1), padding='valid')(x)\n                shortcut = Conv2D(1024, (1, 1), strides=(2, 2), padding='valid')(shortcut)\n                x = BatchNormalization()(x)\n                shortcut = BatchNormalization()(shortcut)\n\n                x = Add()([x, shortcut]) \n                x = Activation('relu')(x)\n\n                shortcut = x               \n\n            else:\n                x = Conv2D(256, (1, 1), strides=(1, 1), padding='valid')(x)\n                x = BatchNormalization()(x)\n                x = Activation('relu')(x)\n\n                x = Conv2D(256, (3, 3), strides=(1, 1), padding='same')(x)\n                x = BatchNormalization()(x)\n                x = Activation('relu')(x)\n\n                x = Conv2D(1024, (1, 1), strides=(1, 1), padding='valid')(x)\n                x = BatchNormalization()(x)            \n\n                x = Add()([x, shortcut])    \n                x = Activation('relu')(x)\n\n                shortcut = x      \n\n        return x\n\n    def conv5_layer(x):\n        shortcut = x    \n\n        for i in range(3):     \n            if(i == 0):            \n                x = Conv2D(512, (1, 1), strides=(2, 2), padding='valid')(x)\n                x = BatchNormalization()(x)\n                x = Activation('relu')(x)        \n\n                x = Conv2D(512, (3, 3), strides=(1, 1), padding='same')(x)\n                x = BatchNormalization()(x)\n                x = Activation('relu')(x)  \n\n                x = Conv2D(2048, (1, 1), strides=(1, 1), padding='valid')(x)\n                shortcut = Conv2D(2048, (1, 1), strides=(2, 2), padding='valid')(shortcut)\n                x = BatchNormalization()(x)\n                shortcut = BatchNormalization()(shortcut)            \n\n                x = Add()([x, shortcut])  \n                x = Activation('relu')(x)      \n\n                shortcut = x               \n\n            else:\n                x = Conv2D(512, (1, 1), strides=(1, 1), padding='valid')(x)\n                x = BatchNormalization()(x)\n                x = Activation('relu')(x)\n\n                x = Conv2D(512, (3, 3), strides=(1, 1), padding='same')(x)\n                x = BatchNormalization()(x)\n                x = Activation('relu')(x)\n\n                x = Conv2D(2048, (1, 1), strides=(1, 1), padding='valid')(x)\n                x = BatchNormalization()(x)           \n\n                x = Add()([x, shortcut]) \n                x = Activation('relu')(x)       \n\n                shortcut = x                  \n\n        return x\n\n    x = conv1_layer(input_tensor)\n    x = conv2_layer(x)\n    x = conv3_layer(x)\n    x = conv4_layer(x)\n    x = conv5_layer(x)\n    x = GlobalAveragePooling2D()(x)\n    output_tensor = Dense(K, activation='softmax')(x)\n\n    resnet50 = Model(input_tensor, output_tensor)\n    resnet50.summary()"},{"metadata":{},"cell_type":"markdown","source":"# 훈련을통해 정확도 검증"},{"metadata":{"trusted":true},"cell_type":"code","source":"def top_3_accuracy(x,y): \n    t3 = top_k_categorical_accuracy(x,y, 3)\n    return t3\n\nlearning_rate = 0.0001\nreduceLROnPlat = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3, \n                                   verbose=1, mode='auto', min_delta=0.005, cooldown=5, min_lr=learning_rate)\nearlystop = EarlyStopping(monitor='val_top_3_accuracy', mode='max', patience=4) \ncallbacks = [reduceLROnPlat]\n\nCNN.compile(loss='categorical_crossentropy',\n              optimizer='adam',\n              metrics=['accuracy', top_3_accuracy])\n\nhistory = CNN.fit(x=X_train, y=Y_train,\n          batch_size = 128,\n          epochs = 60,\n          validation_data = (X_val, Y_val),\n          callbacks = callbacks,\n          verbose = 1)\n\n#drop out no -> 0.75 0.90","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 그래프를 통한 성능 검증"},{"metadata":{"trusted":true},"cell_type":"code","source":"acc = history.history['accuracy']\nval_acc = history.history['val_accuracy']\nloss = history.history['loss']\nval_loss = history.history['val_loss']\n\nepochs = range(1,len(acc) + 1 )\n\nplt.plot(epochs, acc, 'bo' , label = 'Training Accuracy')\nplt.plot(epochs, val_acc, 'b' , label = 'Validation Accuracy')\nplt.title('Training and Validation accuracy')\nplt.legend()\n\nplt.figure()\n\nplt.plot(epochs, loss, 'bo' , label = 'Training Loss')\nplt.plot(epochs, val_loss, 'b' , label = 'Validation Loss')\nplt.title('Training and Validation Loss')\nplt.legend()\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# test데이터 전처리"},{"metadata":{"trusted":true},"cell_type":"code","source":"def preprocessing_test(df) :\n    X= []\n    keys = df.iloc[:].index\n    for i in tqdm(range(len(df.loc[keys,'drawing'].values))) :\n        drawing = ast.literal_eval(df.loc[keys,'drawing'].values[i])\n        img = make_img(drawing)\n        img = np.array(img.resize((64,64)))\n        img = img.reshape(64,64,1)\n        X.append(img)\n    \n    tmpx = np.array(X)\n    return tmpx\n\ntest = pd.read_csv(os.path.join('/kaggle/input/quickdraw-doodle-recognition', 'test_simplified.csv'))\nx_test = preprocessing_test(test)\nprint(test.shape, x_test.shape)\ntest.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.imshow(x_test[0].reshape(64,64))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# test데이터 예측"},{"metadata":{"trusted":true},"cell_type":"code","source":"imgs = x_test\npred = CNN.predict(imgs, verbose=1)\ntop_3 = np.argsort(-pred)[:, 0:3]\nprint(\"Finished !!\")\n\n#print(pred)\nprint(top_3)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# top3 예측값 클래스이름으로 변환"},{"metadata":{"trusted":true},"cell_type":"code","source":"top_3_pred = ['%s %s %s' % (class_label[k[0]], class_label[k[1]], class_label[k[2]]) for k in top_3]\nprint(top_3_pred[0:5])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 제출"},{"metadata":{"trusted":true},"cell_type":"code","source":"preds_df = pd.read_csv('/kaggle/input/quickdraw-doodle-recognition/sample_submission.csv', index_col=['key_id'])\npreds_df['word'] = top_3_pred\npreds_df.to_csv('subcnn_small.csv')\npreds_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.7.2"}},"nbformat":4,"nbformat_minor":1}