{"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":"This notebook should provide accurace result around 0.996. However, it is not possible to submit, because they require to turn off Internet. Without Internet, is not possible to download pretrained model. Dead-end...","metadata":{}},{"cell_type":"code","source":"from fastai.vision.all import *\nimport pandas as pd\n%matplotlib inline\nset_seed(3865)","metadata":{"execution":{"iopub.status.busy":"2022-07-10T03:47:36.775847Z","iopub.execute_input":"2022-07-10T03:47:36.777142Z","iopub.status.idle":"2022-07-10T03:47:36.785605Z","shell.execute_reply.started":"2022-07-10T03:47:36.777090Z","shell.execute_reply":"2022-07-10T03:47:36.784489Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Convert data to image files\nAt the beginning I want to convert dataset into the typical vision flow for fastai.","metadata":{}},{"cell_type":"code","source":"# this need only for the image conversion\nimport numpy as np\nimport os\nimport cv2","metadata":{"execution":{"iopub.status.busy":"2022-07-10T03:47:36.789339Z","iopub.execute_input":"2022-07-10T03:47:36.790187Z","iopub.status.idle":"2022-07-10T03:47:37.040713Z","shell.execute_reply.started":"2022-07-10T03:47:36.790145Z","shell.execute_reply":"2022-07-10T03:47:37.039632Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# function to convert csv file into PNG images inside of categorized file tree\n\ninpSize = 28 # input image size\ndef makeTree( tpath, csvpath, withlabel=True ): # make file tree at tpath from csv dataframe\n    tpd = pd.read_csv(csvpath)\n    # tpd = tpd[:30] # short test\n    os.makedirs(tpath, exist_ok=True) # make train or valid or test folder\n    whiteImg = np.ones((28,28))*255\n    \n    for i in range(len(tpd)):\n        img = np.array(tpd.iloc[i,1:]).reshape(28,28)\n        img2 = whiteImg - img\n        catpath = tpath\n        if withlabel:\n            categ = str(tpd.iloc[i].label)\n            catpath = tpath + '/' + categ\n            os.makedirs(catpath, exist_ok=True)\n        cv2.imwrite(catpath + '/' + str(i) + '.png', img2)\n    \n    return","metadata":{"execution":{"iopub.status.busy":"2022-07-10T03:47:37.043442Z","iopub.execute_input":"2022-07-10T03:47:37.043963Z","iopub.status.idle":"2022-07-10T03:47:37.051391Z","shell.execute_reply.started":"2022-07-10T03:47:37.043931Z","shell.execute_reply":"2022-07-10T03:47:37.050566Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"makeTree('./Kannada-PNG/train', '../input/Kannada-MNIST/train.csv', withlabel=True)","metadata":{"execution":{"iopub.status.busy":"2022-07-10T03:47:37.052850Z","iopub.execute_input":"2022-07-10T03:47:37.053516Z","iopub.status.idle":"2022-07-10T03:48:11.815190Z","shell.execute_reply.started":"2022-07-10T03:47:37.053465Z","shell.execute_reply":"2022-07-10T03:48:11.814168Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# test files are not labeled, \n# so we put them into upper folder, otherwise they will all be auto-labeled as 'test'\nmakeTree('./test', '../input/Kannada-MNIST/test.csv', withlabel=False)","metadata":{"execution":{"iopub.status.busy":"2022-07-10T03:48:11.816972Z","iopub.execute_input":"2022-07-10T03:48:11.817390Z","iopub.status.idle":"2022-07-10T03:48:14.041956Z","shell.execute_reply.started":"2022-07-10T03:48:11.817361Z","shell.execute_reply":"2022-07-10T03:48:14.040879Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# test if we really built an image\n# timg = cv2.imread('./Kannada-PNG/train/8/18.png', cv2.IMREAD_GRAYSCALE)\n# plt.imshow(timg, cmap='gray')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-10T03:48:14.043201Z","iopub.execute_input":"2022-07-10T03:48:14.044494Z","iopub.status.idle":"2022-07-10T03:48:14.048966Z","shell.execute_reply.started":"2022-07-10T03:48:14.044441Z","shell.execute_reply":"2022-07-10T03:48:14.047953Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Now is fastai part","metadata":{}},{"cell_type":"code","source":"import albumentations as Alb\nclass AlbTransform(Transform):\n    def __init__(self, aug): self.aug = aug\n    def encodes(self, img: PILImage):\n        aug_img = self.aug(image=np.array(img))['image']\n        return PILImage.create(aug_img)\n    \ndef get_augs(): return Alb.Compose([\n    # Alb.InvertImg(p=1.), # just because I like it white\n    Alb.ShiftScaleRotate(rotate_limit=20, border_mode=0, value=(255,255,255) ),\n    # Alb.RandomResizedCrop(28,28),\n])\n\n# super small image sizes may not work on all networks\n# also resizing will make edges smoother\n# item_tfms = [Resize(56), AlbTransform(get_augs())] \nitem_tfms = [AlbTransform(get_augs())] \nbatch_tfms = Normalize.from_stats(*imagenet_stats) ","metadata":{"execution":{"iopub.status.busy":"2022-07-10T03:48:14.050523Z","iopub.execute_input":"2022-07-10T03:48:14.050936Z","iopub.status.idle":"2022-07-10T03:48:15.105704Z","shell.execute_reply.started":"2022-07-10T03:48:14.050895Z","shell.execute_reply":"2022-07-10T03:48:15.104706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# create dataloader from the folder structure\ndls = ImageDataLoaders.from_folder( './Kannada-PNG', train='train', valid=None, valid_pct=0.01, \n    item_tfms=item_tfms, batch_tfms=batch_tfms, bs=256, shuffle=True )","metadata":{"execution":{"iopub.status.busy":"2022-07-10T03:48:15.106963Z","iopub.execute_input":"2022-07-10T03:48:15.107907Z","iopub.status.idle":"2022-07-10T03:48:20.250338Z","shell.execute_reply.started":"2022-07-10T03:48:15.107869Z","shell.execute_reply":"2022-07-10T03:48:20.249368Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dls.vocab","metadata":{"execution":{"iopub.status.busy":"2022-07-10T03:48:20.251417Z","iopub.execute_input":"2022-07-10T03:48:20.251720Z","iopub.status.idle":"2022-07-10T03:48:20.259111Z","shell.execute_reply.started":"2022-07-10T03:48:20.251694Z","shell.execute_reply":"2022-07-10T03:48:20.258258Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# uncomment to test data loaders\ndls.train.show_batch(max_n=12)\n# dls.valid.show_batch(max_n=12)\nlen(dls.train.items)\n# dls.vocab","metadata":{"execution":{"iopub.status.busy":"2022-07-10T03:48:20.260225Z","iopub.execute_input":"2022-07-10T03:48:20.260695Z","iopub.status.idle":"2022-07-10T03:48:21.207632Z","shell.execute_reply.started":"2022-07-10T03:48:20.260665Z","shell.execute_reply":"2022-07-10T03:48:21.206965Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# cannot use pre-trained model because for this notebook internet should be disabled\n# resnet18 works well even on 28 x 28, achieve 0.99 after 4 epochs\n# densenet121 require bigger image, 56x56 will work \nlearn = vision_learner(dls, xresnet34, path='.', pretrained=False,\n    # loss_func=FocalLoss(),  \n    loss_func=LabelSmoothingCrossEntropy(), \n    opt_func=ranger,\n    metrics=[accuracy, F1Score(average='weighted')]  ).to_fp16()","metadata":{"execution":{"iopub.status.busy":"2022-07-10T03:48:27.997089Z","iopub.execute_input":"2022-07-10T03:48:27.997753Z","iopub.status.idle":"2022-07-10T03:48:28.680193Z","shell.execute_reply.started":"2022-07-10T03:48:27.997713Z","shell.execute_reply":"2022-07-10T03:48:28.679202Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lrs = learn.lr_find(suggest_funcs=(minimum, steep, valley, slide))\nprint('lrs.valley=', lrs.valley)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learn.fit_one_cycle(50, lrs.valley, # 2e-3, # lr_max=lrs.valley, \n     cbs=[ShowGraphCallback(), EarlyStoppingCallback(patience=5), SaveModelCallback()])","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tfnames = get_image_files('./test')\ntst_dl = dls.test_dl(tfnames, with_labels=False, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2022-07-10T03:49:53.171383Z","iopub.execute_input":"2022-07-10T03:49:53.171759Z","iopub.status.idle":"2022-07-10T03:49:53.216753Z","shell.execute_reply.started":"2022-07-10T03:49:53.171726Z","shell.execute_reply":"2022-07-10T03:49:53.215642Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# uncomment to see if dataloader is working\n# tst_dl.show_batch(max_n=12)","metadata":{"execution":{"iopub.status.busy":"2022-07-10T03:50:04.923300Z","iopub.execute_input":"2022-07-10T03:50:04.924083Z","iopub.status.idle":"2022-07-10T03:50:05.643385Z","shell.execute_reply.started":"2022-07-10T03:50:04.924045Z","shell.execute_reply":"2022-07-10T03:50:05.642052Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds = learn.tta(dl=tst_dl, n=32, use_max=False)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predss = learn.dls.vocab[np.argmax(preds[0], axis=1)] # convert to our classes from probabilities\nidlist = [item.stem for item in tst_dl.items]\nsubm_df = pd.DataFrame(list(zip(idlist, predss)), columns =['id', 'label'])\nsubm_df.to_csv('submission.csv', header=True, index=False)\nsubm_df","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Clean up image files\nOtherwise it will burn time comitting.","metadata":{}},{"cell_type":"code","source":"from shutil import rmtree\nrmtree('./Kannada-PNG', ignore_errors=True)\nrmtree('./test', ignore_errors=True)","metadata":{"execution":{"iopub.status.busy":"2022-06-15T10:26:17.469861Z","iopub.execute_input":"2022-06-15T10:26:17.470315Z","iopub.status.idle":"2022-06-15T10:26:19.672229Z","shell.execute_reply.started":"2022-06-15T10:26:17.470264Z","shell.execute_reply":"2022-06-15T10:26:19.670658Z"},"trusted":true},"execution_count":null,"outputs":[]}]}