{"cells":[{"metadata":{"_uuid":"acb39ca87cfe7bbc8285638f890168967347dfb4"},"cell_type":"markdown","source":"# DIGIT RECOGNIZER\n## K-Neighbour classifier with image cutting+rescaling"},{"metadata":{"_uuid":"171e66c00918282940aa2886c79c5f2ebc93f7e1"},"cell_type":"markdown","source":"## Function declaration"},{"metadata":{"trusted":true,"_uuid":"96160e9a9981b716af5aa185c478ff530b021cd7"},"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nfrom matplotlib import pyplot as plt\n%pylab inline","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2d6a6923bdafa18fee23153f841c4cb8f797d7de"},"cell_type":"code","source":"def plot_examples(d, x1,x2):\n    fig, ax = subplots(1,1,figsize=(17,4))\n    plt.subplot(141)\n    pylab.imshow(d.values[4,:].reshape(x1,x2));\n    plt.subplot(142)\n    pylab.imshow(d.values[6,:].reshape(x1,x2));\n    plt.subplot(143)\n    pylab.imshow(d.values[7,:].reshape(x1,x2));\n    plt.subplot(144)\n    pylab.imshow(d.values[8,:].reshape(x1,x2));","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"961b9b9a729cab741090dbfc4ee1bacf92de42eb"},"cell_type":"code","source":"# Rescalig image to new dimentions x_dim and y_dim\n# Linear approximation of pixels brightness is used\n\ndef img_deform(im, y_dim, x_dim):  \n    #print('im init shape', im.shape)\n    \n    # Scale image along width\n    im_new = np.zeros((y_dim, im.shape[1]))\n    for x in range(0, im.shape[1]):\n        im_new[:,x] = pylab.interp(np.arange(0, im.shape[0], im.shape[0]*1./y_dim), range(im.shape[0]), im[:,x])\n    \n    # Scale image along height   \n    im_new_2 = np.zeros((y_dim, x_dim))\n    for y in range(0, y_dim):\n        im_new_2[y,:] = pylab.interp(np.arange(0, im.shape[1], im.shape[1]*1./x_dim), range(im_new.shape[1]), im_new[y,:])        \n    \n    #print('im new shape', im_new_2.shape)\n    return np.round(im_new_2,0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3cbc55839f79dddbef829d576caba79302b23f8f"},"cell_type":"code","source":"# Cutting empty space from image: from bottom, top, left and right \n# delete rows and columns respectively while sum of pixels brightness is equal to zero\n\ndef im_cut(im):\n    x0 = 0\n    x1 = im.shape[1]+1\n    y0 = 0\n    y1 = im.shape[0]+1    \n    s = 0\n    for i in range(5):\n        si = im[:,i].sum()\n        if si==0:\n            x0 += 1\n        else:\n            break\n    s = 0\n    for i in range(5):\n        si = im[:,-i].sum()\n        if si==0:\n            x1 -= 1\n        else:\n            break\n    s = 0\n    for i in range(5):\n        si = im[i,:].sum()\n        if si==0:\n            y0 += 1\n        else:\n            break\n    s = 0\n    for i in range(5):\n        si = im[-i,:].sum()\n        if si==0:\n            y1 -= 1\n        else:\n            break\n    im_new = im[y0:y1,x0:x1]\n    #print('img_cut: '+str(im_new.shape))\n    \n    return im_new  ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"51331d97e95ebbff1ea2b3c1bbad784d984ac8b9"},"cell_type":"code","source":"# Transform images with cutting and rescaling in cycle\n\ndef transform_imgs(d0, x0, x1=np.NaN, x2=np.NaN):\n    d1=[]\n    for n, img in enumerate(d0.values[:,:]):\n        #print(n)\n        img_new = img.reshape(x0,x0)\n        if x1 is not np.NaN and x2 is not np.NaN:\n            img_new = (im_cut(img_new))\n            img_new = (img_deform(img_new, x1, x2))\n        d1.append(list(ravel(img_new)))\n    d1 = pd.DataFrame(data=d1)\n    #print(d1.shape)\n    return d1","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"cc9128db7ada24cd1b02a0a65613132be2f597ff"},"cell_type":"markdown","source":"## Prepair DATA"},{"metadata":{"trusted":true,"_uuid":"cb85f7b4332d4eef9fb11da989cdb317b9f6bdc1"},"cell_type":"code","source":"# import DATA\n\nd0 = pd.read_csv('../input/train.csv')\nlabs = d0.label\nd0.drop('label', axis=1, inplace=True)\nprint(d0.shape)\nd0.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1b4b4ae120f2ec7898bd2593a2d96be226e05288"},"cell_type":"code","source":"d1 = transform_imgs(d0, 28)\nd2 = transform_imgs(d0, 28, 14, 14)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"62182fe54be38d8bd2186159aa7f406eaffee0f4"},"cell_type":"code","source":"plot_examples(d1, 28, 28)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6088beb129945fa9984f66e054142f7a83d29d3e"},"cell_type":"code","source":"plot_examples(d2, 14, 14)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f97a395b6b1dc2fd33052f867fcd50cf83c8d1d2"},"cell_type":"code","source":"from sklearn import model_selection as ms\nx_train1, x_test1, y_train1, y_test1 = ms.train_test_split(d1.values, labs, random_state=0)\nx_train2, x_test2, y_train2, y_test2 = ms.train_test_split(d2.values, labs, random_state=0)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"55cfe6547ebc332e6b29c0d54aaa1b9be1702d39"},"cell_type":"markdown","source":"## Develop and train model"},{"metadata":{"trusted":true,"_uuid":"6a98294a9988ba36ba7602c0513e8a004e97b632"},"cell_type":"code","source":"from sklearn.neighbors import KNeighborsClassifier\nclf = KNeighborsClassifier(n_neighbors=4, weights='distance')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c572883a7777af5b53dd4cdf2e3fc2209adb00cd"},"cell_type":"code","source":"%%time\nfrom sklearn import metrics\n\nclf.fit(x_train1, y_train1)\ny_pred1 = clf.predict(x_test1)\nprint(metrics.classification_report(y_test1, y_pred1, digits=3))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8a20bbc138d7e48898e377d3360efee252d22218"},"cell_type":"code","source":"%%time\n\nclf.fit(x_train2, y_train2)\ny_pred2 = clf.predict(x_test2)\nprint(metrics.classification_report(y_test2, y_pred2, digits=3))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"9731fc9c6107282a56713ee3ff3f5f064b294001"},"cell_type":"markdown","source":"As we can see both data sets give the same efficiency, but classifier trained on cutted and rescaled images is **3 times faster**"},{"metadata":{"trusted":true,"_uuid":"df510995f985df0bc544bfa216824c442f6b1060"},"cell_type":"code","source":"## Take a glance at wrong classified images \n\ny = y_pred2\npyplot.figure(figsize(10, 6))\nn = 0\nfor i in range(len(y)):\n    if y[i]!=y_test2.values[i]:\n        pyplot.subplot(2, 4, n+1)\n        plt.title(str(y[i])+' ('+str(y_test2.values[i])+')')\n        pylab.imshow(d2.values[y_test2.index[i],:].reshape(14,14))\n        n += 1\n    if n==8:\n        break","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"721a52a137b236261c4c3f540d34c72dd9c0a27c"},"cell_type":"markdown","source":"## Submit DATA"},{"metadata":{"trusted":true,"_uuid":"f03c7f61c2a43c4e9d8ff222c8a1b8d7bb0d312b"},"cell_type":"code","source":"d_submit = pd.read_csv('../input/test.csv')\nd_submit.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"eaf38853a6e9ba66b221d8b3634c08645a83cca5"},"cell_type":"code","source":"d_submit = transform_imgs(d_submit, 28, 14, 14)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7c346f7a481ab126dbaaeecd019a3278ac7c1965"},"cell_type":"code","source":"#y_submit = clf.predict(d_submit)\n#submit_df = pd.DataFrame({'ImageId':d_submit.index, 'Label':y_submit})\n#submit_df.to_csv('submit_data.csv',index=False)","execution_count":null,"outputs":[]},{"metadata":{"collapsed":true,"trusted":false,"_uuid":"e637afb0f8ff434d63abc8ed941515e4f80b16c9"},"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":2},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython2","version":"2.7.13"}},"nbformat":4,"nbformat_minor":1}