{"cells":[{"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)\nimport cv2 as opencv\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import confusion_matrix\nfrom sklearn import svm\nfrom sklearn.decomposition import PCA\n#import mahotas\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 all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"train = pd.read_csv('../input/Kannada-MNIST/train.csv')\nprint('Train shape = ', train.shape)\nsplitTrain, splitTest, splitTrainLabels, splitTestLabels = train_test_split(train.iloc[:, 1:], train.iloc[:, 0], test_size=0.2)\nprint('splitTrain size = ', splitTrain.shape)\nprint('splitTest size = ', splitTest.shape)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Test-1: Using a simple KNN classifier**"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Prepare the training dataset for the KNN classifier. The KNN classifier requires the data and the labels\n# to be a float32 format\nknnTrain = np.array(splitTrain).astype(np.float32)\nknnTrainLabels = np.array(splitTrainLabels).astype(np.float32)\n\n# Train the KNN classifier\nknn = opencv.ml.KNearest_create()\nknn.train(knnTrain, opencv.ml.ROW_SAMPLE, knnTrainLabels)\n\n# Prepare the training dataset for the KNN classifier. The KNN classifier requires the  data and the labels\n# to be a float32 format\nknnTest = np.array(splitTest).astype(np.float32)\nknnTestLabels = np.array(splitTestLabels).astype(np.float32)\n\n# Run the KNN classifier\nret, result, neighbours, dist = knn.findNearest(knnTest, k=5)\n\n# Measure the accuracy\nknnTestLabels = knnTestLabels.reshape(knnTestLabels.size, 1)\nmatches  = result == knnTestLabels\ncorrect  = np.count_nonzero(matches) \naccuracy = correct * 100.0 / result.size\nknnCM = confusion_matrix(result, knnTestLabels)\nprint('KNN Accuracy = ', accuracy)\nprint(knnCM)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Prepare the training dataset for the KNN classifier. The KNN classifier requires the data and the labels\n# to be a float32 format\nknnTrain = np.array(splitTrain).astype(np.float32)\nknnTrainLabels = np.array(splitTrainLabels).astype(np.float32)\n\n# Train the KNN classifier\nknn = opencv.ml.KNearest_create()\nknn.train(knnTrain, opencv.ml.ROW_SAMPLE, knnTrainLabels)\n\n# Prepare the training dataset for the KNN classifier. The KNN classifier requires the  data and the labels\n# to be a float32 format\nknnTest = np.array(splitTest).astype(np.float32)\nknnTestLabels = np.array(splitTestLabels).astype(np.float32)\n\n# Run the KNN classifier\nret, result, neighbours, dist = knn.findNearest(knnTest, k=5)\n\n# Measure the accuracy\nknnTestLabels = knnTestLabels.reshape(knnTestLabels.size, 1)\nmatches  = result == knnTestLabels\ncorrect  = np.count_nonzero(matches) \naccuracy = correct * 100.0 / result.size\nknnCM = confusion_matrix(result, knnTestLabels)\nprint('KNN Accuracy = ', accuracy)\nprint(knnCM)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Test-2: Use the image attributes as feature vectors in a SVM classifier **\nThe inspiration for this was drawn from this post [\"Understanding SVMs for Image Classication\"](https://medium.com/@dataturks/understanding-svms-for-image-classification-cf4f01232700). \n\nThough I intended to use Harlick - https://gogul.dev/software/texture-recognition, it was taking way too much time and decided to do away with it and use Moments alone. "},{"metadata":{"trusted":true},"cell_type":"code","source":"def fd_hu_moments(rasterImg):\n    moments = opencv.HuMoments(opencv.moments(rasterImg, binaryImage=True)).flatten()\n    return moments\n\n\"\"\"\ndef fd_haralick(rasterImg):\n    haralick = mahotas.features.haralick(image).mean(axis=0)\n    return haralick\n\"\"\"\nimage = splitTrain.to_numpy()\n\nrasterImg = image[0].reshape(28, 28)\nfdTrain = fd_hu_moments(rasterImg)\nfor i in range (1, image.shape[0]):\n    rasterImg = image[i].reshape(28, 28)\n    moments = fd_hu_moments(rasterImg)\n    #haralick = fd_haralick(rasterImg)\n    fdTrain = np.vstack((fdTrain, moments))\n\nprint('Starting to fit the SVM classifier')\nsv = svm.SVC(kernel='rbf', C=9, gamma='scale', decision_function_shape='ovo')\nsv.fit(fdTrain, splitTrainLabels)\nprint('Finished fitting the SVM classifier')\n\n# Measure the accuracy against the training dataset\nimage = splitTest.to_numpy()\nrasterImg = image[0].reshape(28, 28)\nmoments = fd_hu_moments(rasterImg)\nfdTest = moments\nfor i in range (1, image.shape[0]):\n    rasterImg = image[i].reshape(28, 28)\n    moments = fd_hu_moments(rasterImg)\n    #haralick = fd_haralick(rasterImg)\n    fdTest = np.vstack((fdTest, moments))\nresult = sv.predict(fdTest)\n\n# Measure accuracy\nsvmTestLabels = np.array(splitTestLabels).astype(np.float32)\nmatches  = result == svmTestLabels\ncorrect  = np.count_nonzero(matches) \naccuracy = correct * 100.0 / result.size\nsvmCM = confusion_matrix(result, svmTestLabels)\nprint('SVM Accuracy = ', accuracy)\nprint(svmCM)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def fd_hu_moments(rasterImg):\n    moments = opencv.HuMoments(opencv.moments(rasterImg, binaryImage=True)).flatten()\n    return moments\n\ndef fd_haralick(rasterImg):\n    haralick = mahotas.features.haralick(image).mean(axis=0)\n    return haralick\n\nimage = splitTrain.to_numpy()\n\nrasterImg = image[0].reshape(28, 28)\nfdTrain = fd_hu_moments(rasterImg)\nfor i in range (1, image.shape[0]):\n    rasterImg = image[i].reshape(28, 28)\n    moments = fd_hu_moments(rasterImg)\n    #haralick = fd_haralick(rasterImg)\n    fdTrain = np.vstack((fdTrain, moments))\n\nprint('Starting to fit the SVM classifier')\nsv = svm.SVC(kernel='rbf', C=9, gamma='scale', decision_function_shape='ovo')\nsv.fit(fdTrain, splitTrainLabels)\nprint('Finished fitting the SVM classifier')\n\n# Measure the accuracy against the training dataset\nimage = splitTest.to_numpy()\nrasterImg = image[0].reshape(28, 28)\nmoments = fd_hu_moments(rasterImg)\nfdTest = moments\nfor i in range (1, image.shape[0]):\n    rasterImg = image[i].reshape(28, 28)\n    moments = fd_hu_moments(rasterImg)\n    #haralick = fd_haralick(rasterImg)\n    fdTest = np.vstack((fdTest, moments))\nresult = sv.predict(fdTest)\n\n# Measure accuracy\nsvmTestLabels = np.array(splitTestLabels).astype(np.float32)\nmatches  = result == svmTestLabels\ncorrect  = np.count_nonzero(matches) \naccuracy = correct * 100.0 / result.size\nsvmCM = confusion_matrix(result, svmTestLabels)\nprint('SVM Accuracy = ', accuracy)\nprint(svmCM)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Test-3: Use PCA on the input and use that as feature vectors in a SVM classifier**\nThe image attributes used as feature vectors did not give good results. There could be multiple reasons for that. \n1. I used only the moments feature to train the classifier, which perhaps does not differ a whole lot across the different digits\n2. Unlike PCA, which can be tuned to explain a certain amount of variance, the moments attribute gives no such guarantee. Hence, it makes sense to use the PCA on the input to see if it can give better results. "},{"metadata":{"trusted":true},"cell_type":"code","source":"# Train the model against the training dataset\npca = PCA(n_components=0.7, svd_solver='full', whiten=True)\ntrainPCA = pca.fit_transform(splitTrain)\nsv = svm.SVC(kernel='rbf', C=9, gamma='scale', decision_function_shape='ovo')\nsv.fit(trainPCA, splitTrainLabels)\n\n# Measure the accuracy against the cross validation dataset\ntestPCA = pca.transform(splitTest)\nresult = sv.predict(testPCA)\n\n# Measure accuracy\nmatches  = result == svmTestLabels\ncorrect  = np.count_nonzero(matches) \naccuracy = correct * 100.0 / result.size\nsvmCM = confusion_matrix(result, svmTestLabels)\nprint('SVM Accuracy = ', accuracy)\nprint(svmCM)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Preparing submission**"},{"metadata":{"trusted":true},"cell_type":"code","source":"test = pd.read_csv('../input/Kannada-MNIST/test.csv')\nsubmission = pd.read_csv('../input/Kannada-MNIST/sample_submission.csv')\nprint(test.shape)\ntestPCA = pca.transform(test.iloc[:, 1:])\nresult = sv.predict(testPCA)\nsubmission['label'] = result\nsubmission.to_csv('submission.csv', index=False)\nsubmission.head()","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":1}