{ "cells": [ { "cell_type": "markdown", "id": "cell-0", "metadata": {}, "source": [ "# Optimise and train a model\n", "\n", "![position of this step in the lifecycle](https://great-ai.schmelczer.dev/media/scope-train.svg)\n", "> The blue boxes show the steps implemented in this notebook.\n", "\n", "Run `data.ipynb` first. We read its ground truth from the shared local TinyDB database. The default uses a compact parameter search suitable for the bundled sample; `GREAT_AI_NOTEBOOK_FULL=1` enables the original larger search on the full MAG training data. \n", "\n", "In this part, we hyperparameter-optimise and train a simple Naive Bayes classifier which we then export for deployment using `great_ai.save_model`.\n", "\n", "## Load data that has been extracted in [part 1](https://great-ai.schmelczer.dev/examples/simple/data)" ] }, { "cell_type": "markdown", "id": "d3495327", "metadata": {}, "source": [ "## Local setup\n", "\n", "Use Python 3.12 or 3.13 and install this checkout with `uv pip install --editable '.[notebooks]'`.\n", "See **Run notebooks locally** in the repository README for the kernel, execution order,\n", "and full-data options. Run related notebooks from the same working directory\n", "to share the default `.cache/` model store and `tracing_database.json` database.\n" ] }, { "cell_type": "code", "execution_count": null, "id": "d8ae0655", "metadata": {}, "outputs": [], "source": [ "from docs.notebook_support import FULL_RUN" ] }, { "cell_type": "code", "execution_count": 2, "id": "cell-3", "metadata": {}, "outputs": [], "source": [ "from great_ai import query_ground_truth\n", "\n", "data = query_ground_truth([\"train\", \"local-domain-example\"])\n", "if not data:\n", " raise ValueError(\"Run data.ipynb first in the same local/full mode.\")\n", "\n", "X = [d.input for d in data for domain in d.feedback]\n", "y = [domain for d in data for domain in d.feedback]" ] }, { "cell_type": "code", "execution_count": 3, "id": "cell-4", "metadata": {}, "outputs": [ { "data": { "image/png": "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IAAAAAAAQCEJQQAAAAAAgEISggAAAAAAAIUkBAEAAAAAAApJCAIAAAAAABSSEAQAAAAAACgkIQgAAAAAAFBIQhAAAAAAAKCQhCAAAAAAAEAhCUEAAAAAAIBCEoIAAAAAAACFJAQBAAAAAAAKSQgCAAAAAAAUkhAEAAAAAAAoJCEIAAAAAABQSEIQAAAAAACgkIQgAAAAAABAIf2uEGTq1Knpgw8+SF988cVM7T9u3Lj0xhtvpO++++73/DoAAAAAAICaDUFGjRqVevbsmeadd9604YYbphVXXDG1bt06DRw4ME2bNq3C/p988knaZJNN0mKLLZa23XbbvG/v3r3TxIkTq3+kAAAAAAAA1dC4OjufffbZacyYMemJJ55IK6+8cv7ssssuSwcccEBe7XHKKaeU7jtlypS02WabpQYNGqQPP/wwtWrVKq8GWXfddfO2wYMHV+dXAwAAAAAA1NxKkB133DE98sgjpQFI2H///dM666yTLrroojL73njjjemVV15JZ555Zg5AwnLLLZf69u2bhgwZkt58883qHSkAAAAAAEBNhSA777xzatKkSYXPW7Rokb799tv0888/l3521113pTnmmCNtsMEGZfaN8lhh5MiR1fnVAAAAAAAANVcOqzJRHuv+++9Pq6yySg49SsRKj0UXXTTNOeecZfZfcsklS7dXZfLkyflVYsKECX/0MAEAAAAAgHqmWitByvvll1/SXnvtlSZNmlSmH0gYP358atasWYWfiabq0SckVo5U5fTTT8+rS0pe7dq1+yOHCQAAAAAA1EN/KASJhuixCuTYY49Nm2++eZltjRo1yiFJeVOnTk3Tpk0rs2qkvP79++cQpeQ1evToP3KYAAAAAABAPfS7y2H16dMnXXnllenwww+vsAoktG7dutKSV19++WXp9qpECa3yZbQAAAAAAABqfCVIv3790vnnn58OO+ywdO6551a6z2qrrZbGjh2bvvjiizKfv/zyy/nPLl26/J5fDQAAAAAAUDMhyIknnpjOPPPMdMghh6SBAwdWuV/Pnj3zn0OGDCnz+bXXXpv7fPTo0aO6vxoAAAAAAKBmymHF6o8BAwakjTbaKPXu3Tu9+OKLZbZ36tSptNdHrPQ49NBD0/HHH5/mmmuu/H748OFp6NCh6ZprrslBCAAAAAAAQJ0IQV555ZXUuXPnXOZqr732qrD9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lB5++OE0duzY1LFjx/SXv/wlNWwoewEAAAAAAP7EIchTTz2Vtt9++7TAAgukzp075zCkZcuWaeTIkalNmzY1+asBAAAAAIB6rsaWZEyYMCFtvfXWaZVVVkkvvvhi+s9//pNee+219OOPP6add965pn4tAAAAAABAzYYggwcPziWwjj/++NSoUaP8WfPmzdNRRx2VHnvssfTkk0/W1K8GAAAAAACouRDkgQceSHPNNVdabbXVyny+3nrr5T/vu+8+ww8AAAAAAPz5eoK89957adFFF63QBL19+/al26syefLk/Coxfvz40hJblDV18o+GhDrnz3CuOneoi/4M505w/lDXOHeg2OeP7x3qIucOOHfA907d+T6eNm3aDPdrMO239vidllhiiTTPPPOkl19+ucK2CEa22267dPPNN1f6syeeeGIaMGBATRwWAAAAAABQEKNHj05t27ad/StBmjZtmn7++ecKn0+ZMiUnM1Eqqyr9+/dPRxxxROn7qVOnpq+//jotuOCCqUGDBjV1yNTz1LBdu3b5hIneNYBzB3z3QN3kug2cO+B7B+o+12zMDpEzfPfdd6lNmzYz3K/GQpBIXkaNGlXh888++6x0e1XmnHPO/JrefPPNVwNHCWVFACIEgepz7sDv5/wB5w7MTr53wLkDvncokhYtWtReY/S//OUvuZfHO++8U+bzkmBk7bXXrqlfDQAAAAAAUHMhyJ577pmaNGmSLrzwwjLLUy666KLUoUOHtPHGGxt+AAAAAACgxtRYOawIOiLw+Pvf/55rwHXp0iWNGDEiPf/88+muu+7KAQnUFVF+7YQTTqhQhg1w7oDvHqhbXLeBcwd870Dd55qNuqTBtFieUYNee+21dNNNN6WxY8emjh07pl69ev1moxIAAAAAAIA6H4IAAAAAAAAUqicIAAAAAABAbRKCAAAAAAAAhSQEgXJUiIOqjRkzJt13333OE5iFfO+Acwdq0rhx49JVV12Vjj322PToo4/mzz799NP0+eefG3ioxOuvv55GjRplbKCavv322zR8+PA0ZcoUY0edIwSh3rrjjjvSU089Vfr+hhtuSC1btkwtWrRIl156aa0eG9TlEGSjjTZKiy++eDrppJPSxx9/XNuHBH8aX331VTrnnHPKPJRab7310hxzzJG6d++exo8fX6vHB3U5KDz11FPTDz/8kN9PnTo17bXXXqlp06Zp2WWXzQ+rgMrdeuutqWPHjmnfffdNp512Wnruuefy5++++27q2bOnYYNKvPzyy6lr165phRVWSOeee2768ssvjRPMZAiy1VZbpfbt26f+/fund955x7hRZwhBqLf/MB955JH5xjl89913ab/99sv/UPfo0SMdeuih6ZNPPqntw4Q6Z9VVV01DhgxJiyyySDrhhBPyTfWmm26abrrppvTTTz/V9uFBnXbKKafkwKNEPNR95pln8sPcuEE488wza/X4oK668cYb02uvvZbmmWee/D6+c6699tq0zTbbpGbNmqWDDz64tg8R6qTRo0fnoCMCkJi4Evc4Jf7617+msWPHprfeeqtWjxHqongmcPHFF6eGDRvm5waLLrpo2mGHHdLdd9+dg3igcvFM7ZZbbknLL798vrdZeuml86SvwYMHpx9//NGwUauEINRLjz/+eOrUqVOab7758vv7778/TZo0Kd17773puuuuS9tuu2268847a/swoc5p0qRJ2m233dITTzyRXnzxxXxT/dhjj6WddtoptWnTJh1++OHp1Vdfre3DhDppxIgR+aa6xG233ZaOOeaYdOWVV6brr78+3zAAM3fubLHFFnkV7wMPPJDDxK+//trQQTk333xz2mSTTdJ5552X2rVrlx/oTi9muU+/Mh74nwjd//73v+cVIY888kgOQKLEz+abb54WW2yx9M9//jN98MEHhgvKie+Z7bbbLpfQfvPNN1OfPn3SK6+8kvbcc888kfKAAw7I121QG4Qg1NtZUfHAtkRc2MRy1wUXXDC/X2WVVXLZH6BqnTt3TpdddlmuKT1o0KDUunXrNHDgwLTiiiumNddcM/373/9OP//8syGESr57YkbuRx99lB/k+t6B6l+3lZw7sRJkiSWWsIIXKhHXaGussUbp+wYNGlR40GtmLszYuuuum4YOHZq/i6KkXKNGjfLq3vju6datWw4b9XeDimIVSITwUWUl+lIttdRS+flBfC+ttNJK6cILL/QdxGwlBKFeWmihhUrrR8cFy8iRI9M666xTpk77AgssUItHCH8eEydOzL0MoqxciNlRcX7ts88++eImHvQCZb97YjZh8+bNc2gYfO/AzJ070c/gs88+c90GMyH6HcZM3KrEqt62bdsaS5gJ0Zcq7nlK+lMtueSSucLEjjvumNZee+1cchuoKKquxLkzYcKE/D4mtkQwcsghh+QS9bFSBGYHIQj10vrrr5+effbZXId91113TW+//XauK10itsVMdqBqMRN3l112yeUVjj/++Bx4RKAYS8OjxnTUcP/ll19yA3Ug5RIKvXr1yiWwoqfOlltumRo3bux7B2bi3DnuuONyg80opxCzb0sCxAhEYnZ71GsHytpss81yucUoKVd+Jcill16a+1FFbxCgctH/I86fWH0YoUc0Se/evXt69NFH8zOEL774Iq9+f//99/PKeCCVea7Wu3fvfI12xBFH5NA9+rrFJMm4fotzK6qx9OvXz7AxW/zvzhvqmVjlEY2Zon9BzNiIh1Grr7563hYpdKTU068MAX5d9REX+pdcckluUhszDOM8ipq5HTp0KB2mueaaK8+KijIlsVwc+F9j9N133z0vC49ycmeccUbpsMSNc9SXBiqKXlRPP/10uuiii/L3TjRFLxGlFA466CDDBpWICSr77bdf7qkT5UdiBnuLFi1yP53oBRLnT7wHyvrmm29y2Z54ffjhh/nh7YABA9Lf/va3XAK4RJw/e++9d5o8eXLukwj13ZQpU9KQIUPSxRdfnEOQWPkeFSIOPPDAtNxyy5XZN8LFCEii5w7MDg2mKV4IFZbqxez1qJELlBU3zGuttVa+kY4LmZ133jk1bdq0ymF6991388Oqk08+2VDCDHz11VelfamAmRcTV+KarWRVFVBW3O5H0B4hYsxcD8svv3w69thjU8+ePQ0XVCJWUMX5seGGG+agfauttsq9QKry5JNP5mbPhx56qPGkXovQsGPHjnnFbkyUjAlg8847b5X7f/nll7lyhJVUzA5CEKjkRqF800Dgf2LZajTZ7NKliyGBavrpp5/Sww8/nDbaaKMK2+6999603nrrpSZNmhhXqMSDDz6YS5XOPffcZT6PWYbt27fPfUOA3/4eCr5rYMaiVFyUwlpmmWUMFVRzcspLL72k1CJ1kp4g1Ft33HFHntVeIpaFR4mFWNIaNXKBihZZZBEBCPxO559/fg47KhOfR1kSoKIoMXLiiSdWCEDCxx9/nA4++GDDBjMhwg8BCPy2pZZaSgACv0M8T9NrirrKShDqpegDstpqq+XZg/PNN1/67rvvcp3PaLQZdQqjWVM0d9ZkE8qaMGFCev7556scllhFFf1AFltssTL1coH/lR+57bbbKr2pfvPNN3M93FdffdVQQTnRVDNWSkVT9Kp6vUWTzehDBVR+/RbfM7GaN+q1T2/llVfODZ+ByldPvf7662n06NG578f02rVrl1coAmXLy08/2biy5wVRTjuev3nexuymeC710uOPP546deqUA5Bw//3353+sYyZu1GSPm4M777wz1zAEfhU3ARtssMFMDUmUzLrgggvSX/7yF0MIKaX33nuvyov9+Dy2AxXFuTGj3gWxSvH9999PnTt3NnxQzplnnplOPfXUPOmrMuedd17q06ePcYNKKkcccsghOQCpTPRGjN4hwK8+//zzmX5eEBOQzz333LTpppsaQmYLIQj1UlzItGnTpvT9I488krp27VralHaVVVZJY8aMqcUjhLopLlRiJnvcUK+00ko54GjevHkuRzJs2LC07rrr5hlRsZLqqquuyr0PXnjhhbT00kvX9qFDrWvVqlV68cUX0zrrrFNhW9TOjdnsQNXnTvfu3Sts+/7773NI4vyBimKCV79+/dK+++6bGzvHKt2GDctWxI6eOkBZY8eOTbvuumu+Zjv77LPzqo/ypeR870BF8T0zYsSIdM455+RJXhGIxLkSKxFvvPHG/FwgQo9YwTtkyJDUo0eP9Oijj+bncVDThCDUS9E8M2a0lzRCHzlyZC5DUmLcuHF5ViFQscZnzHg65ZRTUrdu3cpsi5lScR7FTXb8efjhh+d6oBdffHEaOHCgoaTe22yzzdJhhx2W7r777jJNnONG+9BDDzULCmZw7vTt2zdtvPHGOYAvEat4DzjggFzONB5QAWU9+OCDabfddktXXHGFoYFqiHI+ERDGNVujRo2MHcykKI19zz33pH322Sf16tWrzLYDDzwwh/IhnhXEKsStt946PyuwqorZQWN06qX1118/9wPZa6+98gyPt99+O22zzTal22Ob+p5Q0SeffJLPj/IBSIiZhXvvvXcaNGhQft+4ceN00EEHpVdeecVQQkrp+OOPzysRo/b6tttum5s5x5/xADdWH0bjZ6Ci3XffPTepXXXVVXMQEjfRcf0W59INN9yQzj//fMMGlZh33nn1+4Dfee507NhRAALVFBNU/vOf/+TrtMrsv//+pRMkoz9ITBDzvIDZRQhCvRTL8QYPHpweeOCBdNddd6UTTjghrb766nlb/AM8fvz4SsuVQH335Zdfph9++KHK7VGWJPaZvoRJzAYB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+GN+xYSV8jwvoDYph0W98Nprr+UeBlETN5pmlryfkZJ9gV/Fg9tFFlkk7b777umMM85IjRv/mqV//PHHeUb7vvvum4455hjDBuVcdNFFuQ5unCPbb799WnjhhdMXX3yRbrnlltw/5IILLkh///vfjRuU8/TTT+e+BZtvvnluQhsPo7799ttciuScc85JW221VQ5JoL6L75jfaoRensboUNGNN96Yz6coAbz44osbIqiGeJYWJeQuu+yy3Ax9+gBk4403Tuuuu26+74HZTQgCQLVcffXVqXfv3qlDhw5p7bXXTi1atMjlfe699948k/C5557LzdKBijcEUUrhkEMOqTA0cSNw5ZVXppdfftmwQTkRHMaMwqFDh1YYm6eeeiqXJInyclHKFOqzN998M3344YdlPnvrrbdyr7add945LbfccmnKlCnppZdeSsOHD8+rEzfccEMlGaGcaHweE77+7//+z9hANY0cOTJPUGndunVab731co+QTz75JK+mipW78bzACkRqgxAEyqmqzA/wq9tuuy3fGMQFTDQ/m3/++dPWW2+dP4uLHaCimAn12WefVdpvKvpURdmFSZMmGTooJ26gjz766LwSpDJLL710nrWrPwiUFd8522yzTbr77rsrfPe89957qVevXnlF1fQzdYGUfvrpp7T66qvnECRW7gLVc//996cBAwbkCiwRvjdr1ixtttlm+XlBrOiF2tCwVn4r1AF33HFHnj1Y4oYbbsgNamNW+6WXXlqrxwZ13bbbbptGjRqVJk+enOuzxwPcWCEiAIEZ18iNZeCVUR8Xft+5E5NXoleVflRQUaye6t69e6Xh+xJLLJHL/MSMXaCiCy+8MO2zzz5p8ODB6fXXX8/fQ7HqsOT13XffGTaoQrdu3dIjjzySnxd8//33acKECfmZmwCE2iQEoV6KOtJHHnlkWnbZZfP7uIDZb7/9Uvv27VOPHj3SoYcempfrATMWDZ3nnntuwwQzYZ111smlsOImYHrxHXTYYYfl+rhA5efOiSeeWKHMT6xE7NevX5pjjjnSUkstZeignHhoG5NVqhIPpqoKGKE+u/XWW3OpxbvuuivtueeeqVOnTmmhhRZKrVq1Kn1Fjypgxho2bFhpg3SoDb92tIV65PHHH88XMiV9C2KpXpQgiZ4GUa8wluvdeeedGtRS78XMjSilEGUSoiF6yfsZKdkXKOukk07KfXQWW2yxPDO3pDH6fffdl8+t+G4CKjrooIPSVVddlctebbTRRrknVYSJcc588MEHuSl63GQDZUWJuOhFFQ9xV1lllTLb4uFulMk67rjjDBuUE+fL2WefPcNxKZlQCcy4T1UE7tOLUCRKY8HsJgShXho9enSuvV4ilul17do1ByAlFz1jxoypxSOEuuGFF15Ia621VlpzzTVz+biS9zNSsi9Q1qqrrpof2sYDpxEjRuTwvWnTprkp7amnnqqfAVQh+k498cQTqX///rmcaTy8jZWIXbp0SQMHDszNN4GKdthhh1zSZ7XVVsvhezy0jRVU0Rj9scceSz179kxrrLGGoYNylllmmfwCqu+VV15Je++9d+4fWpmYEFZ+dS/MDkIQ6qVYyhp1PUtqSUct3LhJKBE1Ps1kh//Vi77iiivyOTP9+986v4Cqg5B4gBvfPT/++GMuJ9egQQPDBb8hrsuuueaa/Pc4d2LVYQQhQNUaN26c7rnnnnTKKaekIUOG5L+HKB8Xs9wPP/xwwwfALLXrrrvme514bhCreMuXz45rOKgNDabF/zOhnokmzu3atUs77rhjnokbDZqefvrptPrqq+ft66+/fr5ZiBrUAAAAf3Zx3xOl45o0aVLbhwJ12tixY0snTVYmJrBESZ+YIBarFYFfz52YuBIltE2OpK6xEoR6aYEFFkiDBw/Os5+iSfoJJ5xQGoDE0r3x48cLQKAK0cMgSspFaYXpxczcUaNGpQ022MDYQRW++uqrdMEFF+ReVPH3li1b5nJY0Rg9vpuAGX//vP322/kGu/w8rjiPnENQuVjlHqXk3n///bTpppumddddN3366ac5EIn+VEBZDzzwQJ7NPjPi3ueiiy5Kyy23nGGk3otVH9F7VwBCXWQlCFQyQypq5cbMDqCi7bffPvXq1Sttt912FbbFKqrobRDNn4Gy3nvvvbTeeuvlmVGxNLx169b5oe5bb72VFl100dyfqmPHjoYNKrk2i+bo0QA9rtEq8+STT+b+bkBZt956a26MXtKY9rzzzkt9+vTJ3zknnnhiftgLlPX555+nBx98MJeNi5AjeobONddc+Vpu6NChaaeddkqLL754euedd9Lll1+efvrpp/TGG28I4yGltPPOO6dDDjnExGLqHCEIADMtVknFQ9ooKVeZqNcejTavvPJKowrlRPPmWEU1bNiw3Jy2RNw077LLLvncuv32240blHPyySenM888Mx155JHpL3/5S1pwwQUrjFHMwDWBBcqK75zo//H3v/89HXHEEelf//pX/q6JECSssMIK6ZZbbtEAGsqJ1YbdunXLq3fjPCkfzG+22Wbpsssuy5NaJkyYkEOSeOhbcm5BfTF16tQKzwYidO/fv39edRiTJMuvComebsrIURuUw6JeiuXfsRx8RmJWrhm5UFacN23atJnheRMzpICKYrbto48+WiYAKXl4e/XVV6e//vWvhg0qEbNxIwSJ1SDAzLv55pvTJptskld/hCh/Nb14uPvUU08JQaCS1YXR96N8ABKaNm2aV8THpK+zzjorNW/ePPXu3TuX1Yb65uOPP67yudn1119f6eeLLbZY+vDDD2v4yKAiIQj10o033pj7gcxI1GcfOHDgbDsm+DNo1apVevfdd/PsjnnnnbfC9pdeeskycKjCnHPOmUsnVCYaa8ZNNVBRfN8sueSShgZ+x8SvNdZYo/R9PNSdXqyeip5uQFnRe+qHH36ocljiXujLL78sc48U5U6hvol+bFE2rjpatGhRY8cDMyIEoV7aeuutK9xMT5w4Mb355pvphhtuyDMNo247UFbbtm1zWYUDDjggz36a/qHtyy+/nE477bQ8WxeovD7u8OHD02677VZhWzSs7dmzp2GDSuy111753IkZ7cDMa9myZXr11Ver3P7iiy+mbbbZxpBCOSuttFJ65plncgnT8g3SY9V7lMk6+uijSz97/vnn0+qrr24cqXdiJdRRRx1V24cBM0VPECgn6hluu+22+YHUfPPNZ3ygnPvuuy/XwY2mzlHnM+p5xuqQKPXTpUuXXO6nSZMmxg3K+eSTT9I//vGPXD+6R48epY3R77zzzvT222/nWVSxWqT8Ayyo76If1aBBg/LM3AgR27dvnxo3LjuXK67Zyn8G9V1MUIlrs9tuuy1tueWWua9Ou3btct+CSy+9NH8nRd8Qs3Kh8soQEXasueaaZRqj33333XlS2NNPP51XU8V30xZbbJFLN1a2Uh7qm2+//Ta99tprae211y7z+S+//JLuvffetOmmm9basVG/CUGgEv369cu9DaK5GVBRBB3HHXdceuKJJ9KUKVPyEvCYJXXKKaekZs2aGTKo7KKrXBmSmW3MCfVd165d06hRo36zfnvsB5QVK9wvvvjiXBYryvtE4BGNbKMXyIUXXqjXDszgGizCwjhP3njjjfw+GjzvtNNO6aSTTtLYGWbwvdOpU6d04IEHVtgW588uu+yS++rA7CYEgUocccQReSb7GWecYXxgBuImetKkSWnuuec2TvAb/vWvf1V7jCwvh5SGDh2aexvMSK9evdIiiyxiuKCceHAbK6kuuuiivOowLL/88unYY49VhhFm0s8//5xf7nngt58PRKWI6JFT2fny3//+NweLI0aMMJTMdkIQKLds7/bbb8+J9RVXXJFvqIGq60jHzNyYVRilFbp3725GFABAHfXTTz/lP5UthZkXK9/jvifOn44dO6aNNtpIGAJViPBjxRVXTOPGjat0+yuvvJJXg8TqKpjdFM6lXorkufzs2kisY3ZHiJq50cAWqGjChAm59NVdd91V5vOogXvJJZdU2vQZAP6ob775Jvelih4GUYc96rSvvPLKBhZmkvADZl6sQIySPeXLMUYZ4Ouuuy6HIUBZsQokermNGTMmtW3btsLwvPTSS2mBBRYwbNQKK0Golx5++OHcIHB6jRo1Sm3atMk31Ouss06tHRvUdbvvvnsaOXJkOvzww9P666+fm9F+8MEHefVUNAqMGtOrrbZabR8mAAVy7bXX5hrTsfpwejFxZdiwYZrRwm+IhrRffvll7uU2vbiO08wZKlp33XXT+++/n/7xj3/knjpR2idKyp1//vl5Zcibb75Z6UNeqO8iIJxjjjnS9ddfn5o3b176eZxP8fzgb3/7W/rnP/9Zq8dI/SQEAWCmxayOli1bpsceeywHhuX17Nkz30hffvnlRhWAWeLpp59Oa621Vtp8883zjXOUI4kSpjGp5ZxzzklbbbVVDkmAVGn99RNOOCE999xzOQgp77zzzkt9+vQxdDCdV199NX/vxKz1xRdfvMzYRJC44YYbpk033TQdc8wxxg3KeeGFF/LE4li1G6FHrJ766KOP0r333ps6dOiQnnnmmTLhCMwuQhAAqnVBE6XiShprlhclss4666z00EMPGVUAZol99903/fjjj7lBenmx+vCvf/1rrj3thhrKigdNXbt2Tauuump+YBsPoho2bFhhtnvnzp0NHUwnqkZEmd977rmn0nG5+OKLc0B/zTXXGDeo4rlB//7904MPPpj76cSqw+233z6dccYZeVIl1AY9QajXYgZhzFiPmR7RE2SppZZKe+21V55RCFQ011xzpa+++ipNmzYtNWjQoML2KLMQ+wDArPLOO++ko48+utJt8YA3ZhVGiQX9QaCsO+64I4cfI0aMqPS6Dahc3M/EfU1V3PPAjK2yyip5JWI8N5g4cWIuJwe1rew0EKhHIoGOpXkxc71p06Z59mCU+Nl6663TwQcfXNuHB3XS0ksvnRo3bpz69u1boab0xx9/nAYMGJBnFALA7HgYFTfXEc4L4KHycyfKlwpAoHpWX3319Prrr+f+H/E9M72XX345XXDBBe55oBJRrnT48OGlzwri+0cAQl2hHBb1dkbhsssum44//vg8szBCkBD/UEdz5whB7r///hySAGVdffXVqXfv3nnm7dprr51atGhRWuMzmgNGzelY7goAs8Ipp5ySrrrqqlxSIb57SkR/g6jHHv1APv300wplfqC+i8bN+++/f3rggQdSo0aNavtw4E8leumcdNJJafnll8+hSISK8RwhvotWW2219Pjjj+fJYcCvPvzww9y7bZFFFkl77rlnfm4QFVegLhCCUC9deeWVaciQIbkcVmX22GOP1L59+3zTDVReJzdWU5U02Zx//vnzKqr4rHXr1oYMgFnmm2++yT0NPvnkk7TRRhvlIGTChAn5AdQHH3yQQ5C4dgMquv3229ONN96YS/7Gg6jyq6ZiNbxZulC5mCAZq0FiVUisCIn7nF133TWHI82aNTNsUE6UmY/vneibEwF8nDfRu22fffZJO+ywg+8bapUQhHopApD4BzlmtFcmSvrEbKnjjjtuth8b/JlEADJ58mQXMwDUqM8++yw32IweB1FqIa7TunTpko499li93GAGRo0alQ499NDcxLky5513XurTp48xhBn4+eefc9UIpRdh5r399tvpkksuyZNVYkJLhO4RIkYgEqurYHYTglAvRV3pmEkYPUDmnXfeMtvi4maDDTbIsz6iZBYwc6pqlg4As9KPP/6Y5pxzTuV9YCbKYUVz2ijns/HGG6dWrVpVKBu33nrr5X2AiiZNmpT7G7z66qu5N2KvXr3S+PHj8/OEJZdc0pDBTIjG6MOGDcurQ6KSRFhxxRXTfvvtl8tlWY3I7KKAIfXm4uX7778vfR8PaqPUVc+ePfPS8JVWWinfSMeNQoQf++67b2rXrl2tHjPUVS+88EKuh7vTTjuVvt95551z/c84dy666CJhCACzVNRgjwbPcaM8/c3ys88+m0uYLrTQQkYcyrnhhhtyj8O77rrLtRlU0yuvvJJ69OiRex+GuN+JECTK/XTv3j298cYbVobATD6Pi/AwSpmGNm3a5BKnhxxySDrrrLPSyJEjcygCNU33QOqFSy+9NM98mv4VFzQxq2P77bfP9XEXX3zxtPnmm+deBxGMRHkFoKIDDzywTGPaeB+zcqPxWZSai/MKAGaVWLl74oknVjpT8OOPP04HH3ywwYZKxCSvtdZaSwACv6Pkbzwn6NSpU3r55ZfTf/7zn9Jt0QuxW7du6aabbjKuMAMxUSVWeiy66KLpiCOOSG3bts3nTQSLUeZ0xIgRacEFF0z9+vUzjswWVoJQL0QjprPPPrtaPxN1poGyvv7669yEdo011sjvP//88/TUU0+le++9N8+IinILt9xyi/rsAMwy//73v/NNdGW22267vArxu+++06QWyokmtAcddFCeuV6+DBZQteihE7PXb7311lx+MRqjTy9mrT/55JNpjz32MIxQrrx8TIyM0lcRgkQfkOgBEhMnl1tuuTJjtcUWW+SAJL6rYHYQglAvrLrqqvkF/DEx43aRRRYpff/II4/kmblRaiFETemY0QEAs8p7772XS5hWJb6X3n///dS5c2eDDtOJ8r5777132n333fNDqFj9Xr6xc/RHbNq0qXGD6Xz66af5OyUCkFC+7+E888yTV8IDZY0ZMyZPXImgMIKQ+P4p34d3ehGCbLbZZoaR2UIIAsBMi5rr8aBp8uTJ+aYgSl917do1NW78v6+TcePGpQUWWMCIAjDLRBnTF198Ma84LC96vkVI4rsHKoryvueff37++9ChQysdovPOOy/16dPH8MF0WrZsmd566600bdq0SsvJRU/EKO0DlBXl4h5++OFcjWVmr/EGDRpkGJkthCAAzLRoYlbSPydmd1x//fXp3HPPLd0eS16jcS0AzCoxQ7Bv375p4403TiuttFLp51Gq5IADDkhLLLFEnvEOlLX11lv/5oPamX1QBfVJ3M989dVX6eSTT07//Oc/ywQhUQr46quvTg888ECtHiPURS1atKjye6WqUBFmlwbT4v+FADCTojlg1L+N2VFbbrlluu6661KTJk3SxIkT07LLLptnRpmRC8Cs8tNPP6V11103Pffcc2nDDTdMSy65ZPrmm2/So48+mr744ot09913V7pKBAB+r8GDB6e99torf+e0bt06f99E6H7fffelXXbZJfc9ACp69913c9nskn5u8T76frz66qtpxx13zOfWHHPMYeiY7YQgAMyyJmg//PBDnv0BALNSND4/7rjj0rBhw9KXX36ZyzCuvfba6ZRTTknrrLOOwQZglhs5cmReDfLMM8+kqVOn5lXx+++/fy4116hRIyMOldh2221zP6qtttqq9H1MXNluu+3Srbfemk477bS03377GTtmOyEIAADwpxHNaKORc8OGDWv7UACoB3755Ze8KnGuueaq7UOBOi3CwpgUGeXkolpElC6NPiFXXHFF2m233fJklmuuuSb93//9X20fKvWQOwcAAKDOe+edd9IFF1yQTjrppDRmzJj82dtvv51XiQBATYlVHwIQ+G1jx45N8847bw5AwtNPP50mT56ce4qGVVZZpfQaDmY3jdEBAIA67cQTT8wlSWKGYdhmm21S+/bt0+23356+/fbbXFoBAGbVg9zXX3+9yu3R3HmeeebJPUJiljvwPy1btkxff/11GjduXP778OHD03LLLVfaMzQ+1z+U2iIEAQAA6qw777wznXnmmWnQoEFpp512SltuuWXptqjNvvTSS+feIMpjATArPPDAA2nXXXedqX032GCDdNFFF+UHvVDfRc+2OCfiWu2vf/1rPjcOP/zw0u3PPvtsWnPNNWv1GKm/9AQBAADqrJ133jmtvPLKqX///vn9Wmutlc4777zUtWvX/L5Dhw65tvQyyyxTy0cKQBF8/vnn6cEHH0xnn312fqAbJXyiHNZ7772Xhg4dmgP5xRdfPJdpvPzyy3O/kDfeeMMMd0gpvf/++7n/xwsvvJCDkJtuuik1b948r+Zdfvnl08iRI/MqKpjdrAQBAADqrE8//TTtt99+ZcqQTC9KkkSzdACYFVq3bp0bOQ8ePDitsMIKZbYdeuihabPNNkuXXXZZ2mWXXdJhhx2WQ5LYt0+fPv4HoN6LgPCJJ56odByefPJJJeSoNRqjAwAAdVbUlH7zzTcr3TZhwoQ843DRRRed7ccFQDHFg9oI3MsHIKFp06Zpu+22S1deeWV+HzPce/funV555ZVaOFL484iypXroUJuEIAAAQJ0VM25PPfXUXGpk+pUgU6ZMSUceeWRaaaWV0kILLVTLRwlAkRqj//DDD1Vu//7779OXX35Z+r5Vq1a5XBbwP6NHj87XaFG6NEpgbbjhhulf//pXmjhxoiGi1ghBAACAOmuvvfZKiy22WO4LstFGG+Wa7BGKdOrUKQ0ZMiT3BwGAWSXC9WeeeSYNGzaswrb4DrrgggtS586dSz97/vnnc0ksIKWnn346r6IaNGhQDhNjosrHH3+c+vbtm5uif/3114aJWqExOgAAUKfFTfTxxx+frrvuuvTFF1+kRo0apbXXXjudccYZuVE6AMxK0esjwo54aDt9Y/S77747LbXUUvlBb/SkilUjW2yxRW6kPu+88/ofgXovQsToq3P11Ventm3blo7HqFGj0vbbb5922GGHNHDgwHo/Tsx+QhAAAOBPI0opNGnSJAchAFATpk2bli699NJ04YUX5nKM8T5mtO+0007ppJNO0tsAKjFu3LgcgEQ4uOCCC1bYfuutt+ZJLa+++qrxY7YTggAAAABAJX7++ef8mnvuuY0PzMCECRNShw4dqix59dJLL6V99tknPfvss8aR2U5PEAAAAACoxBxzzCEAgZnQvHnz3Az9scceq3T7HXfckXr27GksqRVWggAAAAAA8LtNnTo1vfvuu+noo49O6623Xtpwww1zWaxPPvkkXX/99WnSpElpwIABqUGDBqU/E+VN559/fqNOjROCAAAAAADwu3344YepY8eO1fqZxRZbLP8c1LTGNf4bAAAAAAAorAUWWCCdffbZ1fqZFi1a1NjxwPSsBAEAAAAAAApJY3QAAAAAAKCQhCAAAAAAAEAhCUEAAAAAAIBCEoIAAAAAAACFJAQBAAAAAAAKSQgCAAAAAAAUkhAEAAAAAAAoJCEIAAAAAABQSEIQAAAAAACgkIQgAAAAAABAKqL/B8IeNbfHYoL7AAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from collections import Counter\n", "import matplotlib.pyplot as plt\n", "\n", "domains, counts = zip(*Counter(y).most_common())\n", "\n", "# Configure matplotlib to have nice, high-resolution charts\n", "%matplotlib inline\n", "plt.rcParams[\"figure.figsize\"] = (20, 5)\n", "plt.rcParams[\"figure.facecolor\"] = \"white\"\n", "plt.rcParams[\"font.size\"] = 12\n", "\n", "plt.xticks(rotation=90)\n", "plt.bar(domains, counts)\n", "None" ] }, { "cell_type": "markdown", "id": "cell-5", "metadata": {}, "source": [ "## Optimise and train Multinomial Naive Bayes classifier\n", "\n", "Each paper may have several accepted labels. We expand it into one training row per label for this single-label classifier, but keep all rows with the same paper text in one cross-validation fold using `GroupKFold`. The final train/test split was already made by paper in Part 1, before expansion.\n", "\n", "The search uses macro F1 on the expanded single-label validation rows as a training surrogate. This differs from the top-1 hit rate and fixed-target multilabel metrics used to evaluate the deployed label sets in [Part 3](https://great-ai.schmelczer.dev/examples/simple/deploy). Rerun the search to obtain results for these grouped folds; the previous ungrouped outputs have been removed." ] }, { "cell_type": "code", "execution_count": 4, "id": "cell-6", "metadata": {}, "outputs": [], "source": [ "from sklearn.naive_bayes import MultinomialNB\n", "from sklearn.pipeline import Pipeline\n", "from sklearn.feature_extraction.text import TfidfVectorizer\n", "\n", "\n", "def create_pipeline() -> Pipeline:\n", " return Pipeline(\n", " steps=[\n", " (\"vectorizer\", TfidfVectorizer(sublinear_tf=True)),\n", " (\"classifier\", MultinomialNB()),\n", " ]\n", " )" ] }, { "cell_type": "code", "execution_count": 5, "id": "cell-7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Fitting 3 folds for each of 8 candidates, totalling 24 fits\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
mean_fit_timestd_fit_timemean_score_timestd_score_timeparam_classifier__alphaparam_classifier__fit_priorparam_vectorizer__max_dfparam_vectorizer__min_dfparamssplit0_test_scoresplit1_test_scoresplit2_test_scoremean_test_scorestd_test_scorerank_test_score
20.0024680.0003980.0014310.0001710.5False0.91{'classifier__alpha': 0.5, 'classifier__fit_pr...0.4554310.4345710.4235470.4378500.0132211
60.0020880.0001660.0011130.0000531.0False0.91{'classifier__alpha': 1, 'classifier__fit_prio...0.4581540.4159510.4060970.4267340.0225782
00.0105470.0054230.0014380.0002070.5True0.91{'classifier__alpha': 0.5, 'classifier__fit_pr...0.4227900.3897840.3523300.3883010.0287843
40.0026620.0004260.0011620.0000681.0True0.91{'classifier__alpha': 1, 'classifier__fit_prio...0.3816070.3825870.2850050.3497330.0457724
30.0016640.0000160.0013540.0000810.5False0.93{'classifier__alpha': 0.5, 'classifier__fit_pr...0.3482600.3585950.3294160.3454240.0120805
70.0021250.0002280.0013680.0002471.0False0.93{'classifier__alpha': 1, 'classifier__fit_prio...0.3447940.3327970.3235810.3337240.0086856
10.0019970.0001040.0011050.0000510.5True0.93{'classifier__alpha': 0.5, 'classifier__fit_pr...0.3492480.3280470.2778550.3183830.0299377
50.0021350.0002510.0014220.0004791.0True0.93{'classifier__alpha': 1, 'classifier__fit_prio...0.3373620.3067760.2920580.3120650.0188708
\n", "
" ], "text/plain": [ " mean_fit_time std_fit_time mean_score_time std_score_time \\\n", "2 0.002468 0.000398 0.001431 0.000171 \n", "6 0.002088 0.000166 0.001113 0.000053 \n", "0 0.010547 0.005423 0.001438 0.000207 \n", "4 0.002662 0.000426 0.001162 0.000068 \n", "3 0.001664 0.000016 0.001354 0.000081 \n", "7 0.002125 0.000228 0.001368 0.000247 \n", "1 0.001997 0.000104 0.001105 0.000051 \n", "5 0.002135 0.000251 0.001422 0.000479 \n", "\n", " param_classifier__alpha param_classifier__fit_prior \\\n", "2 0.5 False \n", "6 1.0 False \n", "0 0.5 True \n", "4 1.0 True \n", "3 0.5 False \n", "7 1.0 False \n", "1 0.5 True \n", "5 1.0 True \n", "\n", " param_vectorizer__max_df param_vectorizer__min_df \\\n", "2 0.9 1 \n", "6 0.9 1 \n", "0 0.9 1 \n", "4 0.9 1 \n", "3 0.9 3 \n", "7 0.9 3 \n", "1 0.9 3 \n", "5 0.9 3 \n", "\n", " params split0_test_score \\\n", "2 {'classifier__alpha': 0.5, 'classifier__fit_pr... 0.455431 \n", "6 {'classifier__alpha': 1, 'classifier__fit_prio... 0.458154 \n", "0 {'classifier__alpha': 0.5, 'classifier__fit_pr... 0.422790 \n", "4 {'classifier__alpha': 1, 'classifier__fit_prio... 0.381607 \n", "3 {'classifier__alpha': 0.5, 'classifier__fit_pr... 0.348260 \n", "7 {'classifier__alpha': 1, 'classifier__fit_prio... 0.344794 \n", "1 {'classifier__alpha': 0.5, 'classifier__fit_pr... 0.349248 \n", "5 {'classifier__alpha': 1, 'classifier__fit_prio... 0.337362 \n", "\n", " split1_test_score split2_test_score mean_test_score std_test_score \\\n", "2 0.434571 0.423547 0.437850 0.013221 \n", "6 0.415951 0.406097 0.426734 0.022578 \n", "0 0.389784 0.352330 0.388301 0.028784 \n", "4 0.382587 0.285005 0.349733 0.045772 \n", "3 0.358595 0.329416 0.345424 0.012080 \n", "7 0.332797 0.323581 0.333724 0.008685 \n", "1 0.328047 0.277855 0.318383 0.029937 \n", "5 0.306776 0.292058 0.312065 0.018870 \n", "\n", " rank_test_score \n", "2 1 \n", "6 2 \n", "0 3 \n", "4 4 \n", "3 5 \n", "7 6 \n", "1 7 \n", "5 8 " ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.model_selection import GridSearchCV, GroupKFold\n", "import pandas as pd\n", "\n", "optimisation_pipeline = GridSearchCV(\n", " create_pipeline(),\n", " {\n", " \"vectorizer__min_df\": ([5, 20, 100] if FULL_RUN else [1, 3]),\n", " \"vectorizer__max_df\": ([0.05, 0.1] if FULL_RUN else [0.9]),\n", " \"classifier__alpha\": [0.5, 1],\n", " \"classifier__fit_prior\": [True, False],\n", " },\n", " scoring=\"f1_macro\",\n", " cv=GroupKFold(n_splits=3),\n", " n_jobs=2,\n", " verbose=1,\n", ")\n", "# Group by paper text so that expanded labels and duplicate texts stay together.\n", "optimisation_pipeline.fit(X, y, groups=X)\n", "\n", "results = pd.DataFrame(optimisation_pipeline.cv_results_)\n", "results.sort_values(\"rank_test_score\")" ] }, { "cell_type": "code", "execution_count": 6, "id": "cell-8", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
Pipeline(steps=[('vectorizer', TfidfVectorizer(max_df=0.9, sublinear_tf=True)),\n",
       "                ('classifier', MultinomialNB(alpha=0.5, fit_prior=False))])
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" ], "text/plain": [ "Pipeline(steps=[('vectorizer', TfidfVectorizer(max_df=0.9, sublinear_tf=True)),\n", " ('classifier', MultinomialNB(alpha=0.5, fit_prior=False))])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn import set_config\n", "\n", "set_config(display=\"diagram\")\n", "\n", "classifier = create_pipeline()\n", "classifier.set_params(**optimisation_pipeline.best_params_)\n", "classifier.fit(X, y)" ] }, { "cell_type": "markdown", "id": "cell-9", "metadata": {}, "source": [ "## Export the model using GreatAI" ] }, { "cell_type": "code", "execution_count": 7, "id": "cell-10", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\u001b[38;5;39mFetching cached versions of small-domain-prediction\u001b[0m\n", "\u001b[38;5;39mFetching cached versions of small-domain-prediction\u001b[0m\n", "\u001b[38;5;39mFetching cached versions of small-domain-prediction\u001b[0m\n", "\u001b[38;5;39mModel small-domain-prediction uploaded with version 0\u001b[0m\n" ] }, { "data": { "text/plain": [ "'small-domain-prediction:0'" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from great_ai import save_model\n", "\n", "save_model(classifier, key=\"small-domain-prediction\", keep_last_n=5)" ] }, { "cell_type": "markdown", "id": "cell-11", "metadata": {}, "source": [ "## Next: [Part 3](https://great-ai.schmelczer.dev/examples/simple/deploy)" ] } ], "metadata": { "kernelspec": { "display_name": ".venv (3.13.5)", "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.13.5" } }, "nbformat": 4, "nbformat_minor": 5 }