{"id":5119,"date":"2024-04-04T21:30:48","date_gmt":"2024-04-04T21:30:48","guid":{"rendered":"https:\/\/dalelane.co.uk\/blog\/?p=5119"},"modified":"2024-04-05T22:42:46","modified_gmt":"2024-04-05T22:42:46","slug":"how-ml-for-kids-handles-numbers-models","status":"publish","type":"post","link":"https:\/\/dalelane.co.uk\/blog\/?p=5119","title":{"rendered":"How ML for Kids handles numbers models now"},"content":{"rendered":"<p><strong>I&#8217;m on vacation for the Easter holidays this week. Apparently I don&#8217;t know how vacations work, so I\u2019ve spent a lot of the last six days working on <a href=\"https:\/\/github.com\/IBM\/taxinomitis\/pull\/493\">a major rewrite<\/a> of a big chunk of <a href=\"https:\/\/machinelearningforkids.co.uk\">Machine Learning for Kids<\/a>. In this post, I want to describe what I&#8217;ve been doing and why.<\/strong><\/p>\n<p><!--more--><\/p>\n<h3>In the beginning<\/h3>\n<p>The <a href=\"https:\/\/youtu.be\/m6dyCRS8EmI\">premise behind Machine Learning for Kids<\/a> is giving school-age children the tools for creating their own machine learning models, and integrating them in child-friendly coding platforms like Scratch so they can create projects using their models. <\/p>\n<p>When I launched the site in 2017&#8230;<\/p>\n<ul>\n<li>models for <strong>recognising text<\/strong> were trained using the Watson Conversation service in IBM Cloud<\/li>\n<li>models for <strong>recognising images<\/strong> were trained using the Watson Visual Recognition service in IBM Cloud<\/li>\n<li>models for <strong>recognising numbers<\/strong> were trained in a Python web service that I wrote using scikit-learn<\/li>\n<\/ul>\n<p>All models were trained in the cloud.<\/p>\n<p>All models were stored in the cloud. <\/p>\n<p>All inferencing was done in the cloud. <\/p>\n<p>For example, if you had a picture that you wanted to recognise using your ML model, you&#8217;d upload that image to the cloud. The image would need to be posted to the model server hosting your model. The model would classify your uploaded image, and return the results. <\/p>\n<p>I still think that was the right decision for the time:<\/p>\n<ul>\n<li>ML models were resource-expensive to train and run <br \/><em>pushing all the ML-related function to the cloud made sense<\/em><\/li>\n<li>ML in JavaScript was prohibitively complex <br \/><em>moving all the ML-related function off the browser made sense<\/em><\/li>\n<li>School computers were very, very underpowered <br \/><em>giving them nothing other than HTTP POST&#8217;s to do made sense<\/em><\/li>\n<li>The site had a low number of concurrent users <br \/><em>I didn&#8217;t need to optimise for scale yet<\/em><\/li>\n<\/ul>\n<p>But times change.<\/p>\n<h3>Seven years is a long time for a website<\/h3>\n<p>The factors that underpinned these decisions have shifted. <\/p>\n<ul>\n<li>ML models are more efficient than ever <br \/>quicker and easier to train and run<\/li>\n<li>JavaScript libraries like TensorFlow.js are amazingly powerful <br \/>(and you can use the same models in both Python and JavaScript)<\/li>\n<li>School computers are getting more powerful <br \/>(they\u2019re still slow compared to non-school computers, but so much better than seven years ago!)<\/li>\n<li>The site has a huge number of concurrent users nowadays <br \/>bottle-necking all projects through cloud APIs is more of a challenge<\/li>\n<\/ul>\n<p>I also support more environments than before &#8211; including Python-based options like replit and EduBlocks. <\/p>\n<p>These sort of shifts have driven a lot of the recent changes in the site. (For example, last Christmas, I <a href=\"https:\/\/dalelane.co.uk\/blog\/?p=5042\">added support for \u201clocal\u201d projects<\/a> &#8211; using IndexedDB and browser storage for training data.)<\/p>\n<p>My general trend is that I\u2019m steadily moving work out of the cloud and onto student computers. <\/p>\n<h4>In 2017&#8230;<\/h4>\n<h5>classifier models for <u>recognising text<\/u><\/h5>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/IBM\/taxinomitis\/blob\/master\/mlforkids-api\/public\/images\/cloud.png?raw=true\" border=0 style=\"width: 17px; height: 17px; margin-bottom: -4px;\"  \/> Trained in the cloud using Watson Conversation<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/IBM\/taxinomitis\/blob\/master\/mlforkids-api\/public\/images\/cloud.png?raw=true\" border=0 style=\"width: 17px; height: 17px; margin-bottom: -4px;\"  \/> Classifying in the cloud using Watson Conversation<\/p>\n<h5>classifier models for <u>recognising images<\/u><\/h5>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/IBM\/taxinomitis\/blob\/master\/mlforkids-api\/public\/images\/cloud.png?raw=true\" border=0 style=\"width: 17px; height: 17px; margin-bottom: -4px;\"  \/> Trained in the cloud using Watson Visual Recognition<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/IBM\/taxinomitis\/blob\/master\/mlforkids-api\/public\/images\/cloud.png?raw=true\" border=0 style=\"width: 17px; height: 17px; margin-bottom: -4px;\"  \/> Classifying in the cloud using Watson Visual Recognition<\/p>\n<h5>classifier models for <u>recognising numbers<\/u><\/h5>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/IBM\/taxinomitis\/blob\/master\/mlforkids-api\/public\/images\/cloud.png?raw=true\" border=0 style=\"width: 17px; height: 17px; margin-bottom: -4px;\"  \/> Trained in the cloud using scikit-learn<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/IBM\/taxinomitis\/blob\/master\/mlforkids-api\/public\/images\/cloud.png?raw=true\" border=0 style=\"width: 17px; height: 17px; margin-bottom: -4px;\"  \/> Classifying in the cloud using scikit-learn<\/p>\n<h4>Today&#8230;<\/h4>\n<h5>classifier models for <u>recognising text<\/u><\/h5>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/IBM\/taxinomitis\/blob\/master\/mlforkids-api\/public\/images\/cloud.png?raw=true\" border=0 style=\"width: 17px; height: 17px; margin-bottom: -4px;\"  \/> Trained in the cloud using Watson Assistant<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/IBM\/taxinomitis\/blob\/master\/mlforkids-api\/public\/images\/cloud.png?raw=true\" border=0 style=\"width: 17px; height: 17px; margin-bottom: -4px;\"  \/> Classifying in the cloud using Watson Assistant<\/p>\n<h5>classifier models for <u>recognising images<\/u><\/h5>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/IBM\/taxinomitis\/blob\/master\/mlforkids-api\/public\/images\/local.png?raw=true\" border=0 style=\"width: 17px; height: 17px; margin-bottom: -4px;\"  \/> Trained in the browser using TensorFlow.js<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/IBM\/taxinomitis\/blob\/master\/mlforkids-api\/public\/images\/local.png?raw=true\" border=0 style=\"width: 17px; height: 17px; margin-bottom: -4px;\"  \/> Classifying in the browser using TensorFlow.js<\/p>\n<h5>classifier models for <u>recognising numbers<\/u><\/h5>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/IBM\/taxinomitis\/blob\/master\/mlforkids-api\/public\/images\/cloud.png?raw=true\" border=0 style=\"width: 17px; height: 17px; margin-bottom: -4px;\"  \/> Trained in the cloud using TensorFlow Decision Forest<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/IBM\/taxinomitis\/blob\/master\/mlforkids-api\/public\/images\/local.png?raw=true\" border=0 style=\"width: 17px; height: 17px; margin-bottom: -4px;\"  \/> Classifying in the browser using TensorFlow.js<\/p>\n<h5>classifier models for <u>recognising sounds<\/u><\/h5>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/IBM\/taxinomitis\/blob\/master\/mlforkids-api\/public\/images\/local.png?raw=true\" border=0 style=\"width: 17px; height: 17px; margin-bottom: -4px;\"  \/> Trained in the browser using TensorFlow.js<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/IBM\/taxinomitis\/blob\/master\/mlforkids-api\/public\/images\/local.png?raw=true\" border=0 style=\"width: 17px; height: 17px; margin-bottom: -4px;\"  \/> Classifying in the browser using TensorFlow.js<\/p>\n<h5>regression models for <u>predicting numbers<\/u><\/h5>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/IBM\/taxinomitis\/blob\/master\/mlforkids-api\/public\/images\/local.png?raw=true\" border=0 style=\"width: 17px; height: 17px; margin-bottom: -4px;\"  \/> Trained in the browser using TensorFlow.js<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/IBM\/taxinomitis\/blob\/master\/mlforkids-api\/public\/images\/local.png?raw=true\" border=0 style=\"width: 17px; height: 17px; margin-bottom: -4px;\"  \/> Classifying in the browser using TensorFlow.js<\/p>\n<p>.<\/p>\n<p>Classifier models for recognising numbers are the latest shift.<\/p>\n<h3>How it works now<\/h3>\n<p>Students collect training data. If it\u2019s a &#8220;local project&#8221;, they store it in their browser. If it\u2019s a \u201ccloud project\u201d, it\u2019s stored in my PostgreSQL database. <\/p>\n<p>When it is time to train a model, this goes to a new Python web service I&#8217;ve created. <\/p>\n<p>It uses the TensorFlow Decision Forests library to create a model&#8230;<\/p>\n<p><script src=\"https:\/\/emgithub.com\/embed-v2.js?target=https%3A%2F%2Fgithub.com%2FIBM%2Ftaxinomitis%2Fblob%2F5c1a94115742ee39ab5fcb9a6cb86db39715baf7%2Fmlforkids-newnumbers%2Fapp%2Fmodels.py%23L97-L100&#038;style=default&#038;type=code&#038;showBorder=on&#038;showLineNumbers=on&#038;showFileMeta=on&#038;fetchFromJsDelivr=on\"><\/script><\/p>\n<p>(It really is that easy.)<\/p>\n<p>The model is saved to a file&#8230; <\/p>\n<p><script src=\"https:\/\/emgithub.com\/embed-v2.js?target=https%3A%2F%2Fgithub.com%2FIBM%2Ftaxinomitis%2Fblob%2F5c1a94115742ee39ab5fcb9a6cb86db39715baf7%2Fmlforkids-newnumbers%2Fapp%2Fmodels.py%23L102-L104&#038;style=default&#038;type=code&#038;showBorder=on&#038;showLineNumbers=on&#038;showFileMeta=on&#038;fetchFromJsDelivr=on\"><\/script><\/p>\n<p>TensorFlow Converter converts the model to a TensorFlow.js version, and saves that to a file. <\/p>\n<p><script src=\"https:\/\/emgithub.com\/embed-v2.js?target=https%3A%2F%2Fgithub.com%2FIBM%2Ftaxinomitis%2Fblob%2F5c1a94115742ee39ab5fcb9a6cb86db39715baf7%2Fmlforkids-newnumbers%2Fapp%2Fmodels.py%23L105-L106&#038;style=default&#038;type=code&#038;showBorder=on&#038;showLineNumbers=on&#038;showFileMeta=on&#038;fetchFromJsDelivr=on\"><\/script><\/p>\n<p>Browser-based environments, like Scratch, download the JS model files <\/p>\n<p><script src=\"https:\/\/emgithub.com\/embed-v2.js?target=https%3A%2F%2Fgithub.com%2FIBM%2Ftaxinomitis%2Fblob%2F5c1a94115742ee39ab5fcb9a6cb86db39715baf7%2Fmlforkids-api%2Fpublic%2Fcomponents%2Fnumbertraining%2Fnumbertraining.service.js%23L114-L116&#038;style=default&#038;type=code&#038;showBorder=on&#038;showLineNumbers=on&#038;showFileMeta=on&#038;fetchFromJsDelivr=on\"><\/script><\/p>\n<p>From here on, all classifying can be done in the browser. <\/p>\n<p><script src=\"https:\/\/emgithub.com\/embed-v2.js?target=https%3A%2F%2Fgithub.com%2FIBM%2Ftaxinomitis%2Fblob%2F5c1a94115742ee39ab5fcb9a6cb86db39715baf7%2Fmlforkids-api%2Fpublic%2Fcomponents%2Fnumbertraining%2Fnumbertraining.service.js%23L228-L232&#038;style=default&#038;type=code&#038;showBorder=on&#038;showLineNumbers=on&#038;showFileMeta=on&#038;fetchFromJsDelivr=on\"><\/script><\/p>\n<p>The browser saves the model in IndexedDB storage, so it can be reused. <\/p>\n<p><script src=\"https:\/\/emgithub.com\/embed-v2.js?target=https%3A%2F%2Fgithub.com%2FIBM%2Ftaxinomitis%2Fblob%2F5c1a94115742ee39ab5fcb9a6cb86db39715baf7%2Fmlforkids-api%2Fpublic%2Fcomponents%2Fnumbertraining%2Fnumbertraining.service.js%23L113-L135&#038;style=default&#038;type=code&#038;showBorder=on&#038;showLineNumbers=on&#038;showFileMeta=on&#038;fetchFromJsDelivr=on\"><\/script><\/p>\n<p>Python-based environments download the full TF model files &#8211; from here on, classifying is all done locally on the student\u2019s computer. The model is saved locally, so it can be reused. <\/p>\n<p><script src=\"https:\/\/emgithub.com\/embed-v2.js?target=https%3A%2F%2Fgithub.com%2FIBM%2Ftaxinomitis%2Fblob%2F5c1a94115742ee39ab5fcb9a6cb86db39715baf7%2Fresources%2Fmlforkidsnumbers.py%23L124-L141&#038;style=default&#038;type=code&#038;showBorder=on&#038;showLineNumbers=on&#038;showFileMeta=on&#038;fetchFromJsDelivr=on\"><\/script><\/p>\n<p>All of this means the web service doesn\u2019t need to keep the model around for long. It only needs to be stored long enough for the student to download it, immediately after it was trained. After that, it can be deleted to save storage space. <\/p>\n<p><script src=\"https:\/\/emgithub.com\/embed-v2.js?target=https%3A%2F%2Fgithub.com%2FIBM%2Ftaxinomitis%2Fblob%2F5c1a94115742ee39ab5fcb9a6cb86db39715baf7%2Fmlforkids-newnumbers%2Fapp%2Fsavedmodels.py%23L25-L33&#038;style=default&#038;type=code&#038;showBorder=on&#038;showLineNumbers=on&#038;showFileMeta=on&#038;fetchFromJsDelivr=on\"><\/script><\/p>\n<p>This makes it much easier to scale &#8211; the only complex thing the web service is doing is training models, as hosting static model files is computationally trivial.<\/p>\n<p><script src=\"https:\/\/emgithub.com\/embed-v2.js?target=https%3A%2F%2Fgithub.com%2FIBM%2Ftaxinomitis%2Fblob%2F5c1a94115742ee39ab5fcb9a6cb86db39715baf7%2Fmlforkids-newnumbers%2Fapp%2Fmain.py%23L42-L43&#038;style=default&#038;type=code&#038;showBorder=on&#038;showLineNumbers=on&#038;showFileMeta=on&#038;fetchFromJsDelivr=on\"><\/script><\/p>\n<h3>Will this help?<\/h3>\n<p>It&#8217;s been a <a href=\"https:\/\/mastodon.org.uk\/@dalelane\/112206368887623227\">bigger piece of work than I anticipated<\/a>. What started as a bit of holiday tinkering turned into <a href=\"https:\/\/github.com\/IBM\/taxinomitis\/pull\/493\">a 150-file commit<\/a>, but I think this will help. The old numbers service was getting harder to scale, and was long overdue an update. <\/p>\n<p>I would&#8217;ve loved to have moved the model training off the cloud as well, but I couldn&#8217;t get that working in an easy way that was consistent across web and Python environments. This feels like a decent compromise &#8211; training once but then doing everything else locally after that. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m on vacation for the Easter holidays this week. Apparently I don&#8217;t know how vacations work, so I\u2019ve spent a lot of the last six days working on a major rewrite of a big chunk of Machine Learning for Kids. In this post, I want to describe what I&#8217;ve been doing and why.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[587],"class_list":["post-5119","post","type-post","status-publish","format-standard","hentry","category-code","tag-mlforkids-tech"],"_links":{"self":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5119","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5119"}],"version-history":[{"count":0,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5119\/revisions"}],"wp:attachment":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}