<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Machine-Learning on Max Halford</title><link>https://maxhalford.github.io/tags/machine-learning/</link><description>Recent content in Machine-Learning on Max Halford</description><generator>Hugo</generator><language>en-US</language><managingEditor>maxhalford25@gmail.com (Max Halford)</managingEditor><webMaster>maxhalford25@gmail.com (Max Halford)</webMaster><lastBuildDate>Tue, 21 Jul 2026 21:18:41 +0200</lastBuildDate><atom:link href="https://maxhalford.github.io/tags/machine-learning/index.xml" rel="self" type="application/rss+xml"/><item><title>Text classification with Python 3.14's zstd module</title><link>https://maxhalford.github.io/blog/text-classification-zstd/</link><pubDate>Fri, 06 Feb 2026 00:00:00 +0000</pubDate><author>maxhalford25@gmail.com (Max Halford)</author><guid>https://maxhalford.github.io/blog/text-classification-zstd/</guid><description>&lt;p&gt;Python 3.14 &lt;a href="https://docs.python.org/3/whatsnew/3.14.html#whatsnew314-zstandard"&gt;introduced&lt;/a&gt; the &lt;a href="https://docs.python.org/3/library/compression.zstd.html"&gt;&lt;code&gt;compression.zstd&lt;/code&gt;&lt;/a&gt; module. It is a standard library implementation of Facebook&amp;rsquo;s &lt;a href="https://en.wikipedia.org/wiki/Zstd"&gt;Zstandard (Zstd)&lt;/a&gt; compression algorithm. It was developed a decade ago by Yann Collet, who holds a &lt;a href="https://fastcompression.blogspot.com/"&gt;blog&lt;/a&gt; devoted to compression algorithms.&lt;/p&gt;
&lt;p&gt;I am not a compression expert, but Zstd caught my eye because it supports incremental compression. You can feed it data to compress in chunks, and it will maintain an internal state. It&amp;rsquo;s particularly well &lt;a href="https://facebook.github.io/zstd/"&gt;suited&lt;/a&gt; for compressing small data. It&amp;rsquo;s perfect for the classify text via compression trick, which I described in &lt;a href="https://maxhalford.github.io/blog/text-classification-by-compression/"&gt;a previous blog post&lt;/a&gt; 5 years ago.&lt;/p&gt;</description></item><item><title>A training set for bike sharing forecasting</title><link>https://maxhalford.github.io/blog/bike-sharing-forecasting-training-set/</link><pubDate>Thu, 04 Apr 2024 00:00:00 +0000</pubDate><author>maxhalford25@gmail.com (Max Halford)</author><guid>https://maxhalford.github.io/blog/bike-sharing-forecasting-training-set/</guid><description>&lt;style&gt;
table {
 font-family: monospace; /* Apply monospace font */
}

