{"cells":[{"metadata":{},"cell_type":"markdown","source":"# CNN 을 이용한 Image Classification"},{"metadata":{"trusted":true},"cell_type":"markdown","source":"사용한 프레임워크: tensorflow, Keras\n1. Keras 사용이유: 딥러닝에 많이 쓰이는 high level api 로 이해하기 쉬움\n2. Convolutional Neural Network 적용이유 : image classification 에 많이 써왔던 방식이고, 대체로 잘 작동하기에\n3. https://www.kaggle.com/jpmiller/image-based-cnn 를 참고함\n4. Resource 의 제한으로 training image 를 다 쓰지 않음 - 정확성 개선 가능"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","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)\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nimport os\nprint(os.listdir(\"../input\"))\n\n# Any results you write to the current directory are saved as output.","execution_count":1,"outputs":[{"output_type":"stream","text":"['test_raw.csv', 'test_simplified.csv', 'train_simplified', 'sample_submission.csv']\n","name":"stdout"}]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"#import\nfrom PIL import Image, ImageDraw\nimport json\n\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D\nfrom tensorflow.keras.layers import Dense, Dropout, Flatten\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.metrics import top_k_categorical_accuracy\nfrom tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping\n\nimport matplotlib.pyplot as plt\n%matplotlib inline","execution_count":2,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 파일 경로와 label dictionary 설정","execution_count":3,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"trainFiles = os.listdir(\"../input/train_simplified/\")\ncommonDir = \"../input/train_simplified/\"\nlabelDict = {i: v[:-4].replace(\" \", \"_\") for i, v in enumerate(trainFiles)}\nlabelDictInv = {v[:-4]: i for i, v in enumerate(trainFiles)}","execution_count":4,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#global variables","execution_count":5,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"imgSize = 64\ndataPerClass = 100\nnumClasses = 340","execution_count":7,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# DataFrame 에 저장된 이미지 데이터를 CNN 에 넣을수 있게 64x64 이미지 포맷으로 바꿔주는 helper functions","execution_count":8,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def convertTo2dImage(strokes):\n    image = Image.new(\"P\", (256,256), color=255)\n    image_draw = ImageDraw.Draw(image)\n    for stroke in 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((imgSize,imgSize))\n    return np.array(image)/255\n\ndef dfToImageArray(data, size=imgSize):\n    x = np.zeros((len(data), size, size, 1))\n    for i, strokes in enumerate(data):\n        x[i, :, :, 0] = convertTo2dImage(strokes)\n    \n    return x","execution_count":9,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Training 파일들을 읽어서 pandas DataFrame 으로 저장하기","execution_count":10,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"colNames = ['countrycode', 'drawing', 'key_id', 'recognized', 'timestamp', 'word']\ndrawList = []\nfor file in trainFiles:\n    data = pd.read_csv(commonDir+file, nrows=dataPerClass)\n    data = data[data.recognized==True]\n    drawList.append(data)\ndraw_df = pd.DataFrame(np.concatenate(drawList), columns=colNames)\n#change str to list\ndraw_df['drawing'] = draw_df['drawing'].apply(json.loads)","execution_count":11,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# train = pd.read_csv(commonDir+trainFiles[0], nrows=500)\n# label = np.full((train.shape[0],1),1)\n# np.concatenate((train, label), axis=1)","execution_count":12,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Use train_test_split method\n# feature 와 label 만들기\nfeatData = draw_df['drawing']\nlabels = draw_df['word'].replace(labelDictInv)\n\nfrom sklearn.model_selection import train_test_split\n\nX_train, X_test, y_train, y_test = train_test_split(featData,labels,\n                                                   test_size = 0.1,\n                                                   random_state = 101)\n\nX_train = dfToImageArray(X_train)\nX_test = dfToImageArray(X_test)\n\ny_train = keras.utils.to_categorical(y_train, num_classes=numClasses)\ny_test = keras.utils.to_categorical(y_test, num_classes=numClasses)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# sample simplified image\nplt.imshow(X_train[0,:,:,0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(X_train.shape, '\\n',\n      X_test.shape, '\\n',\n      y_train.shape, '\\n',\n      y_test.shape, '\\n')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Keras를 사용해서 Convolutional Neural Network 모델 만들기","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=(imgSize, imgSize, 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))\n\nmodel.add(Flatten())\nmodel.add(Dense(680, activation='relu'))\nmodel.add(Dropout(0.5))\nmodel.add(Dense(340, activation='softmax'))\nmodel.summary()","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\n\nreduceLROnPlat = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3, \n                                   verbose=1, mode='auto', min_delta=0.005, cooldown=5, min_lr=0.0001)\nearlystop = EarlyStopping(monitor='val_top_3_accuracy', mode='max', patience=5) \ncallbacks = [reduceLROnPlat, earlystop]\n\nmodel.compile(loss='categorical_crossentropy',\n              optimizer='adam',\n              metrics=['accuracy', top_3_accuracy])\n\nmodel.fit(x=X_train, y=y_train,\n          batch_size = 32,\n          epochs = 10,\n          validation_data = (X_test, y_test),\n          callbacks = callbacks,\n          verbose = 1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"markdown","source":"# 테스트 이미지에 적용 및 제출"},{"metadata":{"trusted":true},"cell_type":"code","source":"ttvlist = []\nreader = pd.read_csv('../input/test_simplified.csv', index_col=['key_id'],\n    chunksize=2048)\ndrawList = []\nfor data in reader:\n    data['drawing'] = data['drawing'].apply(json.loads)\n    test = dfToImageArray(data.drawing.values)\n    testPreds = model.predict(test, verbose=0)\n    ttvs = np.argsort(-testPreds)[:, 0:3] #select top 3 categories\n    ttvlist.append(ttvs)\n\nttvarray = np.concatenate(ttvlist)","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(labelDict)\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('cnn_submission.csv')\nsub.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":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}