{"cells":[{"metadata":{},"cell_type":"markdown","source":"기본적으로 Keras를 이용해서 모델을 학습시켰다. <br>\n학습하기전에 데이터 전처리 과정이 생각보다 어려워서 많은 Public 소스를 참고하면서 학습을 진행했다.<br>\n전처리를 끝내고 처음 학습을 할 때는 기본 2개의 컨벌루션 레이어로 이루어진 모델로 학습을 시켰다.<br>\n활성함수와 optimizer로는 많이 사용하는 relu와 Adam을 사용했다.<br><br>\n학습속도가 더뎌서 정확도를 높이기 위해 기본 keras에서 제공하는 MobileNet을 이용하여 학습을 해보기로 했다.<br>\n찾아보니 MoileNet이 정확도도 괜찮게 나오고 파라미터도 적어서 가진 컴퓨터로 학습하기에 적합하다고 생각을 했다.<br>\n그냥 keras에서 제공되는 모델로 학습을 시켜보니 과적합이 심하게 발생해서 validation set에 대해 제대로 학습이 되지 않았다.<br>\n그래서 과적합을 해결 해보고자 기본 모델 마지막 레이어를 Dropout을 적용하여 학습을 시키니 과적합이 어느정도 예방이 됐다.<br>\nMobileNet을 이용하여 val 정확도가 73%까지 나왔지만 최종 정확도는 test_set은 65%가 최대였고, 캐글에 업로드해서 커밋을 하려고 하니 시간이 너무 오래걸려서 제출은 처음 사용했던 기본 모델을 올리게 됐다.<br><br>\n좀 더 성능을 올려보고 싶어서 이미지 사이즈를 키워보려고 했지만 컴퓨터 성능 문제로 32x32가 최대였다.<br>\n기본 모델도 에폭을 올리니 천천히 오르긴 하지만 60%정도까지 올라갔다.<br>"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"import matplotlib.pyplot as plt\n%matplotlib inline\nimport pandas as pd\nimport numpy as np\nimport os\nimport cv2\nfrom PIL import Image, ImageDraw \nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Dense, Dropout, Flatten,Activation\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D\nfrom tensorflow.keras.metrics import top_k_categorical_accuracy, categorical_accuracy\nfrom keras.applications import MobileNet\nfrom keras.optimizers import Adam\nfrom keras.losses import categorical_crossentropy\nfrom tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"shape = (32,32)\ntraining_classes = 340 # how many class we are training now\ntrain_size = 1000\n# 각 클래스당 2000개의 이미지","execution_count":null,"outputs":[]},{"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","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"reduceLROnPlat = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3)\nearlystop = EarlyStopping(monitor='val_top_3_accuracy', mode='max', patience=5) \ncallbacks = [reduceLROnPlat, earlystop]\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = Sequential()\nmodel.add(Conv2D(32, kernel_size=(3, 3), padding='same', activation='relu', input_shape=(shape[0], shape[1], 1)))\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Conv2D(64, kernel_size=(3, 3), padding='same', activation='relu'))\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.2))\nmodel.add(Flatten())\nmodel.add(Dense(680, activation='relu'))\nmodel.add(Dropout(0.5))\nmodel.add(Dense(training_classes, activation='softmax'))\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"scrolled":true,"trusted":true},"cell_type":"code","source":"'''base_model = MobileNet(input_shape=(shape[0], shape[1], 1), include_top=False,alpha=1, weights=None, classes=training_classes)\n\nmm = Sequential()\nmm.add(base_model)\nmm.add(Flatten())\nmm.add(Dropout(0.5))\nmm.add(Dense(1024,activation='relu'))\nmm.add(Dropout(0.5))\nmm.add(Dense(training_classes,activation='softmax'))\n\nmm.summary()'''","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"처음엔 소스를 찾아보다가 아래와 같이 이미지 처리를 했는데 시간이 너무 오래걸렸다."},{"metadata":{"trusted":true},"cell_type":"code","source":"def draw2img(drawing, shape = shape):\n    fig, ax = plt.subplots()\n    drawing = ast.literal_eval(drawing)\n    for x,y in drawing:\n        ax.plot(x, y,'g',  marker='.') #  marker='.',\n    ax.axis('off')\n    fig.canvas.draw()    \n    X = np.array(fig.canvas.renderer._renderer)\n    plt.close(fig)\n    # image resizing. Original X is of various size due to strokes variable's length\n    temp = (cv2.resize(X, shape) / 255.)[::-1]\n    return temp[:,:,1].astype('int8') # only green channel, as we have drawn with green, try bool","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"밑에 함수를 또 바꾼 이유는 default가 float인데 메모리를 최대한 아끼려고 int로 마지막에 바꿔주는 과정"},{"metadata":{},"cell_type":"markdown","source":"train['drawing'] = train['drawing'].apply(draw2img) # for this training set eval() necessary in draw2img\n이런 식으로 만든 함수 적용하면 된다.\n마지막에 컬러값 하나만 가져오는 이유는 굳이 컬러 필요없이 그림의 모양만 파악하면 되므로"},{"metadata":{},"cell_type":"markdown","source":"draw2img 보다 밑에 얘(draw_it)가 더 성능이 좋다. 훨씬 빠르다<br>\ndraw using stroke coordinate(x,y)"},{"metadata":{"trusted":true},"cell_type":"code","source":"# faster conversion function\ndef draw_it(strokes):\n    image = Image.new(\"P\", (256,256), color=255)\n    image_draw = ImageDraw.Draw(image)\n    for stroke in eval(strokes):\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    image = image.resize((shape[0], shape[1]))\n    return np.array(image)/255.","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"이제 얘가 위에 과정을 하나로 합쳐놓은것이다. 이게 훨씬 더 좋다."},{"metadata":{"scrolled":true,"trusted":true},"cell_type":"code","source":"import time\nstart_time = time.time()\n\ntrain = pd.DataFrame()\ni = 0\n#labels = dict()\nfor file in os.listdir('../input/train_simplified/'):\n    print(f\"Reading...{file}.....{i*100/340}% complete\")\n    temp = pd.read_csv('../input/train_simplified/' + file, nrows=train_size, \n                                    usecols = ['drawing', 'word'])\n    # processing data\n    temp['drawing'] = temp['drawing'].apply(draw_it)\n    #global label encoding\n    temp['word']    = np.int16(i)\n    train = train.append(temp)\n    \n    i = i+1\n    if i==training_classes: \n        break\n    if i%10==0:\n        print(f\"Time elasped in reading: {(time.time() - start_time)} seconds ---\") \n\n\nprint(f\"Total Time elasped in reading: {(time.time() - start_time)} seconds ---\") ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# preparing x_train and y_train\nx = np.array(train['drawing'])\ny = np.array(train['word'])\n# each row of x, y is a input \n# y_train to onehot encoding for making them as useful for output softmax layer\n'''\narray([[1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n       [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n'''\ny =y.reshape(-1, 1)  # making it a 2d array like [[1], [1], ]\nfrom sklearn import preprocessing\nenc = preprocessing.OneHotEncoder()\nenc.fit(y)\ny = enc.transform(y).toarray()\n\n#del train 용량때매 삭제해준다.\ndel train\n\n# test train split\n\nfrom sklearn.model_selection import train_test_split\nx_train, x_val, y_train, y_val = train_test_split(\n    x, y, test_size=0.1, random_state=101)\n\nprint(\"Taking care of dimensions--------------------\")\nprint(f\"shape of x_train: {x_train.shape}\")\nprint(f\"shape of x_val: {x_val.shape}\")\nprint(f\"shape of y_train: {y_train.shape}\")\nprint(f\"shape of y_val: {y_val.shape}\")\nprint(f\"shape of image: {x_train[1].shape}\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"사진들의 어레이로 내부에 [32,32]로 포함되어있다. <br>\nex) [[32,32],[32,32],...] <br>\n그래서 이걸 [n,32,32,1]로 reshape해서 학습을 하려고한다."},{"metadata":{"trusted":true},"cell_type":"code","source":"del x\ndel y\nval_len = int(x_val.shape[0])\ntrain_len = int(x_train.shape[0])\nt_val = np.vstack([a for a in x_val]).reshape(val_len,shape[0],shape[0],1)\ndel x_val\n\nt_train = np.vstack([a for a in x_train]).reshape(train_len,shape[0],shape[0],1)\ndel x_train\nprint(t_val.shape)\nprint(t_train.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(loss='categorical_crossentropy',\n              optimizer='adam',\n              metrics=['accuracy', top_3_accuracy])\n\nhist = model.fit(x=t_train, y=y_train,\n          batch_size = 680,\n          epochs = 50,\n          validation_data = (t_val, y_val),\n          callbacks = callbacks,\n          verbose = 1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''mm.compile(optimizer=Adam(lr=0.002), loss='categorical_crossentropy',\n              metrics=[categorical_crossentropy, categorical_accuracy, top_3_accuracy])\nhist = mm.fit(x=t_train, y=y_train,\n          batch_size = 600,\n          epochs = 70,\n          validation_data = (t_val, y_val),\n          verbose=1\n          )'''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def gen_graph(history, title):\n    plt.plot(history.history['top_3_accuracy'])\n    plt.plot(history.history['val_top_3_accuracy'])\n    plt.title('Accuracy ' + title)\n    plt.ylabel('Accuracy')\n    plt.xlabel('Epoch')\n    plt.legend(['train', 'validation', 'Test top 3', 'Validation top 3'], loc='upper left')\n    plt.show()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"gen_graph(hist,'BasicNet')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"temp = pd.read_csv('../input/test_simplified.csv') \ntemp['drawing'] = temp['drawing'].apply(draw_it)\nttest = np.array(temp['drawing']) \ndel temp \nlength = int(ttest.shape[0])\ntest_set = np.vstack([a for a in ttest]).reshape(length,shape[0],shape[1],1)\ndel ttest","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ttvlist = []\ntestpreds = model.predict(test_set,verbose=0)\n#top 3 accuracy\nttvs = np.argsort(-testpreds)[:,0:3]\nttvlist.append(ttvs)\nttvarray = np.concatenate(ttvlist)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"classfiles = os.listdir('../input/train_simplified/')\nnumstonames = {i: v[:-4].replace(\" \", \"_\") for i, v in enumerate(classfiles)} ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"preds_df = pd.DataFrame({'first': ttvarray[:,0], 'second': ttvarray[:,1], 'third': ttvarray[:,2]})\npreds_df = preds_df.replace(numstonames)\npreds_df['words'] = preds_df['first'] + \" \" + preds_df['second'] + \" \" + preds_df['third']\n\nsub = pd.read_csv('../input/sample_submission.csv', index_col=['key_id'])\nsub['word'] = preds_df.words.values\nsub.to_csv('subcnn_small00.csv')","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.6.8"}},"nbformat":4,"nbformat_minor":1}