table td, table th {
 white-space: nowrap; /* Prevent text from wrapping */
}
&lt;/style&gt;
&lt;p&gt;Last night I went to a &lt;a href="https://www.meetup.com/fr-FR/tlse-data-science/"&gt;Toulouse Data Science&lt;/a&gt; meetup. The talks were about generative AI and information retrieval, which aren&amp;rsquo;t topics I&amp;rsquo;m knowledgeable about. However, one of the speakers was a &lt;a href="https://github.com/raphaelsty"&gt;friend&lt;/a&gt; of mine, so I went to support him. Toulouse used to be my hometown, so I bumped into a few people I knew. It was a nice evening.&lt;/p&gt;</description></item><item><title>Text classification by data compression</title><link>https://maxhalford.github.io/blog/text-classification-by-compression/</link><pubDate>Tue, 08 Jun 2021 00:00:00 +0000</pubDate><author>maxhalford25@gmail.com (Max Halford)</author><guid>https://maxhalford.github.io/blog/text-classification-by-compression/</guid><description>&lt;p&gt;&lt;strong&gt;Edit&lt;/strong&gt; &amp;ndash; &lt;em&gt;I posted this &lt;a href="https://news.ycombinator.com/item?id=27440093"&gt;on Hackernews&lt;/a&gt; and got some valuable feedback. Many brought up the fact that you should be able to reuse the internal state of the compressor instead of recompressing the training data each time a prediction is made. There&amp;rsquo;s also some insightful references to data compression theory and its ties to statistical learning&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Edit (2025-06-29)&lt;/strong&gt; &amp;ndash; *Python 3.14 introduces &lt;a href="https://docs.python.org/3/library/compression.zstd.html#compression.zstd.train_dict"&gt;&lt;code&gt;compression.zstd&lt;/code&gt;&lt;/a&gt;, which implement&amp;rsquo;s Facebook&amp;rsquo;s Zstandard compression algorithm, as discussed in the comments section below.&lt;/p&gt;</description></item><item><title>Reducing the memory footprint of a scikit-learn text classifier</title><link>https://maxhalford.github.io/blog/sklearn-text-classifier-memory-footprint-reduction/</link><pubDate>Sun, 11 Apr 2021 00:00:00 +0000</pubDate><author>maxhalford25@gmail.com (Max Halford)</author><guid>https://maxhalford.github.io/blog/sklearn-text-classifier-memory-footprint-reduction/</guid><description>&lt;h2 id="context"&gt;Context&lt;/h2&gt;
&lt;p&gt;This week at Alan I&amp;rsquo;ve been working on parsing &lt;a href="https://www.wikiwand.com/fr/Ordonnance_(m%C3%A9decine)"&gt;French medical prescriptions&lt;/a&gt;. There are three types of prescriptions: lenses, glasses, and pharmaceutical prescriptions. Different information needs to be extracted depending on the prescription type. Therefore, the first step is to classify the prescription. The prescriptions we receive are pictures taken by users with their phone. We run each image through an OCR to obtain a text transcription of the image. We can thus use the text transcription to classify the prescription.&lt;/p&gt;</description></item><item><title>Unsupervised text classification with word embeddings</title><link>https://maxhalford.github.io/blog/unsupervised-text-classification/</link><pubDate>Sat, 03 Oct 2020 00:00:00 +0000</pubDate><author>maxhalford25@gmail.com (Max Halford)</author><guid>https://maxhalford.github.io/blog/unsupervised-text-classification/</guid><description>&lt;div align="center" &gt;
 &lt;img height="300px" src="https://maxhalford.github.io/img/blog/document-classification/morpheus.jpg" alt="morpheus"&gt;
 &lt;br&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Edit&lt;/strong&gt; &amp;ndash; &lt;em&gt;since writing this article, I have discovered that the method I describe is a form of &lt;a href="https://en.wikipedia.org/wiki/Zero-shot_learning"&gt;zero-shot learning&lt;/a&gt;. So I guess you could say that this article is a tutorial on zero-shot learning for NLP.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Edit&lt;/strong&gt; &amp;ndash; &lt;em&gt;I stumbled on a &lt;a href="https://www.aclweb.org/anthology/P19-1036/"&gt;paper&lt;/a&gt; entitled &amp;ldquo;Towards Unsupervised Text Classification Leveraging Experts and Word Embeddings&amp;rdquo; which proposes something very similar. The paper is rather well written, so you might want to check it out. Note that they call the &lt;code&gt;tech -&amp;gt; technology&lt;/code&gt; trick &amp;ldquo;label enrichment&amp;rdquo;.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Focal loss implementation for LightGBM</title><link>https://maxhalford.github.io/blog/lightgbm-focal-loss/</link><pubDate>Sun, 20 Sep 2020 00:00:00 +0000</pubDate><author>maxhalford25@gmail.com (Max Halford)</author><guid>https://maxhalford.github.io/blog/lightgbm-focal-loss/</guid><description>&lt;p&gt;&lt;strong&gt;Edit (2021-01-26)&lt;/strong&gt; &amp;ndash; &lt;em&gt;I initially wrote this blog post using version 2.3.1 of LightGBM. I&amp;rsquo;ve now updated it to use version 3.1.1. There are a couple of subtle but important differences between version 2.x.y and 3.x.y. If you&amp;rsquo;re using version 2.x.y, then I strongly recommend you to upgrade to version 3.x.y.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="motivation"&gt;Motivation&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re reading this blog post, then you&amp;rsquo;re likely to be aware of &lt;a href="https://github.com/microsoft/LightGBM"&gt;LightGBM&lt;/a&gt;. The latter is a best of breed &lt;a href="https://explained.ai/gradient-boosting/"&gt;gradient boosting&lt;/a&gt; library. As of 2020, it&amp;rsquo;s still the go-to machine learning model for tabular data. It&amp;rsquo;s also ubiquitous in competitive machine learning.&lt;/p&gt;</description></item><item><title>Speeding up scikit-learn for single predictions</title><link>https://maxhalford.github.io/blog/speeding-up-sklearn-single-predictions/</link><pubDate>Tue, 31 Mar 2020 00:00:00 +0000</pubDate><author>maxhalford25@gmail.com (Max Halford)</author><guid>https://maxhalford.github.io/blog/speeding-up-sklearn-single-predictions/</guid><description>&lt;p&gt;It is now common practice to train machine learning models offline before putting them behind an API endpoint to serve predictions. Specifically, we want an API route which can make a prediction for a single row/instance/sample/data point/individual (&lt;a href="https://www.youtube.com/watch?v=1prhCWO_518"&gt;call it what you want&lt;/a&gt;). Nowadays, we have great tools to do this that take care of the nitty-gritty details, such as &lt;a href="https://github.com/cortexlabs/cortex"&gt;Cortex&lt;/a&gt;, &lt;a href="https://www.mlflow.org/docs/latest/models.html"&gt;MLFlow&lt;/a&gt;, &lt;a href="https://www.kubeflow.org/docs/components/serving/"&gt;Kubeflow&lt;/a&gt;, and &lt;a href="https://github.com/ucbrise/clipper"&gt;Clipper&lt;/a&gt;. There are also paid services that hold your hand a bit more, such as &lt;a href="https://www.datarobot.com/"&gt;DataRobot&lt;/a&gt;, &lt;a href="https://www.h2o.ai/"&gt;H2O&lt;/a&gt;, and &lt;a href="https://www.cubonacci.com/"&gt;Cubonacci&lt;/a&gt;. One could argue that deploying machine learning models has never been easier.&lt;/p&gt;</description></item><item><title>Global explanation of machine learning with sensitivity analysis @ MASCOT-NUM</title><link>https://maxhalford.github.io/blog/global-explanation-of-ml-with-sensitivity-analysis/</link><pubDate>Tue, 10 Mar 2020 00:00:00 +0000</pubDate><author>maxhalford25@gmail.com (Max Halford)</author><guid>https://maxhalford.github.io/blog/global-explanation-of-ml-with-sensitivity-analysis/</guid><description/></item><item><title>Bayesian linear regression for practitioners</title><link>https://maxhalford.github.io/blog/bayesian-linear-regression/</link><pubDate>Wed, 26 Feb 2020 00:00:00 +0000</pubDate><author>maxhalford25@gmail.com (Max Halford)</author><guid>https://maxhalford.github.io/blog/bayesian-linear-regression/</guid><description>&lt;h2 id="motivation"&gt;Motivation&lt;/h2&gt;
&lt;p&gt;Suppose you have an infinite stream of feature vectors $x_i$ and targets $y_i$. In this case, $i$ denotes the order in which the data arrives. If you&amp;rsquo;re doing supervised learning, then your goal is to estimate $y_i$ &lt;em&gt;before&lt;/em&gt; it is revealed to you. In order to do so, you have a model which is composed of parameters denoted $\theta_i$. For instance, $\theta_i$ represents the feature weights when using linear regression. After a while, $y_i$ will be revealed, which will allow you to update $\theta_i$ and thus obtain $\theta_{i+1}$. To perform the update, you may apply whichever learning rule you wish &amp;ndash; for instance most people use &lt;a href="https://en.wikipedia.org/wiki/Stochastic_gradient_descent#/Extensions_and_variants"&gt;some flavor of stochastic gradient descent&lt;/a&gt;. The process I just described is called &lt;a href="https://en.wikipedia.org/wiki/Online_machine_learning"&gt;online supervised machine learning&lt;/a&gt;. The difference between online machine learning and the more traditional batch machine learning is that an online model is dynamic and learns on the fly. Online learning solves a lot of pain points in real-world environments, mostly because it doesn&amp;rsquo;t require retraining models from scratch every time new data arrives.&lt;/p&gt;</description></item><item><title>Under-sampling a dataset with desired ratios</title><link>https://maxhalford.github.io/blog/undersampling-ratios/</link><pubDate>Tue, 17 Dec 2019 00:00:00 +0000</pubDate><author>maxhalford25@gmail.com (Max Halford)</author><guid>https://maxhalford.github.io/blog/undersampling-ratios/</guid><description>&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve just spent a few hours looking at under-sampling and how it can help a classifier learn from an imbalanced dataset. The idea is quite simple: randomly sample the majority class and leave the minority class untouched. There are more sophisticated ways to do this &amp;ndash; for instance by creating synthetic observations from the minority class &lt;em&gt;à la&lt;/em&gt; &lt;a href="http://rikunert.com/SMOTE_explained"&gt;SMOTE&lt;/a&gt; &amp;ndash; but I won&amp;rsquo;t be discussing that here.&lt;/p&gt;
&lt;p&gt;I checked out the &lt;a href="https://imbalanced-learn.readthedocs.io/en/stable/index.html"&gt;&lt;code&gt;imblearn&lt;/code&gt;&lt;/a&gt; library and noticed they have an implementation of random under-sampling aptly named &lt;a href="https://imbalanced-learn.readthedocs.io/en/stable/generated/imblearn.under_sampling.RandomUnderSampler.html#imblearn.under_sampling.RandomUnderSampler"&gt;&lt;code&gt;RandomUnderSampler&lt;/code&gt;&lt;/a&gt;. It contains a &lt;code&gt;sampling_strategy&lt;/code&gt; parameter which gives some control over the sampling. By the default the observations are resampled so that each class is equally represented:&lt;/p&gt;</description></item><item><title>A smooth approach to putting machine learning into production</title><link>https://maxhalford.github.io/blog/machine-learning-production/</link><pubDate>Sat, 13 Jul 2019 00:00:00 +0000</pubDate><author>maxhalford25@gmail.com (Max Halford)</author><guid>https://maxhalford.github.io/blog/machine-learning-production/</guid><description>&lt;p&gt;Putting machine learning into production is hard. Usually I&amp;rsquo;m doubtful of such statements, but in this case I&amp;rsquo;ve never met anyone for whom everything has gone smoothly. Most data scientists might agree that there is a huge gap between their local environment and a live environment. In fact, &amp;ldquo;productionalizing&amp;rdquo; machine learning is such a complex topic that entire companies have risen to address the issue. I&amp;rsquo;m not just talking about running a gigantic grid search and finding the best model, I&amp;rsquo;m talking about putting a machine learning model live so that it actually has a positive impact on your business/project. Off the top of my head: &lt;a href="https://www.cubonacci.com/"&gt;Cubonacci&lt;/a&gt;, &lt;a href="https://www.h2o.ai/"&gt;H2O&lt;/a&gt;, &lt;a href="https://cloud.google.com/automl/"&gt;Google AutoML&lt;/a&gt;, &lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/how-it-works-hosting.html"&gt;Amazon Sagemaker&lt;/a&gt;, and &lt;a href="https://www.datarobot.com/"&gt;DataRobot&lt;/a&gt;. In other words people are making money off businesses because data scientists and engineers are having a hard putting their models into production. In my opinion if a data scientist can&amp;rsquo;t put her model into production herself then something is wrong. Life should be simpler.&lt;/p&gt;</description></item><item><title>Target encoding done the right way</title><link>https://maxhalford.github.io/blog/target-encoding/</link><pubDate>Sat, 13 Oct 2018 00:00:00 +0000</pubDate><author>maxhalford25@gmail.com (Max Halford)</author><guid>https://maxhalford.github.io/blog/target-encoding/</guid><description>&lt;p&gt;When you&amp;rsquo;re doing supervised learning, you often have to deal with categorical variables. That is, variables which don&amp;rsquo;t have a natural numerical representation. The problem is that most machine learning algorithms require the input data to be numerical. At some point or another a data science pipeline will require converting categorical variables to numerical variables.&lt;/p&gt;
&lt;p&gt;There are many ways to do so:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.LabelEncoder.html"&gt;Label encoding&lt;/a&gt; where you choose an arbitrary number for each category&lt;/li&gt;
&lt;li&gt;&lt;a href="http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html"&gt;One-hot encoding&lt;/a&gt; where you create one binary column per category&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tensorflow.org/tutorials/representation/word2vec"&gt;Vector representation&lt;/a&gt; a.k.a. word2vec where you find a low dimensional subspace that fits your data&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Microsoft/LightGBM/blob/master/docs/Advanced-Topics.rst#categorical-feature-support"&gt;Optimal binning&lt;/a&gt; where you rely on tree-learners such as LightGBM or CatBoost&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.saedsayad.com/encoding.htm"&gt;Target encoding&lt;/a&gt; where you average the target value by category&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each and every one of these method has its own pros and cons. The best approach typically depends on your data and your requirements. If a variable has a lot of categories, then a one-hot encoding scheme will produce many columns, which can cause memory issues. In my experience, relying on LightGBM/CatBoost is the best out-of-the-box method. Label encoding is useless and you should never use it. However if your categorical variable happens to be ordinal then you can and should represent it with increasing numbers (for example &amp;ldquo;cold&amp;rdquo; becomes 0, &amp;ldquo;mild&amp;rdquo; becomes 1, and &amp;ldquo;hot&amp;rdquo; becomes 2). &lt;a href="https://en.wikipedia.org/wiki/Word2vec"&gt;Word2vec&lt;/a&gt; and others such methods are cool and good but they require some fine-tuning and don&amp;rsquo;t always work out of the box.&lt;/p&gt;</description></item><item><title>Subsampling a training set to match a test set - Part 1</title><link>https://maxhalford.github.io/blog/subsampling-1/</link><pubDate>Mon, 19 Jun 2017 00:00:00 +0000</pubDate><author>maxhalford25@gmail.com (Max Halford)</author><guid>https://maxhalford.github.io/blog/subsampling-1/</guid><description>&lt;p&gt;&lt;strong&gt;Edit&lt;/strong&gt; &amp;ndash; &lt;em&gt;it&amp;rsquo;s 2022 and I still haven&amp;rsquo;t written a part 2. That&amp;rsquo;s because I believe this problem is easily solved with &lt;a href="https://www.kaggle.com/carlmcbrideellis/what-is-adversarial-validation"&gt;adversarial validation&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Some friends and I recently qualified for the final of the 2017 edition of the &lt;a href="http://www.datasciencegame.com"&gt;Data Science Game&lt;/a&gt; competition. The first part was a Kaggle competition with data provided by Deezer. The problem was a binary classification task where one had to predict if a user was going to listen to a song that was proposed to him. Like many teams we extracted clever features and trained an XGBoost classifier, classic. However, the one special thing we did was to subsample our training set so that it was more representative of the test set.&lt;/p&gt;</description></item><item><title>Predire la disponibilité des Velib' @ Toulouse Data Science Meetup</title><link>https://maxhalford.github.io/blog/forecasting-bicycle-sharing-usage/</link><pubDate>Wed, 30 Mar 2016 00:00:00 +0000</pubDate><author>maxhalford25@gmail.com (Max Halford)</author><guid>https://maxhalford.github.io/blog/forecasting-bicycle-sharing-usage/</guid><description/></item><item><title>The Naïve Bayes classifier</title><link>https://maxhalford.github.io/blog/naive-bayes/</link><pubDate>Thu, 10 Sep 2015 00:00:00 +0000</pubDate><author>maxhalford25@gmail.com (Max Halford)</author><guid>https://maxhalford.github.io/blog/naive-bayes/</guid><description>&lt;p&gt;The objective of a classifier is to decide to which &lt;em&gt;class&lt;/em&gt; (also called &lt;em&gt;label&lt;/em&gt;) to assign an observation based on observed data. In &lt;em&gt;supervised learning&lt;/em&gt;, this is done by taking into account previous classifications. In other words if we &lt;em&gt;know&lt;/em&gt; that certain observations are classified in a certain way, the goal is to determine the class of a new observation. The first group of observations on which the classifier is built is called the &lt;em&gt;training set&lt;/em&gt;.&lt;/p&gt;</description></item><item><title>An introduction to genetic algorithms</title><link>https://maxhalford.github.io/blog/genetic-algorithms-introduction/</link><pubDate>Sun, 02 Aug 2015 00:00:00 +0000</pubDate><author>maxhalford25@gmail.com (Max Halford)</author><guid>https://maxhalford.github.io/blog/genetic-algorithms-introduction/</guid><description>&lt;p&gt;The goal of genetic algorithms (GAs) is to solve problems whose solutions are not easily found (ie. NP problems, nonlinear optimization, etc.). For example, finding the shortest path from A to B in a directed graph is easily done with &lt;em&gt;Djikstra&amp;rsquo;s algorithm&lt;/em&gt;, it can be solved in polynomial time. However the time to find the smallest path that joins all points on a non-directed graph, also known as the &lt;a href="http://www.wikiwand.com/en/Travelling_salesman_problem"&gt;Travelling Salesman Problem&lt;/a&gt; (TSP) increases exponentially as the number of points increases. More generally, GAs are useful for problems where an analytical approach is complicated or even impossible. By giving up on perfection they manage to find a good approximation of the optimal solution.&lt;/p&gt;</description></item></channel></rss>