Created
July 11, 2017 23:50
-
-
Save nbrochu/2aaa9888df85a4127aa9d602ff987cbe to your computer and use it in GitHub Desktop.
OCR Notebook
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": { | |
"scrolled": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"image/png": "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\n1Kj/A7RZxEs25kItAAAAAElFTkSuQmCC\n", | |
"text/plain": [ | |
"<matplotlib.figure.Figure at 0x7fd07c034630>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"image/png": "iVBORw0KGgoAAAANSUhEUgAAApsAAAGoCAYAAAAJlC76AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3X+MXFd58PFnjRuIA+xMQmMDUiLSkmXLojJRlApCA22l\nFipRISHIUtF534r8cGia7EuELWTk9QZHhUjVi6Kk2Y2JRIdN34khaQRCOFJSUASpGmhsFobuJKlo\nUAvedfHcS2BjAnjeP9C448mdueece37cH9+PhBSS+9xz7p3xncfPOeeeqX6/LwAAAIAL20J3AAAA\nAOVFsgkAAABnSDYBAADgDMkmAAAAnCHZBAAAgDMkmwAAAHCGZBMAAADOkGwCAADAGZJNAAAAOLM9\ndAdERBqNBtsYAYAH73rXu878c7fbDdgTAEX3wAMPTKkcR2UTACrkK1/5ypl/npmZCdgTAFVBsgkA\nFUbCCcA1kk0AAAA4k4s5mwCA4nnggQe0Y9773veKiMhll10m+/bt047N0qZLOv368Y9/LH/3d38n\nx44dM76eLPdhOHbSvUk6ztd1fuITn5Bjx44p9U3Ve9/7XrnsssvkhhtukPPPP18rbpLRvgyue9u2\nbWPbsvkZppn0OYy7NtXviCoqmwBQMcPzNkO54YYbQnchmAsuuEA+/OEPh+6Gc1mu09X90U00TQyu\n20dbOv0JiWQTACoo9EKhPPwIh3TBBReE7oIXptfp6v74+t5dcMEFufqOh/6+MYwOAMgsy1BbqFhX\nVIemdeJUjrU99GnSh9F+6MSpxE46h+oQscoxJkPcg/Ml9SPLPVFpcxzT67CNyiYAVFTo6iaAaqCy\nCQDIzGZFSifWhtDt560f8K/snz2VTQCoMKqbAFyjsgkAOGNmZoZtLDNKq1KdPHlS7r77bk+9cacq\n14nsSDYBAJnpDu+pHu9jgYPvocl+vy+nT58O3g/Xxl0nXqxsn/0ohtEBoOLy8N7NKsnDew99qMp1\nIh2VTQBAZroLHGxVLFXO47tqpPIqmqT3HoZYJJLlc1B5bVDo9zumycurgUItEPJ1/VQ2AQBGC4VO\nnjzpqjtj2/LZZllxD9W5vFchPodQnz3JJgBARPQTzpWVFS8/XsMLTXy16UuIaynbPXTJ5QKnEJ9D\nqM9+qt/ve290VKPRCN8JAIC8613vOvPPrEoHMMkDDzwwpXIclU0AwBksFgJgG8kmACARL3kHYAPJ\nJgBgLBJOAFmRbAIAAMAZkk0AwFlG521S3QSQBckmAAAAnGEHIQDAi3zlK1856zVIVDcBmKKyCQBI\nxGuQANhAsgkAAABnSDYBAGNR3QSQFdtVAgAKa2trK3QXgMrqdrtsVwkAAICwSDYBAADgDMkmAAAA\nnCHZBAAUEvM1gWIg2QQAAIAzJJsAAABwhmQTAAAAzrA3OnLv6NGjif/+ox/9qDzyyCPe27Xtqaee\nkquvvvrM/6/X6/LZz35WXvOa18j27e7+iN5zzz1y9913i4jba+33+/KNb3xD7r33Xjl27NhZ/83X\nPX7yySdlZWVFnnjiCXnooYfk4osvdtbWCy+8IE8//bR86EMfkp///Odn/r2va/3BD34gt912mzzx\nxBMiIvLKV75S/vRP/1Te8573yOte9zo555xznLT74IMPyic+8Ymz/t3S0pL8/u//vtRqNZmaUnod\nn5Hhfdu73a6zdk6cOCGPPPKI3HffffL000+f+fd33323/OEf/qGzdp9++mm577775MiRI9Lr9c78\n+23btsnFF18sCwsL8s53vtNZ+1tbW3LLLbfIP/3TPzlrA+VGZRPIkWuuuUY+//nPy0UXXeQ00fRp\nampK3va2t8m9994rX/jCF+SlL31p6C45dc4558gb3/hGefjhh+WSSy4J3R353Oc+J3v37pWZmRln\niWaSpaUl+bM/+zOp1+tOE02ffvM3f1M+8IEPyIMPPiif/OQnvbX7+te/Xg4cOCCPPvroWUntXXfd\nJUeOHHGaaAI2kGwCOfLGN75RarVa6G44sW3bNjn//PPlDW94Q+iueDE9PZ2La921a1eQdt/61rcG\nadeHc845R1772td6b/e8886TSy+99Mz//73f+z3vfQBMkGwCObJjxw55yUteErobzmzbtk1e8YpX\nhO6GN6985StDd8FrNXPYy1/+8iDt+hLqvp533nmJ/wzkGckmAK/KMqQKAFBDsgkAAABnyrECAfCk\n2+3KF77wBfmP//gPa+dU2QXlS1/6knz1q1+V5557TuvcH/nIR2R2dta0a/Kzn/1MFhYWtOMOHTpk\n3KbIr1ePD1bK2/DTn/5UfvjDH6Ye12635dFHH9U+f5br3djYkNXVVVlfX9eKu+SSS+RjH/uYcbuP\nPfaYHDlyRE6cOKEV98EPflDe/va3G7f7mc98Rr75zW/K6dOnteLuuusu46HrZ555Ru677z555pln\ntOKuuOIK+eu//mujNgduuumms1aQq/jIRz4ijUbDuM1Tp07Jtddeaxw/6vTp09r3DhhGsgloeO65\n5+Tf/u3fpNPpeG33Rz/6kXz729+WkydPasXpJqejfvnLX8q3vvWtTOcw0ev1grT77LPPem/35z//\nuTz11FPa7Q6/VsnEf//3f8t3vvMd+c///E+tuD/+4z/O1O73v/99+da3vqWdbOoeP+ynP/2pfO97\n33vRq7fS1Ot14zYHnnzySe2EXjc5HXX69Okzr74C8oBhdAAAADhDZRPQcPnll8vq6qrVc46+1B0i\nf/RHf2T1JejDL3XPm4suukhWVlasne/06dNy6tQpa+dD8ezYscPqy+15qTuyorIJACXy3HPPyfe/\n//3Q3QCAM0g2AaBEPv/5z2eeqwsANjGMDgAl8Itf/EKeeuop+dKXvhS6KwBwFpJNoABe/epXy+/+\n7u9qV6yqtFuPDRdffLFcfvnlobuh7Ve/+pVsbm7mck7qqNe97nVy+eWXa68u37bNfCDu5S9/ufzO\n7/yO9quTXv/61xu3CeB/kGwCBfDud79b3v3ud4fuRunNz8/L/Py8lXM999xz8s1vftPKudK85CUv\nkde+9rXyl3/5l3LxxRfLRz/60UyvCnLpmmuukWuuucZrm7/9278ti4uL1s73i1/8wuq7doGyY84m\nADiwvLwsx48f997uRRddJJdccon3dqui3+/Ld7/7XWm326G7AhQGlU1AQ6gdhKom1A5CNrzwwgvy\n7//+7/Lggw8qvYLI9g5Cv/EbvyG1Wk3rXFBz4sQJ+epXvyqrq6tWXy1k6i/+4i+snu9zn/uc1fMB\nAySbgIZQOwhVTagdhEKwvYPQ1NRUpvmNGG9qaurM//KgCHN0ARGG0QHAqnPOOUdmZ2fl0UcflUsv\nvTR0d2DRq171Knnf+94nDzzwgPzt3/5t6O4AhUFlE4X1W7/1WxJFkbXz/fCHP0wdan3FK14hs7Oz\ncu6551prd2trS773ve9ZO59N27dvD7I6u16vW213MIz+k5/8xNo50+zYsUNmZ2flqaeemnjcS1/6\nUrn00ku1F/RknZf5qle9St70pjfJrl27tOIuvPDCTO2Wwfbt25Xv22WXXaa917nqnuxXXHGF1nmB\nUEg2UVi7d++2er6VlRVZXl6eeMzMzIzs27fParsq21Xec889cv/998vJkye1zr2yspLpB+m8886T\n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\n", | |
"text/plain": [ | |
"<matplotlib.figure.Figure at 0x7fd07cad04e0>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"ename": "NameError", | |
"evalue": "name 'frame' is not defined", | |
"output_type": "error", | |
"traceback": [ | |
"\u001b[0;31m-------------------------------------\u001b[0m", | |
"\u001b[0;31mNameError\u001b[0mTraceback (most recent call last)", | |
"\u001b[0;32m<ipython-input-1-b6225d508507>\u001b[0m in \u001b[0;36mon_character_submit\u001b[0;34m(w)\u001b[0m\n\u001b[1;32m 82\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 83\u001b[0m \u001b[0mw\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalue\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 84\u001b[0;31m \u001b[0mnext_character\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 85\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 86\u001b[0m character_widget = widgets.Text(\n", | |
"\u001b[0;32m<ipython-input-1-b6225d508507>\u001b[0m in \u001b[0;36mnext_character\u001b[0;34m()\u001b[0m\n\u001b[1;32m 64\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mnext_character\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 65\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 66\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mframe\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mframe\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdtype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 67\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mon_character_submit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mw\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 68\u001b[0m \u001b[0mcharacter\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mw\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;31mNameError\u001b[0m: name 'frame' is not defined" | |
] | |
} | |
], | |
"source": [ | |
"from IPython.display import display, clear_output\n", | |
"\n", | |
"import os\n", | |
"import glob\n", | |
"import numpy as np\n", | |
"import skimage.io\n", | |
"import ipywidgets as widgets\n", | |
"\n", | |
"from redis import StrictRedis\n", | |
"\n", | |
"import matplotlib.pyplot as plt\n", | |
"import matplotlib.patches as mpatches\n", | |
"\n", | |
"%matplotlib inline\n", | |
"\n", | |
"\n", | |
"redis_client = StrictRedis()\n", | |
"\n", | |
"files = os.scandir(\"datasets/ocr/characters\")\n", | |
"char_uuid = None\n", | |
"\n", | |
"frame_image = None\n", | |
"\n", | |
"def next_character():\n", | |
" clear_output(wait=True)\n", | |
" file = next(files)\n", | |
" \n", | |
" global char_uuid\n", | |
" char_uuid = file.name.split(\"_\")[1]\n", | |
" \n", | |
" frame_uuid = file.name.split(\"_\")[3]\n", | |
" char_bounding_box = file.name.split(\"_\")[4].replace(\".png\", \"\").split(\"-\")\n", | |
" char_bounding_box = [int(cbb) for cbb in char_bounding_box]\n", | |
" \n", | |
" redis_key = f\"PROJECT_EC:CHAR:{char_uuid.upper()}\"\n", | |
" if redis_client.get(redis_key) is not None:\n", | |
" return next_character()\n", | |
"\n", | |
" if file.is_file:\n", | |
" char_image = skimage.io.imread(file.path)\n", | |
" \n", | |
" plt.figure()\n", | |
" plt.imshow(char_image, cmap=\"gray\")\n", | |
" \n", | |
" frame_image = skimage.io.imread(f\"datasets/ocr/frames/frame_{frame_uuid}.png\")\n", | |
"\n", | |
" fig, ax = plt.subplots(figsize=(10, 6))\n", | |
" ax.imshow(frame_image)\n", | |
"\n", | |
" y0, x0, y1, x1 = char_bounding_box\n", | |
" rect = mpatches.Rectangle(\n", | |
" (x0 - 2, y0 - 2), (x1 + 2) - (x0 -2), (y1 + 2) - (y0 - 2),\n", | |
" fill=False, \n", | |
" edgecolor='red', \n", | |
" linewidth=2\n", | |
" )\n", | |
" \n", | |
" ax.add_patch(rect)\n", | |
" ax.set_axis_off()\n", | |
" \n", | |
" plt.tight_layout()\n", | |
" plt.show()\n", | |
" else:\n", | |
" return next_character()\n", | |
" \n", | |
" print(frame.shape, frame.dtype)\n", | |
"def on_character_submit(w):\n", | |
" character = w.value\n", | |
" \n", | |
" redis_key = f\"PROJECT_EC:CHAR:{char_uuid.upper()}\"\n", | |
" redis_count_key = f\"PROJECT_EC:CHAR_COUNTS:{character.upper()}\"\n", | |
" \n", | |
" redis_client.set(redis_key, character)\n", | |
" \n", | |
" current_count = redis_client.get(redis_count_key)\n", | |
" \n", | |
" if current_count is None:\n", | |
" redis_client.set(redis_count_key, 1)\n", | |
" else:\n", | |
" current_count = int(current_count.decode(\"utf-8\"))\n", | |
" redis_client.set(redis_count_key, current_count + 1)\n", | |
" \n", | |
" w.value = \"\"\n", | |
" next_character()\n", | |
" \n", | |
"character_widget = widgets.Text(\n", | |
" value=\"\",\n", | |
" placeholder=\"Enter the character you see...\",\n", | |
" description=\"\"\n", | |
")\n", | |
"\n", | |
"character_widget.on_submit(on_character_submit)\n", | |
"\n", | |
"display(character_widget)\n", | |
"\n", | |
"next_character()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Stats" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"584" | |
] | |
}, | |
"execution_count": 14, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"total_samples = len(redis_client.keys(\"PROJECT_EC:CHAR:*\"))\n", | |
"total_samples" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 15, | |
"metadata": { | |
"scrolled": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"ALPHABETICAL\n", | |
": 3\n", | |
"': 1\n", | |
"*: 1\n", | |
"-: 3\n", | |
"0: 5\n", | |
"1: 23\n", | |
"2: 4\n", | |
"3: 14\n", | |
"4: 17\n", | |
"4A: 1\n", | |
"5: 37\n", | |
"6: 30\n", | |
"7: 9\n", | |
"8: 38\n", | |
"9: 11\n", | |
":: 16\n", | |
"A: 27\n", | |
"B: 10\n", | |
"C: 14\n", | |
"D: 17\n", | |
"E: 34\n", | |
"F: 4\n", | |
"G: 14\n", | |
"H: 12\n", | |
"I: 28\n", | |
"J: 2\n", | |
"K: 4\n", | |
"L: 14\n", | |
"M: 10\n", | |
"N: 19\n", | |
"O: 25\n", | |
"P: 15\n", | |
"R: 36\n", | |
"S: 34\n", | |
"T: 22\n", | |
"U: 18\n", | |
"V: 2\n", | |
"W: 7\n", | |
"X: 2\n", | |
"Y: 1\n", | |
"\n", | |
"TOP\n", | |
"8: 38\n", | |
"5: 37\n", | |
"R: 36\n", | |
"E: 34\n", | |
"S: 34\n", | |
"6: 30\n", | |
"I: 28\n", | |
"A: 27\n", | |
"O: 25\n", | |
"1: 23\n", | |
"T: 22\n", | |
"N: 19\n", | |
"U: 18\n", | |
"4: 17\n", | |
"D: 17\n", | |
":: 16\n", | |
"P: 15\n", | |
"L: 14\n", | |
"3: 14\n", | |
"G: 14\n", | |
"C: 14\n", | |
"H: 12\n", | |
"9: 11\n", | |
"M: 10\n", | |
"B: 10\n", | |
"7: 9\n", | |
"W: 7\n", | |
"0: 5\n", | |
"F: 4\n", | |
"K: 4\n", | |
"2: 4\n", | |
": 3\n", | |
"-: 3\n", | |
"V: 2\n", | |
"J: 2\n", | |
"X: 2\n", | |
"*: 1\n", | |
"4A: 1\n", | |
"Y: 1\n", | |
"': 1\n" | |
] | |
} | |
], | |
"source": [ | |
"character_count_keys = redis_client.keys(\"PROJECT_EC:CHAR_COUNTS*\")\n", | |
"character_counts = list()\n", | |
"\n", | |
"for character_count_key in character_count_keys:\n", | |
" character_count_key = character_count_key.decode(\"utf-8\")\n", | |
" character = character_count_key.replace(\"PROJECT_EC:CHAR_COUNTS:\", \"\")\n", | |
" count = int(redis_client.get(character_count_key).decode(\"utf-8\"))\n", | |
" \n", | |
" character_counts.append((character, count))\n", | |
" \n", | |
"character_counts\n", | |
"\n", | |
"sorted_alpha = sorted(character_counts, key=lambda cc: cc[0])\n", | |
"sorted_top = sorted(character_counts, key=lambda cc: cc[1], reverse=True)\n", | |
"\n", | |
"print(\"ALPHABETICAL\")\n", | |
"for t in sorted_alpha:\n", | |
" print(f\"{t[0]}: {t[1]}\")\n", | |
"\n", | |
"print(\"\\nTOP\")\n", | |
"for t in sorted_top:\n", | |
" print(f\"{t[0]}: {t[1]}\")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 17, | |
"metadata": { | |
"scrolled": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"['',\n", | |
" \"'\",\n", | |
" '*',\n", | |
" '-',\n", | |
" '0',\n", | |
" '1',\n", | |
" '2',\n", | |
" '3',\n", | |
" '4',\n", | |
" '5',\n", | |
" '6',\n", | |
" '7',\n", | |
" '8',\n", | |
" '9',\n", | |
" ':',\n", | |
" 'A',\n", | |
" 'B',\n", | |
" 'C',\n", | |
" 'D',\n", | |
" 'E',\n", | |
" 'F',\n", | |
" 'G',\n", | |
" 'H',\n", | |
" 'I',\n", | |
" 'J',\n", | |
" 'K',\n", | |
" 'L',\n", | |
" 'M',\n", | |
" 'N',\n", | |
" 'O',\n", | |
" 'P',\n", | |
" 'R',\n", | |
" 'S',\n", | |
" 'T',\n", | |
" 'U',\n", | |
" 'V',\n", | |
" 'W',\n", | |
" 'X',\n", | |
" 'Y']" | |
] | |
}, | |
"execution_count": 17, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"def generate_labels():\n", | |
" character_count_keys = redis_client.keys(\"PROJECT_EC:CHAR_COUNTS*\")\n", | |
" labels = list()\n", | |
" \n", | |
" for character_count_key in character_count_keys:\n", | |
" character_count_key = character_count_key.decode(\"utf-8\")\n", | |
" character = character_count_key.replace(\"PROJECT_EC:CHAR_COUNTS:\", \"\")\n", | |
"\n", | |
" labels.append(character) if len(character) < 2 else \"\"\n", | |
" \n", | |
" return sorted(labels)\n", | |
"\n", | |
"labels = generate_labels()\n", | |
"labels" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 18, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"def generate_data_and_targets():\n", | |
" character_keys = redis_client.keys(\"PROJECT_EC:CHAR:*\")\n", | |
" \n", | |
" data = list()\n", | |
" targets = list()\n", | |
" \n", | |
" for character_key in character_keys:\n", | |
" character_key = character_key.decode(\"utf-8\")\n", | |
" character_uuid = character_key.split(\":\")[-1].lower()\n", | |
" \n", | |
" character_file_path = glob.glob(f\"datasets/ocr/characters/char_{character_uuid}*\")[0]\n", | |
" \n", | |
" character_image = skimage.io.imread(character_file_path, as_grey=True)\n", | |
" data.append(character_image.astype(np.bool).flatten())\n", | |
" \n", | |
" target = redis_client.get(character_key) \n", | |
" targets.append(target.decode(\"utf-8\"))\n", | |
" \n", | |
" return (data, targets)\n", | |
" \n", | |
"data, targets = generate_data_and_targets()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 19, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"SVC(C=100.0, cache_size=200, class_weight=None, coef0=0.0,\n", | |
" decision_function_shape=None, degree=3, gamma=0.001, kernel='rbf',\n", | |
" max_iter=-1, probability=False, random_state=None, shrinking=True,\n", | |
" tol=0.001, verbose=False)" | |
] | |
}, | |
"execution_count": 19, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"from sklearn import svm\n", | |
"classifier = svm.SVC(gamma=0.001, C=100.)\n", | |
"\n", | |
"classifier.fit(data[:], targets[:])" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 20, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"import pickle\n", | |
"\n", | |
"serialized_classifier = pickle.dumps(classifier)\n", | |
"\n", | |
"with open(\"datasets/ocr/super_hexagon_ocr.model\", \"wb\") as f:\n", | |
" f.write(serialized_classifier)" | |
] | |
} | |
], | |
"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.0" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 1 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment