<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Heuritech, a Luxurynsight Company - Medium]]></title>
        <description><![CDATA[Heuritech is a cutting-edge artificial intelligence company that provides fashion &amp; sportwears brands with predictive analytics on trends. - Medium]]></description>
        <link>https://medium.com/heuritech?source=rss----8fc6104db0e8---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Heuritech, a Luxurynsight Company - Medium</title>
            <link>https://medium.com/heuritech?source=rss----8fc6104db0e8---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 10:06:17 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/heuritech" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Should We Ship This Model? A Bayesian look at precision and recall, and how to turn it into actions]]></title>
            <link>https://medium.com/heuritech/should-we-ship-this-model-a-bayesian-look-at-precision-and-recall-and-how-to-turn-it-into-actions-e994de21de9b?source=rss----8fc6104db0e8---4</link>
            <guid isPermaLink="false">https://medium.com/p/e994de21de9b</guid>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[fashion-trends]]></category>
            <category><![CDATA[probability]]></category>
            <category><![CDATA[bayesian-statistics]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Oscar Bouvier]]></dc:creator>
            <pubDate>Mon, 22 Jun 2026 14:32:58 GMT</pubDate>
            <atom:updated>2026-06-22T15:18:17.401Z</atom:updated>
            <content:encoded><![CDATA[<p>Every machine learning team eventually runs into the same uncomfortable moment. You’ve trained a new classification model, the numbers look a little better than the old one, someone asks: <em>“So, are we shipping it?”</em></p><p>And you realize the answer isn’t obvious. Precision went up by 3 points, but on how many images? Recall dropped on one rare category; is that real, or just noise? The classifier looks great on your test set, but will it hold up on real-world data?</p><p>I’m Oscar Bouvier, research engineer at Heuritech. At <a href="https://medium.com/heuritech">Heuritech</a>, we analyze millions of social media images to detect over 2,000 fashion attributes, and turn that into trend forecasts for fashion and sportswear brands. Our <strong>Data Science</strong> team trains specialized deep-learning models, one per garment family (dresses, pants, shoes, tops…), each detecting hundreds of fine-grained attributes.</p><p><strong>And a model is never uniformly good or bad</strong>; its quality varies sharply <strong>from one attribute to the next</strong>, and so does the <strong>amount of data</strong> used to assess it. “Bleach Denim” fabric might be rock-solid while “Poet” sleeve is a coin flip. The labels that matter most are the ones we see <em>least, </em>and so the ones we can judge with least confidence: a niche detail meaningful to a client, or an emerging trend still on the rise.</p><p>Alongside us, the <strong>Ops Team</strong> safeguards the quality and completeness of what reaches the platform: they turn client demands into concrete attributes, collect the relevant data, and orchestrate the retrains.</p><p>After every retrain, both teams face the same recurring question: <strong>for any single attribute, is the model good enough to ship?</strong></p><p>This article tries to answer this question, resting on one central idea: <strong>a metric isn’t a model’s true behavior but an observation of it, and every observation carries a degree of confidence</strong>.</p><p><strong>Bayesian probability </strong>is the practical framework<strong> </strong>that<strong> </strong>quantifies that uncertainty and turns it into diagnoses and actionable decisions, giving the Ops Team what it needs to make the right move.</p><p>The mathematical backbone of the approach comes from a 2005 paper by Goutte and Gaussier, <a href="https://link.springer.com/chapter/10.1007/978-3-540-31865-1_25">“A Probabilistic Interpretation of Precision, Recall and F-score”</a>. It’s an elegant, well-established result that we’ve found genuinely useful in production. <strong>We’d like to see it become a standard tool, and this article is our case for adopting it!</strong></p><p>Everything here is available as reusable Python code in this repo, with examples, plots, and animations illustrating the different practical use cases. The <em>bayesian-precision-recall</em> package is also available on PyPI. Check it out!</p><pre>pip install bayesian-precision-recall</pre><p><a href="https://github.com/OscarBouv/bayesian-precision-recall/tree/main">GitHub - OscarBouv/bayesian-precision-recall: Bayesian precision-recall model for ML evaluation with production drift detection</a></p><p>If you want the bigger picture of the team’s research, and our efforts to push model performance and trend-insight quality as far as possible, take a look at my colleagues’ articles!</p><ul><li><a href="https://medium.com/@etienne.david">Étienne</a> on designing the cutting-edge forecasting models that power Heuritech’s trend insights: <a href="https://medium.com/heuritech/is-fashion-predictable-the-rise-of-foundation-models-44c7d12cd0ba"><em>Is Fashion Predictable? The Rise of Foundation Models</em></a></li><li><a href="https://medium.com/@paul.morel">Paul</a> on our deep-learning vision stack: <a href="https://medium.com/heuritech/a-social-media-image-is-worth-a-thousand-fashion-labels-72423e472587"><em>A social media image is worth a thousand fashion labels…</em></a></li><li><a href="https://medium.com/@develle.louis">Louis</a> on our systematic approach to tuning every model for the best possible performance: <a href="https://medium.com/heuritech/stop-guessing-a-systematic-methodology-for-tuning-deep-learning-models-b3ea18e7e7c6"><em>Stop Guessing: A Systematic Methodology for Tuning Deep Learning Models</em></a></li></ul><h3>Part 1: The two questions every attribute has to answer</h3><p>Every data science student learns <strong>precision</strong> and <strong>recall</strong> early on, usually as a pair of formulas to memorize. But it’s worth pausing on what they actually mean.</p><p>When a model looks at an image and declares <em>“this is a bleach denim jacket,”</em> there are two different ways it can be wrong, and they map onto two metrics.</p><p><strong>Precision</strong> answers: <em>When the model says “bleach denim jacket,” how often is it right?</em> A high-precision detector is rarely wrong. When it makes a claim, you can trust it.</p><p><strong>Recall</strong> answers: <em>Of all the bleach denim jackets that were actually there, how many did it find?</em> A high-recall one rarely misses anything, even if it occasionally over-claims.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EGS2jVRW3n5rFMgSproOCQ.png" /><figcaption><em>Two archetypes of failure, for one attribute. The cautious model only flags what it’s sure of: few false alarms, but plenty missed. The eager model catches everything, at the cost of constant false alarms.</em></figcaption></figure><p>These two pull in opposite directions, and either is easy to game at the other’s expense. The extreme cases make it clear:</p><ul><li>Predict only what you’re sure of (~near 100% certainty threshold) : precision is perfect, recall can be near zero;</li><li>Predict every image (~0% certainty threshold): recall is perfect while precision is near zero;</li></ul><p><strong>Alone, each is meaningless,</strong> which is why the F1-score rolls them into a single number. <strong>For us, though, they don’t carry equal weight, and the reason shapes everything below.</strong></p><h3>Part 2: Why precision matters most for us</h3><p>What Heuritech sells is <strong>trend insights</strong>. The question for a client is less “is there a trench coat in this photo” but more “is the trench coat growing or shrinking, in which market, and how fast.” This is driven by the <em>relative volume of an attribute over time</em> (its trajectory), and a trajectory is only trustworthy if the underlying counts are clean and stable.</p><p>The two metrics matter for different reasons: precision keeps the trajectory’s <em>shape</em> honest, stopping false detections from bending it, while recall keeps its <em>volume</em> high enough that the signal stays statistically meaningful. Steady errors are survivable: a fixed fraction of detections are wrong, or a fixed fraction missed, just scales the counts by a constant factor and doesn’t impact the <em>shape</em>. The figure below tells the story for false positives.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eo9mdWFO7vmRSVLc7uKJ-A.png" /><figcaption><em>The true rising trend (green) is identical across all three panels; only the false positives (red) differ. With high precision the signal is clean. With low-but-steady precision the red caps are large yet grow in proportion, so the trajectory’s shape survives. The danger is the third case: when false positives drift, growing faster than the real signal, the measured trajectory bends and we report a growth rate that isn’t real.</em></figcaption></figure><p>The problem is false positives whose rate <strong>shifts with season, platform, or geography</strong>, such as a new Instagram filter that fools the classifier, a regional styling it never saw, a seasonal look-alike garment. <strong>Any of these can make false positives, so as the underlying trend, surge while the real one is flat</strong>. <strong>High precision ensures that drift is small enough that the shape stays trustworthy</strong>.</p><p><strong>Recall can drift too:</strong> if the model’s miss rate increases over time, a flat trend can show up as a decline.</p><p><strong>What tips the balance is the direction of error</strong>: precision drift tends to invent or <strong>inflate a trend,</strong> while recall drift mostly dampens a real one, and reporting a rise that isn’t happening is the failure we least want to hand a client.</p><p>That’s why we set asymmetric minimum bars for shipping an attribute, <strong>consistently favoring precision over recall, </strong>reflecting our preference to miss some real garments rather than distort the growth signals our clients act on.</p><p>The target thresholds are set granularly depending on the <em>criticality</em> of the attribute, its<em> business impact</em>, and its <em>visual distinctiveness.</em></p><p><strong>Precision keeps the signal honest; recall keeps it readable and we need every attribute to clear its respective bars.</strong></p><h3>Part 3: A metric is an estimate, not a fact</h3><p>We never actually know an attribute’s true precision. What we call “precision = 80%” only ever means “out of the 100 images we happened to check, 80 were correct.” <strong>The <em>true</em> precision, the rate at which the model would be right across all possible images, is invisible.</strong> We estimate it only through a finite, often small, sometimes biased sample.</p><p>Take a coin you suspect is unfair. Flip it 10 times and get 7 heads (70% rate). We can’t tell yet if the coin is biased: 7 out of 10 can happen with a perfectly fair coin, so 50% is still entirely plausible. Now flip it 1,000 times and get 508 heads, 50.8%. The observed rate is closer to even, but more importantly it is now much more <em>reliable</em>: a thousand flips leave almost no room for the true rate to be far from 50%. <strong>Confidence comes from the volume of flips behind a rate, not from the rate itself.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*M5HI1-IhWxxT1JamfkGbFQ.png" /><figcaption><em>A genuinely fair coin seen two ways. After 10 flips a 70% reading looks like bias, but the plausible range comfortably covers 50%, so we can’t conclude anything. After 1,000 flips the reading sits near 50.8% and the band collapses around the truth.</em></figcaption></figure><p><strong>Estimating an attribute’s precision is exactly the same problem, except that heads and tails become true positives and false positives.</strong></p><h3>Part 4: From a single number to a curve</h3><p>This is where Bayesian modeling enters. Instead of reporting a single number, we report a <strong>distribution</strong>: a description of which true precision values are plausible given the data, and by how much. <strong>Bayesian inference is exactly the machinery that turns a raw count of true and false positives into a probability distribution, represented by a curve</strong>. For precision and recall, that curve takes the form of a <a href="https://en.wikipedia.org/wiki/Beta_distribution"><strong>Beta distribution</strong>,</a> a flexible family that lives neatly between 0 and 1, exactly the range a probability can take.</p><p><em>For</em> <em>a deeper look at the mathematics behind those concepts and further explanations on Precision/Recall, see the animations in the final section!</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EO0E_nhw_1MuXEm1BjVhDA.png" /><figcaption><em>The same 70% estimate, two different worlds. With 20 samples (orange) the curve is broad: the truth could plausibly sit anywhere between 50% and 80%. With 200 samples (blue) it collapses into a tight spike.</em></figcaption></figure><p><strong>More data gives a narrower curve and more confidence.</strong> A wide, flat curve means “the true precision could be anywhere.” A tall, narrow spike means “we’re quite sure.” Through all of it the curve stays <em>centered</em> on the precision we actually observed; <strong>our best single guess remains the raw measured rate while our confidence in it grows.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*veXrl9VBbDA5bf6R9jAPdw.gif" /></figure><h3>Part 5: Two real attributes from our data</h3><p>For the rest of this article we’ll draw our entity examples from one classifier, the <strong>pants attribute model</strong> (loose jeans, cargo pocket, equestrian pants, etc.). Here are two of its labels from our actual pipeline. <strong>Loose jeans</strong>: 80 true positives, 26 false positives. With over a hundred predictions behind it, the curve is tight. <strong>Equestrian pants</strong>: just 5 true positives, 6 false positives. With only 11 predictions, the curve is very wide and the real performance remains uncertain.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gdsPyRtnXizvOo1o7DdZJw.png" /><figcaption><em>Two production attributes, drawn from their real counts. If you only read the point estimates, you’d treat both as solid facts. The curves tell you that one of them is barely a rumor.</em></figcaption></figure><p>This is why we never compare bare numbers. The loose-jeans 75% precision is something we can act on; the equestrian-pants 45% could just as easily be 30% or 60%, the same kind of number but a completely different decision.</p><blockquote><em>A useful quirk: for a fixed number of samples, </em>extreme<em> estimates come with more confidence than middling ones. A model that nails 10/10 is more convincingly good than one scoring 6/10 is convincingly average.</em></blockquote><h3>Part 6: The diagnosis: the three gates every attribute must pass</h3><p>A metric estimate alone is not enough to decide whether an attribute is ready. This is where real-world industrial constraints comes into play.</p><p>We ask three questions:</p><ul><li>does it clear our quality bars?</li><li>is it better than the model currently in production?</li><li>will it hold up on real-world data?</li></ul><p>The same Bayesian framework can answer all three <strong>by measuring confidence, not just performance.</strong></p><p><strong>Question 1: Does it confidently clear the bar?</strong></p><p>Using the posterior curve and our in-lab testing data, <strong>we compute the probability that the attribute’s true precision and true recall exceeds their respective floor</strong>. What we care about is how much of the curve sits above the bar, not merely where its peak lands. In practice, this probability is simply the area under the posterior curve that falls above the threshold (the green region).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*QfIjBc92xYhTLnjehrGn1w.gif" /></figure><p>An attribute is considered “<strong>satisfying”</strong> only when that probability is high (&gt;80%) and “<strong>insufficient”</strong> when it’s low (&lt;20%). We flag “<strong>borderline</strong><em>”</em> performance when confidence is close to the acceptance threshold (70–80%), since a small amount of additional data could change the verdict. Anything in between is “<strong>uncertain”.</strong></p><p><strong>Question 2: Is it better than the model currently in production?</strong></p><p>We also ask whether the new candidate actually improves on the model currently serving it. <strong>Instead of comparing two point estimates, we compare two <em>curves</em>, asking for the probability that the new model is genuinely better</strong>: <em>P(p_new &gt; p_old)</em>. Since the difference of two Betas has no tidy closed form, we estimate it by sampling from each curve and counting how often the new model wins. See how this sampling strategy can actually converge to a precise estimate.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*hqy8HpBjjPf7t--DpIrVgw.gif" /></figure><p>We can now turn these probabilities into actionable verdicts: <strong>Certain gain</strong> (P &gt; 0.80), <strong>Certain drop</strong> (P &lt; 0.20), <strong>Stagnation</strong> (in between).</p><p>A <strong>certain drop</strong> matters: the retrain has made this attribute <em>worse</em> than what’s already live, and needs an investigation. A stagnation means the change was real but neutral.</p><p><strong>Question 3: Will it survive real-world data?</strong></p><p>A classifier can clear the bar and beat the old model on the <strong>test set</strong>, then fall apart on <strong>production</strong> data, where new filters, regional styles, and shifting habits can differ. This is <strong>domain shift</strong>, and on social media it’s the default.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0uo-q_M8z3phTYRw59MYCA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3vrCo9z66vC3as-tSTiNrA.png" /><figcaption>Few production samples. The production curve is so wide it swallows the test curve, so even a 12.5% apparent drop tells us nothing. We cannot conclude there’s a problem.</figcaption></figure><p>The same Bayesian tools handle it: we look at the posterior of the difference between the two rates and ask whether it’s big enough to matter, using a small Region of Practical Equivalence (ROPE) around zero. If the credible interval sits inside the ROPE the metric transfers; if it sits clearly outside, the drop is real; if it straddles the edge, there isn’t enough data to tell.</p><p>Two things matter at once here, <strong>how big the gap is and how much data supports it.</strong> A big drop on lots of data is a five-alarm fire. A big drop on five images is a shrug.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*RIh5lWcd3fpPQJeOp4gycw.gif" /></figure><h3>Part 7: From diagnosis to action with the Ops playbook</h3><p>The shipping decision belongs to our <strong>Ops Team, the people who safeguard the quality and completeness of our platform insights</strong>. For every attribute they decide the next step. Is it already good to go? What kind of data should we target? This framework is what gives them the tools to choose with confidence.</p><p><strong>Each failure mode points to a different remedy, and each remedy becomes a concrete task for our Ops team</strong>. Rather than label it “insufficient” and move on, we route it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dUSo9IzBGOmiZdxUlGRSZw.png" /><figcaption><em>Every diagnosis maps to one action. Four lead back to retraining; the fifth (an attribute already far from any threshold) skips the loop, either shipping straight away or being set aside. The loop runs in parallel across the whole nomenclature.</em></figcaption></figure><p>The five situations we route on, and their responses:</p><ul><li><strong>Not enough data (wide, uncertain curve).</strong> The estimate is too uncertain to trust either way. Ops launches a <strong>targeted acquisition</strong>: rather than tagging at random, we run a <strong>text</strong> <strong>embedding-based search</strong> that queries our image pool with the attribute’s description and combine it with <em>active learning</em> that prioritizes the cases the model is least sure about. The goal isn’t more data in general, but more data <em>for this specific class</em>, found efficiently.</li><li><strong>Bad production transfer (test and prod curves separate).</strong> The attribute works in the lab but not in the wild. Ops runs a <strong>precision audit on true production positives</strong>, pulling the actual predicted-positive images from prod and hand-checking them to find the failure mode (a new filter? a confusable look-alike garment? a regional styling we never trained on?). The audit tells us <em>what kind</em> of data to go collect.</li><li><strong>A certain drop against the live model.</strong> An <em>existing</em> attribute comes back confidently worse than what’s shipped, usually because a <strong>newly added class confounds an old one</strong> (“cargo pocket” bleeding into “patch pocket”). Ops finds the offending pair and either <strong>tags more examples along the confusion frontier</strong> to sharpen the boundary, or <strong>redefines the class architecture</strong> if the two simply aren’t separable.</li><li><strong>Borderline precision or recall.</strong> The estimate sits near a bar but the posterior curve still spills across it. If it’s <em>precision</em>, the model is over-claiming on a confusable category, so Ops mines <strong>hard negatives</strong> to push that curve above the floor. If it’s <em>recall</em>, the fix points the other way: tag more <strong>positives</strong>, especially the <strong>harder ones</strong> the model misses.</li><li><strong>Far from any threshold (clearly above or clearly below).</strong> Not every verdict needs a retrain. If a class sits comfortably above both floors with a tight curve, the right action is to <strong>ship it now</strong> and move the team’s effort elsewhere. If it sits far <em>below</em>, and acquisition has already had its chances, the honest call is to <strong>deprioritize it</strong>, or redefine the attribute into something the model can actually separate. Knowing when <em>not</em> to spend another cycle is as valuable as knowing when to.</li></ul><p>Each remedy feeds a <strong>retrain until every attribute clears the bars. For a critical new attribute, one pass is rarely enough.</strong></p><p>Shipping a brand-new critical attribute reliably can take <strong>up to four retrain-and-acquisition cycles</strong>, each loop sharpening a different weakness (first volume, then transfer, then the stubborn confusions) <strong>until it clears all three gates with enough confidence to trust.</strong></p><p>The discipline of the loop is what lets us promise clients <em>trustworthy</em> insight, not just <em>available</em> insight.</p><h3>Why this changes how we work</h3><p>The change is easy to state and far-reaching in practice. We stopped treating per-attribute metrics as facts and began treating them as <strong>beliefs with a measurable degree of confidence.</strong> It helps us avoid overreacting to sparse data, detect meaningful regressions earlier, and direct data-collection efforts toward the attributes where additional evidence will have the greatest impact.</p><p>More importantly, <strong>it sets the standard an entity must meet before reaching production.</strong> Instead of relying on an uncertain performance estimate, <strong>we require enough evidence to be confident that the result is real. </strong>The goal is not just better metrics, but more trustworthy ones.</p><p>That discipline is what lets the trends we report stand on solid ground, so that when our platform tells a brand a dress silhouette is rising in South Korea, the number reflects what is actually happening, not what a thin or shifting sample merely suggested.</p><h3>Beyond Heuritech: build your own decisions</h3><p>The three use cases presented here (acceptance thresholds, model-to-model comparisons, and production drift detection) are simply the questions we needed to answer. They are not special cases of the framework, they are consequences of it.</p><p><strong>Once precision and recall are modeled as probability distributions, uncertainty becomes something you can reason about</strong>. From there, designing new decision rules is surprisingly easy. The question is no longer “what is the metric?” but “<strong>what is the probability that the metric satisfies the condition I care about?</strong>”.</p><p>If you’re a data scientist or ML engineer, and this kind of problem shows up in your own work, I encourage you to give it a try! The Bayesian machinery stays the same; only the question changes.</p><h3>⤷ Bonus : the maths, for the curious</h3><p>Let’s get a bit deeper into the bayesian precision and recall modelling.</p><p>Take a very simple prediction task, like predicting whether the animal in an image is a cat or a dog. The “cat” true precision is an unknown number p ∈ [0,1]. We never see p directly; we only see counts of true positive (right “cat” detections) and false positives (predicted “‘cat” when it’s actually a “dog”) named TP and FP. The same goes for recall r ∈ [0,1] with counting false negatives (missed “cat” predicting “dog”).</p><p><strong>Each predicted-positive “cat” image is then one biased flip trial : given unknow true precision is p, that prediction is correct (TP) with probability p and wrong with probability 1-p (FP).</strong></p><blockquote><em>Similarly each labeled-positive “cat” image is predicted with probability r (TP) and missed with probability 1-r (FN).</em></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*kkDCMqqzcJVFm8OIGuJTwg.gif" /></figure><p>The link between the two is the <strong>likelihood</strong>: the probability of seeing those counts, <em>assuming</em> the true precision is some value p, that follows <strong>Binomial distribution</strong> (same as biased coin flips). Using a well-chosen <strong>Beta prior , the posterior is also a Beta distribution.</strong></p><blockquote>The uninformative prior applies when choosing Beta(1, 1) (α=β=1), collapsing to a uniform (flat) prior.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*heVwN0ycA1Ism4tOtvSziQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*6EF0ZflPys_8DqHDza2jAw.gif" /></figure><p>Have a play with this Desmos visualization to see how the prior, likelihood, and posterior interact, and how we turn the posterior into the probability of clearing a minimum acceptance rate!</p><p><a href="https://www.desmos.com/calculator/zyp4xqqbmr">Bayesian Precision Posterior</a></p><p>Recall is then the mirror image. Precision asked, “<em>among the images we predicted positive</em>, how many were right?”, conditioning on the TP + FP pool. Recall asks, “<em>among the images that truly are positive</em>, how many did we catch?”, conditioning instead on the TP + FN pool. The posterior then follows naturally by the same Beta-conjugacy argument:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IrQq2ioAFu6FzeWMVgVYAg.png" /></figure><p>So both metrics share the same machinery, a Beta posterior driven by two counts, differing only in <em>which</em> pool the true positives are measured against: predicted-positives (TP+FP) for precision, actual-positives (TP+FN) for recall.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e994de21de9b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/heuritech/should-we-ship-this-model-a-bayesian-look-at-precision-and-recall-and-how-to-turn-it-into-actions-e994de21de9b">Should We Ship This Model? A Bayesian look at precision and recall, and how to turn it into actions</a> was originally published in <a href="https://medium.com/heuritech">Heuritech, a Luxurynsight Company</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Stop Guessing: A Systematic Methodology for Tuning Deep Learning Models]]></title>
            <link>https://medium.com/heuritech/stop-guessing-a-systematic-methodology-for-tuning-deep-learning-models-b3ea18e7e7c6?source=rss----8fc6104db0e8---4</link>
            <guid isPermaLink="false">https://medium.com/p/b3ea18e7e7c6</guid>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[dinov3]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[hyperparameter-tuning]]></category>
            <category><![CDATA[fine-tuning]]></category>
            <dc:creator><![CDATA[Louis Develle]]></dc:creator>
            <pubDate>Wed, 27 May 2026 16:32:36 GMT</pubDate>
            <atom:updated>2026-05-31T22:52:01.404Z</atom:updated>
            <content:encoded><![CDATA[<p><em>Turning Hyperparameter tuning from art into science, and beating our baseline by an average of 4.6% across 13 production tasks.</em></p><p>You’ve run <strong>47 hyperparameter sweeps</strong>. Each one takes 6 hours on 4 GPUs. Your validation metric has improved by <strong>0.4% in two weeks, </strong>and it may have been a lucky run.</p><p>Your experiment tracker has a graveyard of rejected ideas:</p><ul><li>Cosine annealing: <strong>no improvement</strong>.</li><li>Weight decay: <strong>hurts performance</strong>.</li><li>Muon: <strong>unstable</strong>.</li></ul><p>But you tested cosine annealing with a learning rate tuned for a constant schedule. You tested weight decay on SGD but never tried it with Adam. You tested Muon with Adam’s learning rate range. None of those ideas were bad. The method was, and most of them probably would have worked given a fair shot.</p><p>This article shows you how to give them one. You’ll learn how to separate the parameters you’re studying from the ones you need to control, how to explore search spaces efficiently with quasi-random sampling, and how to sequence your experiments so each round builds on the last instead of invalidating it.</p><p>This methodology draws on my years of experience — directing research teams at 42 AI’s research lab, and teaching at Paris 1 Sorbonne and Amsterdam Tech University — as well as sources I’ll link throughout, particularly the Google Deep Learning Tuning Playbook [1] and Goodfellow et al.’s debugging strategies [1b].</p><p>One piece of context before we dive in: this work was part of migrating our production image classifiers from TensorFlow to PyTorch. Our TensorFlow baseline was a formidable target: it encodes a decade of accumulated knowledge from researchers and engineers, some of whom are now at Mistral and DeepMind. So “beating the baseline” meant out-tuning years of refinement with a PyTorch stack built from the ground up. Across our 13 production tasks, this methodology did exactly that, with an average gain of 4.6%.</p><h3>In This Article</h3><ol><li><strong>Heuritech</strong>:<br>The company behind this work</li><li><strong>The Problem With Ad-Hoc Tuning: <br></strong>Why sequential one-at-a-time tuning produces biased conclusions</li><li><strong>Scientific vs. Nuisance Parameters</strong>:<br>The key insight that makes fair comparisons possible</li><li><strong>Beyond Grid Search: Quasi-Random Sampling</strong>:<br>Sobol sequences, and why not Optuna (yet)</li><li><strong>Foundations Before Tuning</strong>: <br>Metric, batch size, and compute budget</li><li><strong>The Ordering Rationale</strong>:<br>Why architecture → optimizer → scheduler → regularization</li><li><strong>The Iterative Loop</strong>:<br>Four phases of compounding gains on 13 production tasks</li><li><strong>The 5-Phase Experiment Workflow:<br></strong>From research question to reproducible results</li><li><strong>Results: From Matching TensorFlow to Beating It</strong>:<br>+4.6% average, up to +14.5% on individual tasks</li><li><strong>Making It Your Own</strong>:<br>The distilled framework</li></ol><h3>Heuritech</h3><p>A word about the system this work lives in:</p><p><a href="https://heuritech.com/">Heuritech</a>’s computer vision pipeline processes over 1.5 billion images sourced from 16 markets (US, Europe, Japan, and beyond) to help fashion &amp; sportswear brands forecast demand more accurately and reduce overproduction.</p><p>The AI stack runs deep: object detection models identify garments in the wild, a dozen image classifiers label their attributes (shoe type, fabric, silhouette…), and from these visual signals we extract over 2,000 individual trends that get combined combinatorially (red × skirt × midi length) and mapped across geographies to produce more than 200,000 time series that we forecast into the future using advanced ensembling methods. We serve inference through Triton for production-grade throughput, use VLMs for specialized detections where traditional classifiers fall short, and run active learning pipelines to target our annotation budget (500K to 1M newly labeled images per month) where it matters most.</p><p>This article focuses specifically on one piece of that system: retraining our image classifiers, the dozen models that turn raw detections into the attribute labels everything downstream depends on.</p><p>For context on the rest of the pipeline, the team has written extensively across both sides of the stack:</p><p><strong>On the vision side</strong> — directly upstream of this article — <a href="https://www.linkedin.com/in/paulmorelurl/">Paul Morel</a>’s <a href="https://medium.com/heuritech/a-social-media-image-is-worth-a-thousand-fashion-labels-72423e472587">A social media image is worth a thousand fashion labels…</a> walks through how we extract fashion attributes from social media images using deep learning, using metal-studs jackets as a worked example.</p><p><strong>On the forecasting side</strong> — what happens downstream once these labels feed the time series — <a href="https://www.linkedin.com/in/etienne-david-896777171/">Etienne David</a>’s three-part series:</p><ol><li><a href="https://medium.com/heuritech/is-fashion-predictable-9894d0861f1e">Is fashion predictable?</a> — the foundation: translating fashion dynamics into measurable time series.</li><li><a href="https://medium.com/heuritech/is-fashion-predictable-part-2-e66fd321d363">Is Fashion Predictable? From Basic to Accurate Forecasting Models</a> — applying statistical and deep learning forecasting models, with code.</li><li><a href="https://medium.com/heuritech/is-fashion-predictable-the-rise-of-foundation-models-44c7d12cd0ba">Is Fashion Predictable? The Rise of Foundation Models</a> — evaluating time series foundation models from Amazon, Microsoft, and IBM on fashion forecasting.</li></ol><h3>The Problem With Ad-Hoc Tuning</h3><p>Most hyperparameter tuning in practice looks like this:</p><p>1. Pick a parameter (usually learning rate)<br>2. Try a few values<br>3. Pick the best one<br>4. Move to the next parameter<br>5. Repeat until deadline</p><p>This approach has four fatal flaws:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ln8ccFphVC0MrHNeFPZ9OA.png" /></figure><p><strong>Confounded comparisons:</strong> Hyperparameters interact.<br>When you compare lr=1e-3 vs lr=1e-4 with weight decay (wd) fixed at wd=1e-5, you’re not comparing learning rates, you’re comparing:</p><ul><li>“lr=1e-3 with appropriate weight decay”</li><li>“lr=1e-4 with the wrong weight decay.”</li></ul><p>Each learning rate has its own optimal weight decay. A fair comparison requires tuning the parameters separately for each.</p><p><strong>Incomplete exploration.</strong> Finding a good run isn’t enough, you need to find where performance <em>degrades</em>. <br>If your best result sits at the edge of your search range, you haven’t found the optimum; you’ve found the boundary of where you looked. Keep expanding until the best value is surrounded by worse ones on all sides.</p><p><strong>Biased conclusions</strong>. If augmentation A gets 30 experiments and augmentation B gets 10, A may win simply because it was searched more thoroughly. Worse: if A’s sub-parameters are well-tuned but B’s aren’t, you’ll conclude A is better, when B might win with equal tuning budget. Fair comparison demands equal search effort across the options you’re evaluating.</p><p><strong>Wasted compute</strong>. Grid search tests every combination, including those in unproductive regions. Random search is better but still inefficient.</p><h3>Scientific vs. Nuisance Parameters: The Key Insight</h3><p>The single most important concept in systematic tuning is the distinction between <strong>scientific</strong> and <strong>nuisance</strong> parameters.</p><p><strong>Scientific parameters</strong> are what you’re trying to measure. They answer your research question directly. <br>Example: “What optimizer works best?” → The scientific parameter is optimizer and could take values sgd, adam, adamw and muon.</p><p><strong>Nuisance parameters</strong> must be tuned <em>per scientific parameter value</em> to ensure a fair comparison. When comparing optimizer types, the learning rate is one of the nuisance parameters: different optimizers need different optimal learning rates. If you hold it constant, you might not be fairly evaluating the optimizer types.</p><p>Critically, nuisance parameters <strong>don’t have to be the same</strong> across scientific parameter values. When comparing SGD vs Adam, SGD’s nuisance parameter is learning rate (range 1e-3 to 1e-1), while Adam’s nuisance parameters are learning_rate (range 1e-5 to 1e-3) <strong><em>and</em></strong> beta1 (range 0.8 to 0.99). Each scientific value gets its own nuisance search space, tailored to what makes sense for that option. This is what makes the comparison fair.</p><p>The same applies to scheduler comparison: a constant learning rate has no nuisance parameters beyond LR itself, while cosine annealing has warmup epochs, restart multiplier, and decay length — all nuisance parameters that must be tuned to give cosine annealing a fair shot.</p><p><strong>Fixed parameters</strong> are everything else, held constant to reduce the search space.</p><h4>The Common Mistake</h4><p>An easy mistake is to confuse nuisance parameters with scientific ones. <br>Here’s a real example. Suppose your research question is: <strong>“Which optimizer achieves the best validation metric: Muon or Adam?”</strong></p><p>That question already tells you everything about the parameter classification, but in practice an easy mistake is to reach for the parameter suspected to have the most impact and place it as scientific:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VtzXjFazytyey_-WnHF6Kw.png" /></figure><p>In this setup, you’re treating a sub-parameter as the thing under study, and burying the actual decision — which optimizer? — as something to hold constant. The right setup flips this: the optimizer <em>type</em> is what you’re measuring, and each option gets its own nuisance search space.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*n7NZbYxfwwjEWIuCfJosdw.png" /></figure><p>Notice that the nuisance spaces are not just different values : they’re <strong>different parameters entirely</strong>. Muon doesn’t have a beta1, Adam doesn&#39;t have ns_steps.</p><p>Each optimizer gets tuned on its own terms:</p><ul><li><strong>Muon:</strong> <br>learning_rate ∈ <strong>[1e-3, 1e-1]</strong> ← search space is not shared<br>ns_steps ∈ [3, 10]<br>momentum ∈ [0.8, 0.95]</li><li><strong>Adam:<br></strong> learning_rate ∈ <strong>[1e-5, 1e-3]</strong> ← search space is not shared<br>beta1 ∈ [0.8, 0.99]<br>epsilon ∈ [1e-9, 1e-7]</li></ul><p><em>Notice that even for nuisance parameters sharing the same name, their search spaces do not have to be shared across scientific parameters.</em></p><p>Now, the instinct to study learning rate isn’t <em>wrong: </em>it’s <em>premature</em>. Learning rate is one of the highest-impact continuous hyperparameters, and wanting to understand it deeply is exactly the right reflex. But the sequential logic matters: first, settle the optimizer choice (where LR is a nuisance parameter that must be tuned per optimizer to ensure a fair comparison). Then, once the optimizer is locked, that same instinct to study learning rate becomes the <strong>next scientific question</strong> : you’re now comparing LR schedules, warmup strategies, and decay shapes. The parameter is promoted from nuisance to scientific, in the right order.</p><p>This distinction seems pedantic until you realize it prevents the most common source of bias in ML experiments: <em>unfairly comparing a well-tuned option against a poorly-tuned one.</em></p><h3>Beyond Grid Search: Quasi-Random Sampling</h3><p>Once you’ve defined your search space, how do you explore it efficiently?</p><p>To build intuition, consider a simple two-dimensional example: tuning two hyperparameters with a budget of just 16 experiments.</p><ul><li>One parameter has a high impact on our metric of interest (<a href="https://en.wikipedia.org/wiki/F-score">F1-score</a> in this example): a narrow optimal region that’s easy to miss.</li><li>The other has low impact : it matters, but not nearly as much.</li></ul><p><strong>Grid search</strong> places experiments on a rigid lattice. With 16 trials, you get a 4×4 grid, <strong>only 4 unique values per dimension</strong>. If the optimal region falls between two grid lines, every single experiment misses it. The heatmap tells the story: the grid’s best configuration scores 0.13, completely blind to the peak.</p><figure><img alt="Grid sampling: 16 points on a rigid 4×4 lattice, best = 0.13 — the grid straddles the optimum without ever hitting it" src="https://cdn-images-1.medium.com/max/1024/1*aV2_p0_q1nF4Uluc-zPEKQ.png" /></figure><p><strong>Random search</strong> breaks free from the lattice. <em>Bergstra and Bengio (2012)</em> showed that random search is more efficient than grid search precisely because it samples each dimension independently [2]. With 16 random trials, you get <strong>16 unique values per dimension</strong> instead of 4. But randomness comes with a cost: clusters and gaps. Some regions get over-sampled while others are ignored entirely. Here, a lucky draw lands near the peak — best = 0.48, but coverage is uneven, and another random seed might miss it entirely.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cS18p1cwzbvjFYXw2CNYwQ.png" /></figure><p><strong>Quasi-random sampling</strong> (Halton/Sobol sequences) combines the best of both worlds: the structural coverage of a grid with the dimensional independence of random search [3a]. Sobol sequences are designed to fill the space as uniformly as possible, <strong>no clusters, no gaps</strong>. Every new point is placed to maximally reduce the largest remaining hole in the coverage. The result: best = 0.51, with points distributed evenly across the entire space.</p><figure><img alt="Quasi-random (Sobol) sampling: 16 points with uniform coverage, best = 0.51 — consistent, unbiased exploration" src="https://cdn-images-1.medium.com/max/1024/1*D6dHaZ8r40QrTlGwDG-L3Q.png" /></figure><p>The marginal F1 plots on each figure make the mechanism visible. Look at the dots projected onto the high-impact parameter curve (top):</p><ul><li>Grid search gives you only 4 probes, none near the peak.</li><li>Random search gives you 16, but they cluster on the left.</li><li>Sobol gives you 16 evenly spaced probes, guaranteeing that at least one lands close to any narrow optimum.</li></ul><h4>Where It Really Matters: Higher Dimensions</h4><p>The two-dimensional case is illustrative. The real payoff comes in higher dimensions.</p><p>In a 5-dimensional search with a grid of 5 values per dimension, you need <strong>3,125 trials</strong>, but each dimension still only sees <strong>5 unique values</strong>. That’s 3,125 experiments to test the same 5 learning rates. <em>80% of your compute is spent re-confirming what the low-impact dimensions do.</em></p><p>Random search with 30 trials gives you 30 unique values per dimension : <strong>6× better coverage</strong> than the 3,125-point grid, <strong>at less than 1% of the cost</strong>.</p><p>Halton and Sobol sequences with 30 trials give you 30 unique values <em>with guaranteed uniformity</em>, <strong>no clusters, no gaps</strong>, reducing lucky-seed dependence. As dimensionality grows, the advantage of quasi-random over both grid and random search compounds dramatically.</p><p>Both SciPy’s Sobol and Halton samplers work the same way: generate uniform points in [0, 1], then scale to your parameter ranges. Here’s a minimal Sobol example with log-scaled learning rate and a categorical optimizer:</p><pre>from scipy.stats.qmc import Sobol<br>import numpy as np<br><br>sampler = Sobol(d=2, scramble=True)<br>points = sampler.random(n=32)  # Sobol works best with powers of 2<br><br>lr = 10 ** (np.log10(1e-5) + points[:, 0] * (np.log10(1e-2) - np.log10(1e-5)))<br>optimizer = np.array([&quot;sgd&quot;, &quot;adam&quot;, &quot;adamw&quot;])[<br>    (points[:, 1] * 3).astype(int).clip(max=2)<br>]<br># lr.shape = (32,)       → [2.1e-5, 7.4e-4, 3.1e-3, ...]<br># optimizer.shape = (32,) → [&quot;adam&quot;, &quot;sgd&quot;, &quot;adamw&quot;, ...]</pre><p>And the Halton equivalent, same interface, but accepts <strong>any sample size</strong> and is naturally extensible (add trials by continuing the index):</p><pre>from scipy.stats.qmc import Halton<br><br>sampler = Halton(d=2, scramble=True)<br>points = sampler.random(n=30)  # Halton: any n, not just powers of 2<br><br>lr = 10 ** (np.log10(1e-5) + points[:, 0] * (np.log10(1e-2) - np.log10(1e-5)))<br>optimizer = np.array([&quot;sgd&quot;, &quot;adam&quot;, &quot;adamw&quot;])[<br>    (points[:, 1] * 3).astype(int).clip(max=2)<br>]<br># lr.shape = (30,)       → [1.2e-3, 4.8e-5, 6.0e-4, ...]<br># optimizer.shape = (30,) → [&quot;sgd&quot;, &quot;adam&quot;, &quot;adamw&quot;, ...]</pre><p><strong>Sobol vs. Halton </strong>:</p><p>Sobol sequences (used above) have slightly better theoretical uniformity in high dimensions (measured by discrepancy [3d], how evenly points fill a space), but require power-of-2 sample sizes for optimal coverage.</p><p><a href="https://en.wikipedia.org/wiki/Sobol_sequence#/media/File:Sobol_sequence_2D.svg">Visual example of Sobol sampling, from Wikipedia</a>:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*T1JyEfXaSkkMxl1E.png" /></figure><p>Halton sequences accept any sample size and are naturally extensible (you can add trials by continuing the index sequence, and new points automatically fill gaps in the existing coverage; however, regions added by widening the search space afterwards remain less explored).</p><p><a href="https://en.wikipedia.org/wiki/Halton_sequence">Visual example of Halton sampling, from Wikipedia</a>:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*4S4N5fVa46wTjrtM.png" /></figure><p>Both are vastly superior to grid or random search. If you anticipate extending a running experiment (widening a search range, adding more trials), Halton is the more practical choice.</p><p><a href="https://en.wikipedia.org/wiki/Sobol_sequence#/media/File:Pseudorandom_sequence_2D.svg">Visual example of Random sampling, from Wikipedia</a>:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*7yvkDOLpY1gAFidI.png" /></figure><p><strong>How many trials?</strong> <br>As a rule of thumb: <strong>5–30 trials per scientific parameter value</strong>, depending on the number of nuisance dimensions and the type of hyperparameter.</p><ul><li>With 1–2 nuisance parameters, 5–10 trials suffice.</li><li>With 4–5, you need 20–30.</li><li>Avoid tuning <strong>more than 5 hyperparameters simultaneously</strong>, above that, the space is too large for a reasonable trial budget to cover meaningfully (unless you are GPU rich!).</li></ul><p><strong>The type of parameter greatly impacts the number of trials needed</strong>. Continuous numeric parameters require the fewest trials (e.g. learning rate), then discrete numeric parameters (e.g. batch size, number of layers), and finally categorical parameters are the most costly — they will exceed the recommendations above as soon as they can take more than a couple of values.</p><p>In practice, <strong>we keep most experiments to 2–4 nuisance dimensions</strong>, and we try to exclude categorical parameters (or to treat them as scientific ones in later rounds of optimization).</p><h4>Why Not Optuna or Hyperopt?</h4><p>A natural question: if we’re trying to find the best configuration efficiently, why not use Bayesian optimization tools like Optuna[3b] or Hyperopt[3c]? They’re designed for exactly this : they model the objective function (our error metric) and focus trials on the most promising regions of each of our hyperparameters.</p><p>That’s precisely the problem. <strong>We’re not just trying to find the best configuration (yet) we’re trying to understand the system to direct our compute resources.</strong></p><p>Bayesian optimizers tend to bias exploration toward the first good results they encounter. After a few trials, they build a surrogate model and start exploiting : concentrating new trials near the current best. This is efficient for finding a single optimum, but it leaves large regions of the search space unexplored. You can get a great configuration, but you learn almost nothing about <em>why</em> it’s great, or what else might work.</p><p>Quasi-random search doesn’t bias. Every region gets equal coverage, which means:</p><p><strong>You can run all trials in parallel.</strong> Sobol generates every configuration upfront, so you can launch them all simultaneously across available GPUs. Bayesian optimization needs completed results to update its surrogate before sampling the next trial; you’re either waiting between runs or batching blindly, losing the adaptive advantage that justified using it in the first place.</p><p><strong>You can distinguish high-impact from low-impact parameters.</strong> When all configurations near lr=1e-3 perform well regardless of weight decay, you know weight decay doesn&#39;t matter, and stop wasting time on it. Biased sampling makes this kind of sensitivity analysis unreliable.</p><p><strong>You can extend a search range without starting over.</strong> If your best learning rate sits at the boundary, you need to explore further. With Sobol, you extend the range and add trials; all previous results remain valid data points. A Bayesian surrogate model built for the old range doesn’t transfer cleanly.</p><p><strong>You can promote nuisance parameters to scientific ones.</strong> Sometimes you discover mid-experiment that a nuisance parameter actually matters. Because quasi-random search explored it uniformly, your existing data is already an unbiased sample of its effect. Bayesian optimization concentrated its exploration wherever the objective was high; you can’t draw fair conclusions about independent effects from biased coverage.</p><p><strong>You build transferable knowledge.</strong> “Adam’s optimal LR for DINOv3[4a] backbones is broadly 1e-4 to 1e-3” is reusable across tasks and projects. “Optuna found lr=3.7e-4” is not.</p><figure><img alt="Quasi-random vs Bayesian optimization: understanding the system vs finding a single optimum" src="https://cdn-images-1.medium.com/max/1024/1*HRyWpa2RFjeNVGOcKyxvGQ.png" /></figure><p>Bayesian optimization has its place: once you understand your system, it’s powerful for squeezing out the last few points. But starting with it means optimizing a system you don’t understand, and that’s how you end up with fragile configurations that break when anything changes.</p><p>One notable exception, is when using a quasi-random sampler (like Sobol or Halton) specifically — for example, Optuna’s QMCSampler [4b]</p><h4>Search Space Boundaries: A Critical Diagnostic</h4><p>One diagnostic that’s easily missed in practice: always make your search space large enough to include clearly bad configurations at the edges. You want to see performance degrading at both boundaries: that’s how you know the optimum is enclosed, not just clipped by where you stopped looking.</p><blockquote><strong>If your best configuration is at the boundary of your search space, you haven’t found the best configuration — you’ve found the edge of where you looked.</strong></blockquote><p>This sounds obvious, but it’s an easy mistake to make : setting a learning rate range of [1e-4, 1e-3] and finding the best result at 1e-3. Is 1e-3 optimal, or would 2e-3 be better? You can’t know without expanding the range. Design search spaces to include the bad runs on purpose: they’re not wasted compute — they’re confirmation that you’ve explored far enough.</p><p>Sources: <br>[2] Bergstra &amp; Bengio, 2012 (JMLR) : <a href="https://www.jmlr.org/papers/v13/bergstra12a.html">https://www.jmlr.org/papers/v13/bergstra12a.html</a><br>[3a] SciPy QMC Documentation : <a href="https://docs.scipy.org/doc/scipy/reference/stats.qmc.html">https://docs.scipy.org/doc/scipy/reference/stats.qmc.html</a><br>[3b] Optuna : <a href="https://github.com/optuna/optuna">https://github.com/optuna/optuna</a><br>[3c] HyperOpt : <a href="https://github.com/hyperopt/hyperopt">https://github.com/hyperopt/hyperopt</a><br>[3d] Discrepancy : <a href="https://en.wikipedia.org/wiki/Low-discrepancy_sequence">https://en.wikipedia.org/wiki/Low-discrepancy_sequence</a><br>[4a] DINOv3 : <a href="https://arxiv.org/abs/2508.10104">https://arxiv.org/abs/2508.10104</a><br>[4b] Optuna QMCS <a href="https://optuna.readthedocs.io/en/stable/reference/samplers/generated/optuna.samplers.QMCSampler.html">https://optuna.readthedocs.io/en/stable/reference/samplers/generated/optuna.samplers.QMCSampler.html</a></p><h3>Foundations Before Tuning</h3><p>Before running a single experiment, three decisions shape everything that follows.</p><h4>Know Your Compute Budget</h4><p>Your compute budget shapes your experimental design. With 4 GPUs and 6-hour runs, you get ~20 experiments per week, enough for 2–3 nuisance parameters per round, not 5. This constraint is precisely why sequential tuning works: you can’t search a 10-parameter space on a realistic budget, but you <em>can</em> search three 3-parameter spaces in sequence.</p><h4>Choose a Single-Number Metric</h4><p>Whenever it’s possible to optimize for a single metric, do it. <br>A single target simplifies every decision in the tuning process: you always know whether a configuration is better or worse.</p><p>When you have multiple optimization targets, experiments become much harder to exploit. You’ll frequently find that improving one metric degrades another, making comparisons blurry and conclusions uncertain. Many experiments end up with ambiguous results that are hard to act on. A single number cuts through that ambiguity.</p><p>Your metric will depend on your task, but the principle is the same: <strong>collapse your evaluation to one number</strong> whenever the problem allows it. It’s not always possible, but when it is, it transforms the tuning process.</p><h4>Set Batch Size First</h4><p>Set batch size before anything else. Batch size is primarily a hardware efficiency decision, not a model quality decision.</p><p><strong>Choose the largest batch size that maximizes GPU utilization.</strong> <br>The effect of batch size on optimization dynamics (larger batches → smoother gradients → potentially different optima) can almost always be compensated by adjusting the learning rate downstream. This means batch size doesn’t need to participate in the hyperparameter search — <strong>it’s a fixed precondition</strong>.</p><p>The notable exception: tasks where batch size has semantic meaning, such as contrastive learning, where the batch defines the ratio of negative samples. In those cases, batch size is a scientific parameter. For standard classification, it’s not.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*I0mGJ9IqF73Wp2_bmo2nmw.png" /></figure><h4><strong>The Ordering Rationale</strong></h4><p>The sequence in which you tune dimensions is not arbitrary : it’s chosen to minimize cascading retuning. The principle: <strong>tune the most globally impactful decisions first, and the most dependent decisions last.</strong></p><p>Why does this work? <em>Hutter et al. (ICML 2014)</em> showed through functional <a href="https://en.wikipedia.org/wiki/Analysis_of_variance">ANOVA</a> decomposition that even in high-dimensional HP spaces, most performance variance is explained by just a few parameters [4]. <em>Bergstra and Bengio (2012)</em> confirmed this with their effective dimensionality finding: for most tasks, only a small subset of hyperparameters truly matter, but <em>which</em> ones matter varies by task [2]. <em>Wang et al. (2025)</em> measured this directly on CNN image classification: architectural depth alone explained <strong>38.5%</strong> of performance variance, learning rate 22.8%, dropout 13.1%, batch size just 1.5% [5]. Their Grouped Sequential Optimization Strategy, tuning groups in decreasing importance order, achieved a <strong>32% reduction in total optimization time</strong> versus simultaneous search, with equivalent final accuracy.</p><p>The practical consequence is what we call <strong>cascading invalidation</strong>: changing a high-impact parameter shifts the optimal values of everything downstream, but not vice versa. Tuning in the right order means later decisions rarely invalidate earlier ones.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*a80TywfjUbDskiHpALcfGg.png" /></figure><p><strong>Architecture first.</strong> Architecture determines the entire function class, computational budget, and memory footprint. Changing the backbone invalidates optimizer settings, scheduler parameters, and regularization, everything downstream must be re-tuned. This is why <em>Wang et al.</em> found it explains the most variance: it’s the most <em>global</em> decision. Our approach: try the largest model that fits on your GPU for each architecture family you’re considering, then scale down if needed. This gives each family its best shot.</p><p><strong>Optimizer second.</strong> The optimal learning rate for SGD (typically 1e-2 to 1e-1) differs from Adam’s (typically 1e-4 to 1e-3) by <strong>several orders of magnitude</strong> [1]. As <em>the Google Tuning Playbook states</em>: switching optimizers after tuning the learning rate wastes all prior LR work, the learning rate is effectively a different parameter for each optimizer. Fix the optimizer early, and everything you build on top stays valid.</p><p><strong>Scheduler third.</strong> Scheduler parameters (warmup length, decay rate, restart multiplier) are tightly coupled to the optimizer and learning rate; they’re essentially a more granular tuning of the learning dynamics. <em>Karpathy’s advice</em> is emphatic: disable learning rate decay entirely until you’ve established the base learning rate, because the best schedule is sensitive to nearly every other optimization choice [6]. <em>The Google Playbook</em> recommends starting with a constant LR, then adding cosine or linear decay only once the base rate is locked [1].</p><p><strong>Regularization last.</strong> Three reasons:</p><ul><li>First, regularization addresses the gap between training and validation metrics — you can only meaningfully measure that gap once architecture, optimizer, and scheduler are stable. Tuning regularization earlier means optimizing against a moving target.</li><li>Second, large learning rates themselves act as implicit regularizers through optimization noise <em>(Smith, 2018)</em> [7]. The optimal dropout and weight decay values therefore <em>depend</em> on your learning rate: tune regularization before LR is set, and your results are misleading.</li><li>Third, <em>Hernandez-Garcia &amp; König (2018)</em> showed that data augmentation is robust to other HP changes, while weight decay and dropout are brittle, they can dramatically hurt performance if not carefully tuned in the context of the final configuration [8]. Regularization is the most dependent dimension, which is exactly why it comes last.</li></ul><p>One interaction deserves special mention: <strong>learning rate × weight decay</strong>. <em>Loshchilov &amp; Hutter (2019)</em> proved that L2 regularization and weight decay are <em>not equivalent</em> for Adam, which motivated AdamW [9]. More subtly, with BatchNorm layers, weight decay’s primary effect is modulating the <strong>effective learning rate</strong> rather than providing traditional regularization [10]. This means weight decay tuned before the learning rate is set will produce doubly misleading results, it’s partially an LR modifier masquerading as a regularizer.</p><p>Sources: <br>[1] <a href="https://github.com/google-research/tuning_playbook">Google Research Deep Learning Tuning Playbook</a> · <br>[2] <a href="https://www.jmlr.org/papers/v13/bergstra12a.html">Bergstra &amp; Bengio, 2012 (JMLR)</a> · <br>[4] <a href="http://proceedings.mlr.press/v32/hutter14.pdf">Hutter, Hoos &amp; Leyton-Brown, 2014 (ICML)</a> · <br>[5] <a href="https://arxiv.org/abs/2503.05106">Wang et al., 2025, Grouped Sequential Optimization Strategy (arXiv:2503.05106)</a> · <br>[6] <a href="http://karpathy.github.io/2019/04/25/recipe/">Karpathy, A Recipe for Training Neural Networks</a> · <br>[7] <a href="https://arxiv.org/abs/1803.09820">Smith, 2018, A Disciplined Approach to Neural Network Hyper-Parameters (arXiv:1803.09820)</a> · <br>[8] <a href="https://arxiv.org/abs/1806.03852">Hernandez-Garcia &amp; König, 2018 (arXiv:1806.03852)</a> · <br>[9] <a href="https://openreview.net/forum?id=Bkg6RiCqY7">Loshchilov &amp; Hutter, 2019, Decoupled Weight Decay Regularization (ICLR)</a> · <br>[10] <a href="https://arxiv.org/abs/1706.05350">van Laarhoven, 2017, L2 Regularization versus Batch and Weight Normalization (arXiv:1706.05350)</a></p><h3>The Iterative Loop: Building Systematically</h3><p>You can’t tune everything at once, the search space is too large. A 5-dimensional search with continuous ranges requires orders of magnitude more trials than a 2-dimensional one. The solution is sequential: <strong>fix one dimension, tune the next, build on previous results</strong>.</p><p>The rest of this article applies that principle to a concrete case: Heuritech’s image classification pipeline. Our computer vision stack detects garments in social media images, then classifies their attributes through a set of hierarchical classifiers : one model identifies the type of garment (jacket, dress, top…), others label its texture, silhouette, pattern, color, and finer attributes like neckline shape or sleeve length. These predictions combine to define the thousands of fashion trends we track and forecast.</p><p>In total, we retrained <strong>13 production classifiers</strong> spanning diverse visual tasks: outerwear type, dress type, shoe type, bag model, gender, brand logo, fabric, and more. Each task has different class distributions, visual complexity, and sensitivity to hyperparameters, which is precisely what makes them a good stress test for a general-purpose methodology.</p><p>One crucial design choice: We ran this entire progression on a <strong>single dataset, </strong>outerwear classification. The goal was never to find the best configuration for outerwear specifically. It was to find a <strong>general-purpose configuration</strong> that would work out of the box across all 13 production tasks, without any per-task tuning (our compute budget couldn’t afford tuning all 13 datasets directly). This is a much harder constraint, and it influenced decisions throughout. The other 12 datasets were held out entirely: the methodology was blind to them until final evaluation.</p><p>All results below are reported in <strong>p@r60</strong> (precision at 60% recall): the precision our classifier achieves when recall is held at 60%. We need a recall floor for coverage, and we optimize precision above that floor : a single number, following the principle described earlier in this article.</p><p>As a reference point: DINOv3-ViTS16 with default PyTorch training parameters scored <strong>0.650 p@r60</strong> on our outerwear test set. Every phase below builds from there.</p><p>We followed a 4-phase progression (after the batch size and metric foundations described above), each phase building on the previous one’s best configuration:</p><h4>Phase 1: Backbone Selection → p@r60 = 0.676</h4><p><strong>Scientific parameter</strong>: backbone architecture. <br><strong>Nuisance</strong>: learning rate. <br><strong>Fixed</strong>: constant scheduler, SGD optimizer, no regularization.</p><p><strong>Result</strong>: DINOv3-ViTS16 selected as the foundation. Starting metric on our outerwear classification task: 0.676 p@r60, by far the best option among all the tested architectures!</p><h4>Phase 2: Optimizer Choice → p@r60 = 0.692 (+1.6%)</h4><p><strong>Scientific parameter</strong>: optimizer (SGD, Adam, AdamW, Muon). <br><strong>Nuisance</strong>: learning rate, betas, momentum, with different ranges per optimizer. <br><strong>Fixed</strong>: DINOv3, constant scheduler, no regularization.</p><p><strong>Result</strong>: Four optimizers, four different stories:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WFNa0HfEhWjsYiFY0R0WoA.png" /></figure><p>A quick note on experiment counts: the number of trials per optimizer is proportional to its nuisance dimensions, following the guidelines from the quasi-random sampling section. SGD has one nuisance parameter (learning rate), so it got fewer trials. Adam has three (learning rate, beta1, epsilon), so it required more trials to cover its larger search space. This isn’t unequal effort — it’s <em>appropriately scaled</em> effort. Each optimizer gets the budget its search space demands.</p><p><strong>For SGD</strong>, we ran 4 experiments because we only had one nuisance parameter. SGD achieved the highest single-configuration score, but it had a very narrow optimal region, the peak was sharp and easy to miss:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qqr5VUvGZtdslfhmD_6k9A.png" /></figure><p><strong>Adam</strong> had more nuisance parameters to tune, so 15 experiments were needed. It scored lower but had a broad, flat optimal region of good learning rates:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2uemjQ3bA1_ChcEO8geWow.png" /></figure><p>Since we needed a single configuration that works across 13 classification tasks (shoe type, bag model, dress type, gender, etc.), <strong>Adam’s robustness mattered more than SGD’s peak performance</strong>. A configuration that’s 2% worse but works across all tasks beats one that’s 2% better on one task but fails on others.</p><p>Adam sensitivity analysis:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1n7G2ZDLCnLBPBJMyVgmsQ.png" /></figure><p><strong>Recommended</strong>: Adam with lr=5e-4, beta1=0.86, epsilon=1e-3, beta2=0.999.</p><h4>Phase 3: Scheduler Choice → p@r60 = 0.722 (+3.0%)</h4><p><strong>Scientific parameter</strong>: scheduler type (constant, linear decay, cosine annealing). <br><strong>Nuisance</strong>: scheduler-specific parameters — constant LR has just the learning rate, while cosine annealing has warmup epochs, restart multiplier, decay length, and more. <br>With so many nuisance parameters, we increased the number of experiments to 30.<br><strong>Fixed</strong>: DINOv3, Adam.</p><p><strong>Result</strong>: Cosine annealing was the clear winner at 0.722 vs. constant LR at 0.699. The gain was not free, it required more epochs (training went from optimal at epoch 2–3 to optimal at epoch 10–20). But 3% relative improvement justified the additional compute (internally we mostly care about inference-time compute).</p><p>The first round of cosine experiments revealed an important diagnostic: the best configurations clustered at the boundary of our search space (especially for learning_rate), meaning we hadn’t explored far enough:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lEV7wBdte35EEPuYV60iBw.png" /></figure><p>After extending the search space and doing our 30 experiments, we had a clearer picture, though the full scatter is dense. Filtering to the top 8 runs (&gt;25% of our 30 experiments) makes the sweet-spot regions visible :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Khn4E_oFfE2oMxERs3TjZw.png" /></figure><p>Recommended scheduler: <strong>Cosine Annealing</strong> with:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/844/1*VGQBXho7iU-DA459A8H2cQ.png" /></figure><h4>Phase 4: Regularization → p@r60 = 0.727 (+0.5%)</h4><p><strong>Scientific parameter</strong>: regularization strategy. <br><strong>Nuisance</strong>: dropout, weight decay, image size. <br><strong>Fixed</strong>: DINOv3, Adam, cosine annealing.</p><p><strong>Result</strong>: Data augmentation did not improve results for our tasks — the sweet spot was simply dropout=0.10, image_size=224, weight_decay=0. The key takeaway: <strong>not every addition of complexity helps.</strong> Regularization should be validated, not assumed.</p><p>Regularization comes last for a reason: it addresses the gap between training and validation metrics. You can only meaningfully measure and reduce that gap once everything else — architecture, optimizer, scheduler — is stable. Tuning regularization earlier would mean optimizing against a moving target.</p><h4>The Compound Effect</h4><p>Each phase’s improvement was modest individually: +1.5%, +3%, +0.5%. But <strong>they compounded</strong>:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1oPWTVUH7CGHa7NeTPN74w.png" /></figure><p>And that was just outerwear. On other tasks, the gains were larger: up to +14.5% on dress type classification.</p><h3>The 5-Phase Experiment Workflow</h3><p>The methodology above tells you <em>what</em> to tune. But in practice, even well-designed experiments fail: wrong YAML configs, unlogged parameters, GPU crashes wasting hours of compute. We developed a 5-phase workflow to make experiments reliable:</p><figure><img alt="The 5-phase experiment workflow: design, generate, verify, document, launch" src="https://cdn-images-1.medium.com/max/1024/1*C2E0GoBMkib4xdcM7zkt_g.png" /></figure><h4>Phase 1: Collaborative Design</h4><p>Start with a research question: “Does label smoothing improve DINOv3 accuracy?” Define the scientific parameter (label_smoothing, range 0.0–0.2), nuisance parameters (dropout, data augmentation), and fixed parameters (everything else). Research the literature for informed range choices.</p><h4>Phase 2: Configuration Generation</h4><p>A generation script creates all experiment configurations using quasi-random sampling. Critically, it also generates a <strong>TEST configuration</strong>: a single config with max_epochs=3, limit_train_batches=10, designed to validate the setup in minutes rather than hours.</p><h4>Phase 3: Pre-Launch Verification</h4><p>Before burning any real compute:</p><p>1. <strong>Verify hyperparameter logging:</strong> Run a verification script against the TEST config to confirm all scientific and nuisance parameters will appear in your experiment tracker. We use <a href="https://www.tensorflow.org/tensorboard">TensorBoard</a>’s hparams tab: it logs every hyperparameter alongside training metrics, making post-experiment analysis possible. If a parameter isn’t logged, you can’t analyze it.</p><p>2. <strong>Verify code state: </strong>git status and git log to ensure you’re running committed code. Nothing is worse than discovering a great result came from uncommitted changes you can’t reproduce.</p><p>3. <strong>Run the TEST config</strong>: Launch the TEST yaml on a single GPU. This catches YAML syntax errors, missing dataset paths, shape mismatches, and configuration bugs. Catching these before launching 30 full experiments saves days.</p><figure><img alt="Pre-launch verification gates: hparam logging, code state, and TEST run" src="https://cdn-images-1.medium.com/max/1024/1*OTx-CfWFSNNfsXVet8yHDg.png" /></figure><h4>Phase 4: Documentation</h4><p>Write the experiment hypothesis <strong>before</strong> seeing results. This prevents post-hoc rationalization, the tendency to explain whatever result you got as if you expected it.</p><p>Our experiment documentation template includes:</p><ul><li>Objective (the research question)</li><li>Hypothesis (what we expect and why)</li><li>Configuration (dataset, model, metric, trial count)</li><li>Parameter tables (scientific, nuisance, fixed — with ranges and rationale)</li></ul><h4>Phase 5: Launch and Monitor</h4><p>After TEST validation passes, launch the full experiment. Distribute across available GPUs, monitor training curves for early divergence, and document results while they’re fresh.</p><p>The discipline of this workflow is what makes systematic tuning practical. Without it, the friction of running rigorous experiments pushes teams back toward ad-hoc tuning.</p><h3>The Results: From Matching TensorFlow to Beating It</h3><p>After applying this methodology across our full production workload, here are the results. Each task is a different image classification problem evaluated on precision-at-recall-60.</p><p>The TF Baseline column is <em>not</em> default TensorFlow, it’s <strong>the best TensorFlow configuration our team had refined over years of production use</strong>, based on an <a href="https://arxiv.org/pdf/1610.02357">Xception backbone</a>. This is the bar we needed to clear:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*S821FrarHJGzOUjpTmMmzA.png" /></figure><p>A few things to note:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oO8CDahuHRWR1JNtqMeK1A.png" /></figure><p><strong>Not every task improved :</strong> Brand logo and shoe type showed regressions of -2.9% and -1.8%. This is expected: the entire methodology was tuned on a single dataset and applied blindly to 12 others. <br>The fact that 11 out of 13 tasks improved (with an average gain of +4.6%) validates the general-purpose approach. But the two regressions point to the natural next step: now that we have well-characterized search spaces and a solid baseline configuration, we can run <strong>task-specific optimization</strong> on the underperforming tasks. <br>Data augmentation — which didn’t help on outerwear — may matter for brand logos, which have fundamentally different visual patterns. And this is precisely where Bayesian optimization earns its place: the exploration phase is done, the search spaces are mapped, and tools like Optuna can now squeeze out per-task gains within those spaces without risk of optimizing blindly.</p><p><strong>Remember the starting point</strong>. On gender classification, our TensorFlow baseline (Xception backbone, refined over years) scored 82.5%. A naive PyTorch port with the same Xception architecture and default parameters scored 70.5% — a 12pp gap that made the migration look like a regression.</p><p>The final result — 91.0% — came from two compounding improvements: switching to a DINOv3 backbone (the architecture phase), and systematically tuning the training configuration (the methodology phases). Neither alone would have gotten there. The architecture gave us a better starting point; the methodology ensured we actually found its optimal operating point.</p><p>This is the broader lesson: an architecture upgrade without proper tuning leaves performance on the table, and tuning without the right architecture has a lower ceiling. The methodology’s value is making sure you reach whatever ceiling your architecture allows.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BDa1AAyURZY8EKHdI9vrfg.png" /></figure><p>A telling sign of how unexpected these results were: when first presented, the team suspected a measurement error. The improvements, particularly the 10pp jump on gender classification, seemed too large to be real. This is exactly why the phased verification methodology matters: every result was traceable to a documented experiment with logged hyperparameters, committed code, and reproducible configurations. <em>The skepticism was healthy; the evidence was airtight.</em></p><h3>Making It Your Own</h3><p>This methodology is framework-agnostic. The same principles apply whether you’re tuning PyTorch, TensorFlow, JAX, or anything else, and whether you’re recovering from a migration or starting from scratch.</p><p>Here’s the distilled framework:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uW1TcqB-qpX7uV95LkWbaA.png" /></figure><p>The tools we built (Halton sequence generators, YAML configuration scripts, hyperparameter verification scripts, experiment documentation templates) are not complex, and the heavy lifting still runs on standard PyTorch. The value isn’t in the tools, it’s in the discipline of using them consistently.</p><p>Sources: <br>[1] Google Research Deep Learning Tuning Playbook :https://github.com/google-research/tuning_playbook<br>[1b] Goodfellow, Bengio &amp; Courville, Deep Learning, Ch. 11.5: Debugging Strategies : https://www.deeplearningbook.org/</p><h3>The Bottom Line</h3><p>An experienced engineer’s intuition about learning rate might be right 80% of the time. But across 6 hyperparameters, 4 architectural choices, and 13 classification tasks, that 80% accuracy compounds to less than a coin flip. Systematic methodology beats intuition not because intuition is wrong, but because <strong>the investment in systematic methodology delivers compounding interest after each new experiment</strong>.</p><p>This approach gave us an average +4.6% over configurations our team had refined for years, not from a single insight, but from the compound effect of many small, rigorous, well-validated improvements. The two tasks that regressed (−2.9% on brand logos, −1.8% on shoe type) point to the natural next step: now that search spaces are mapped, Bayesian optimization can squeeze out per-task gains where the general-purpose config falls short.</p><p>Now it’s your turn to share: what’s your tuning methodology?</p><p>I’m particularly curious whether you’ve found techniques that transfer reliably across diverse tasks, the interaction between optimizer choice and task characteristics is something we’re still investigating.</p><p><em>Louis Develle is an ML Research Engineer at Heuritech, where he led the TensorFlow-to-PyTorch migration and designed the systematic tuning methodology described in this series.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b3ea18e7e7c6" width="1" height="1" alt=""><hr><p><a href="https://medium.com/heuritech/stop-guessing-a-systematic-methodology-for-tuning-deep-learning-models-b3ea18e7e7c6">Stop Guessing: A Systematic Methodology for Tuning Deep Learning Models</a> was originally published in <a href="https://medium.com/heuritech">Heuritech, a Luxurynsight Company</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Is Fashion Predictable? The Rise of Foundation Models]]></title>
            <link>https://medium.com/heuritech/is-fashion-predictable-the-rise-of-foundation-models-44c7d12cd0ba?source=rss----8fc6104db0e8---4</link>
            <guid isPermaLink="false">https://medium.com/p/44c7d12cd0ba</guid>
            <category><![CDATA[foundation-models]]></category>
            <category><![CDATA[fashion]]></category>
            <category><![CDATA[time-series-forecasting]]></category>
            <dc:creator><![CDATA[Etienne David]]></dc:creator>
            <pubDate>Fri, 09 Jan 2026 08:35:55 GMT</pubDate>
            <atom:updated>2026-01-09T08:35:54.686Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="Generate with Dall-E 3" src="https://cdn-images-1.medium.com/max/1024/1*4ZFLkGVbShf-QbLfSDvtFw.png" /><figcaption>Generated with Dall-E 3</figcaption></figure><p>Welcome back everyone, I am Etienne David, a research engineer at Heuritech. Today, I would like to share a recent development in time series forecasting that has attracted significant attention in the research community: <strong>time series forecasting foundation models</strong>. In this article, we will start by explaining what a foundation model is. Then, we will review five foundation models recently released by major players in the field, such as Amazon, Microsoft, and IBM. Finally, as this is central to our work at Heuritech, we will evaluate how these new approaches perform on fashion forecasting tasks.</p><p>If you have not read them yet, I highly recommend taking a look at our two previous articles on fashion time series forecasting, they cover all the background needed for this article <em>(</em><a href="https://medium.com/heuritech/is-fashion-predictable-9894d0861f1e"><em>Is Fashion Predictable?</em></a><em>, </em><a href="https://medium.com/heuritech/is-fashion-predictable-part-2-e66fd321d363"><em>Is Fashion Predictable ? From Basic to Accurate Forecasting Models</em></a><em>)</em>. And as always, if you would like to reproduce the results and figures shown here, we have released all the code and materials in a <a href="https://github.com/etidav/is_fashion_predictable_foundation_models"><strong>public github repository</strong></a><strong>.</strong></p><h3>1) Foundation models for time series forecasting.</h3><p>A foundation model is a large machine learning model trained on massive amounts of data, designed to serve as a general-purpose model that can be adapted to a wide range of downstream tasks. The best-known examples come from text generation, with large language models such as ChatGPT from OpenAI, Claude from Anthropic, or Le Chat by Mistral. Trained on large-scale text data drawn from the internet, these models can now understand natural language and answer questions ranging from simple to complex with striking accuracy. It was only a matter of time before researchers began adapting foundation models to other domains, including time series forecasting.</p><p>Over the past few years, several companies have released foundation models specifically designed for generic time series forecasting. We list below some of them:</p><ul><li><strong>Chronos 2: </strong>An encoder-only Transformer-based foundation model from <strong>Amazon</strong> with 120 million parameters, released on 17 October 2025. <em>(</em><a href="https://arxiv.org/pdf/2510.15821"><em>Paper</em></a><em>, </em><a href="https://huggingface.co/amazon/chronos-2"><em>Weights</em></a><em>)</em></li><li><strong>TimesFM 2.5</strong>: <strong>Google’s</strong> decoder-only Transformer-based foundation model, released on 15 September 2025, trained on 200 million real and synthetic sequences. <em>(</em><a href="https://arxiv.org/pdf/2310.10688"><em>Paper</em></a><em>, </em><a href="https://huggingface.co/google/timesfm-2.5-200m-pytorch/discussions/4"><em>Weights</em></a><em>)</em></li><li><strong>Moirai 2:</strong> A lightweight decoder-only Transformer-based foundation model from <strong>Salesforce</strong>, released on 22 November 2025. It carries 11 million parameters and is pre-trained on 36 million real and synthetic time series. <em>(</em><a href="https://arxiv.org/pdf/2511.11698"><em>Paper</em></a><em>, </em><a href="https://huggingface.co/Salesforce/moirai-2.0-R-small"><em>Weights</em></a><em>)</em></li><li><strong>FlowState</strong>: IBM’s state-space–based encoder-decoder foundation model, released on 19 August 2025, packing 9.1 million parameters.<em> (</em><a href="https://arxiv.org/pdf/2508.05287"><em>Paper</em></a><em>, </em><a href="https://huggingface.co/ibm-research/flowstate"><em>Weights</em></a><em>)</em></li><li><strong>TireX</strong>: An xLSTM-based foundation model from NXAI, released on 2 November 2025, with 35 million parameters trained over 47.5 million real and synthetic sequences. <em>(</em><a href="https://arxiv.org/pdf/2505.23719"><em>Paper</em></a><em>, </em><a href="https://huggingface.co/NX-AI/TiRex"><em>Weights</em></a><em>)</em></li></ul><p>These foundation models are trained on vast sets of real and synthetic time series from diverse domains, such as retail, weather, and cloud infrastructure usage. The goal is to expose the models to as many examples as possible, enabling them to forecast new time series with high accuracy, regardless of forecasting horizon, seasonality, or noise. These approaches offer a major advantage: <strong>zero-shot forecasting</strong>. You no longer have to fit your own time series forecasting model. You can simply load a foundation model off the shelf and make predictions for any desired horizon. The only price to pay is size: some foundation models are huge, with hundreds of millions of parameters, and need a GPU to compute predictions efficiently.</p><p>But a key question remains: <strong>how accurate are these models?</strong> Let’s find out.</p><h3>2) A Complete Code Base</h3><p>Before testing the foundation models, we first introduce some code that makes it easy to experiment with the five models presented above. The complete code base is available at the <strong>following</strong> <a href="https://github.com/etidav/is_fashion_predictable_foundation_models"><strong>link</strong></a>. Using these models is straightforward. Apart from one or two exceptions, they all work in a similar way: a function to load the model weights from a Hugging Face repository, a predict function, and a save function for hosting the model’s weights. Several models also provide a fit function to fine-tune them and improve accuracy for specific use cases. We will come back to this later.</p><p>Below, we present the abstract class we defined to group the five foundation models. We also display the class implemented to wrap <strong>TimesFM 2.5</strong>, making it easy to use and experiment with. Note that in the init_model() method of the TimesfmForecastModel class, the model weights are loaded from the publicly released checkpoint available on <a href="https://huggingface.co/google/timesfm-2.5-200m-pytorch">Hugging Face</a>.</p><pre>import abc<br>import copy<br>import json<br>import os<br>from enum import Enum<br>from typing import Any, List<br><br>import numpy as np<br>import pandas as pd<br>from pydantic import BaseModel<br><br><br>from config import PREDICTION_ONE_YEAR, WEEK_FREQUENCY_TIMEINDEX<br>from timesfm import ForecastConfig, TimesFM_2p5_200M_torch<br><br>DEFAULT_MAX_CONTEXT = 256<br>DEFAULT_MAX_HORIZON = 256<br><br><br>class FoundationForecastModelType(str, Enum):<br>    chronos = &quot;chronos&quot;<br>    timesfm = &quot;timesfm&quot;<br>    moirai = &quot;moirai&quot;<br>    tirex = &quot;tirex&quot;<br>    flowstate = &quot;flowstate&quot;<br><br><br>class FoundationForecastModel(BaseModel, metaclass=abc.ABCMeta):<br>    &quot;&quot;&quot;<br>        Abstract class for foundation models.<br>    &quot;&quot;&quot;<br><br>    horizon: int = PREDICTION_ONE_YEAR<br>    model_type: FoundationForecastModelType = None<br>    model: Any = None<br>    model_args: List[str] = None<br><br>    class Config:<br>        arbitrary_types_allowed = True<br><br>    def __init__(self, **kwargs):<br>        super().__init__(**kwargs)<br>        if self.model_args is None:<br>            self.model_args = []<br>        if self.model is None:<br>            self.init_model()<br><br>    @abc.abstractmethod<br>    def init_model(self):<br>        pass<br><br>    @abc.abstractmethod<br>    def save_model(self, path: str):<br>        pass<br><br>    def save_model_args(self, path: str):<br><br>        model_args = {arg_name: getattr(self, arg_name) for arg_name in self.model_args}<br>        model_args_path = os.path.join(path, &quot;model_args.json&quot;)<br>        with open(model_args_path, &quot;w&quot;) as f:<br>            json.dump(model_args, f, indent=4)<br><br>    def format_predictions(<br>        self, predictions: np.ndarray, last_historical_index: pd.Timestamp,<br>        prediction_columns: List[str]<br>    ) -&gt; pd.DataFrame:<br>        predictions[predictions &lt; 0] = 0.<br>        predictions = predictions.astype(&#39;float64&#39;)<br>        predictions_index = pd.date_range(<br>            start=last_historical_index, periods=self.horizon + 1, freq=WEEK_FREQUENCY_TIMEINDEX<br>        )[1:]<br>        return pd.DataFrame(<br>            predictions,<br>            columns=prediction_columns,<br>            index=predictions_index,<br>        )<br><br>    @classmethod<br>    def from_saved_model(cls, path: str, **kwargs) -&gt; &quot;FoundationForecastModel&quot;:<br><br>        model_args_path = os.path.join(path, &quot;model_args.json&quot;)<br>        if os.path.isfile(model_args_path):<br>            with open(model_args_path) as f:<br>                model_args = json.load(f)<br>        else:<br>            model_args = {}<br><br>        if not os.path.isdir(path):<br>            raise ValueError(f&quot;No model saved at following directory path : {path}&quot;)<br><br>        return cls(<br>            model_path=path,<br>            **model_args,<br>            **kwargs,<br>        )<br><br><br>class TimesfmForecastModel(FoundationForecastModel):<br>    model_type: FoundationForecastModelType = FoundationForecastModelType.timesfm<br>    model_path: str = &quot;google/timesfm-2.5-200m-pytorch&quot;<br>    model: TimesFM_2p5_200M_torch = None<br><br>    zero_shot: bool = None<br>    max_context: int = None<br>    max_horizon: int = None<br>    normalize_inputs: bool = None<br>    force_flip_invariance: bool = True<br>    infer_is_positive: bool = True<br><br>    class Config:<br>        arbitrary_types_allowed = True<br><br>    def init_model(self):<br>        self.zero_shot = True if self.zero_shot is None else self.zero_shot<br>        self.max_context = DEFAULT_MAX_CONTEXT if self.max_context is None else self.max_context<br>        self.max_horizon = DEFAULT_MAX_HORIZON if self.max_horizon is None else self.max_horizon<br>        self.normalize_inputs = True if self.normalize_inputs is None else self.normalize_inputs<br>        self.force_flip_invariance = True if self.force_flip_invariance is None else self.force_flip_invariance<br>        self.infer_is_positive = True if self.infer_is_positive is None else self.infer_is_positive<br><br>        self.model_args = [<br>            &quot;zero_shot&quot;, &quot;max_context&quot;, &quot;max_horizon&quot;, &quot;normalize_inputs&quot;, &quot;force_flip_invariance&quot;,<br>            &quot;infer_is_positive&quot;<br>        ]<br><br>        self.model = TimesFM_2p5_200M_torch.from_pretrained(self.model_path, torch_compile=True)<br>        self.model.compile(<br>            ForecastConfig(<br>                max_context=self.max_context,<br>                max_horizon=self.max_horizon,<br>                normalize_inputs=self.normalize_inputs,<br>                force_flip_invariance=self.force_flip_invariance,<br>                infer_is_positive=self.infer_is_positive,<br>            )<br>        )<br><br>    def predict(self, historical_data: pd.DataFrame, time_index: str = None) -&gt; pd.DataFrame:<br><br>        if time_index is not None:<br>            historical_data = copy.deepcopy(historical_data)<br>            historical_data.date_split(time_index)<br><br>        y_pred_df, _ = self.model.forecast(horizon=self.horizon, inputs=historical_data.values.T)<br>        predictions = y_pred_df.T<br>        return self.format_predictions(<br>            predictions, historical_data.index[-1], historical_data.columns<br>        )<br><br>    def save_model(self, path: str):<br><br>        self.model.save_pretrained(save_directory=path)<br>        self.save_model_args(path)<br><br></pre><h3>3) Foundation models and fashion time series forecasting</h3><h4>3.1) Zero-shot forecasting</h4><p>Now that we have a functional code base, let’s assess the performance of the foundation models on a real-world fashion dataset introduced in our previous articles. This dataset contains 100 fashion time series, each representing the social media visibility of a sneaker type in the United States. We evaluate the five foundation models on a one-year forecasting task. The last year of each time series will be hidden, and zero-shot predictions will be generated using all five models.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mNk1KZ06wrwxp3DBUlUp6g.png" /><figcaption>Matte Leather Sneakers</figcaption></figure><p>Below is the portion of <a href="https://github.com/etidav/is_fashion_predictable_foundation_models">the code we released</a> that was used to generate <strong>zero-shot foundation model predictions</strong>. Once again, it is remarkably straightforward to work with them:</p><pre>import os<br><br>from model.foundation_model import (<br>    ChronosForecastModel, FlowStateForecastModel, FoundationForecastModelType, MoiraiForecastModel,<br>    TimesfmForecastModel, TirexForecastModel<br>)<br>from utils import (<br>    eval_predictions, load_forecast, load_time_series_csv, mean_errors_ranking, save_forecast<br>)<br><br># Load the fashion time series data and remove the last year of data<br>fashion_ts = load_time_series_csv(&quot;data/us_female_sneakers.csv&quot;)<br>fashion_ts = fashion_ts.loc[:&quot;2023-01-01&quot;]<br># Define foundations models<br>foundation_models = {<br>    FoundationForecastModelType.chronos.value: ChronosForecastModel(device_map=&#39;cpu&#39;),<br>    FoundationForecastModelType.timesfm.value: TimesfmForecastModel(),<br>    FoundationForecastModelType.moirai.value: MoiraiForecastModel(),<br>    FoundationForecastModelType.tirex.value: TirexForecastModel(),<br>    FoundationForecastModelType.flowstate.value: FlowStateForecastModel(device=&#39;cpu&#39;)<br>}<br># Generate zero-shot predictions.<br>models_forecasts = {<br>    model_name: model.predict(fashion_ts_train)<br>    for model_name, model in foundation_models.items()<br>}<br># Save forecasts<br>save_forecast(models_forecasts=models_forecasts, forecasts_dir=&quot;model_forecasts&quot;)</pre><p>Using the three error metrics introduced in our previous articles (<a href="https://en.wikipedia.org/wiki/Mean_absolute_scaled_error">MASE</a>, <a href="https://en.wikipedia.org/wiki/Mean_absolute_percentage_error">MAPE</a>, <a href="https://en.wikipedia.org/wiki/Symmetric_mean_absolute_percentage_error">SMAPE</a>), we evaluated the performance of the foundation models. Below, we show the average MAPE, SMAPE, and MASE across the 100 forecasts for each model:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PLl8hxXV3xO5JIUzQavjuw.png" /><figcaption>Accuracy of foundation models on the Sneakers dataset</figcaption></figure><p>TimesFM and Chronos achieve the best accuracy on the fashion forecasting use case, reaching the lowest values across all three metrics. TireX and FlowState are slightly less accurate but still show promising results. Only Moirai appears to underperform on this specific dataset. To put these results into perspective, the table below compares the foundation models with some of the best deep learning methods we tested in our previous article.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*P7H3OddURLksRYVtx3pgGQ.png" /><figcaption>Accuracy of deep learning and foundation models on the Sneakers dataset</figcaption></figure><p>One of the most striking findings is that foundation models like Chronos and TimesFM, even in a zero-shot setting, achieve performance comparable to deep learning models that were specifically trained on our fashion dataset. This demonstrates the remarkable ability of these models to generalise to new time series without any task-specific training.</p><p>The forecast examples below illustrate how these models capture both complex seasonal patterns and the overall trends of the fashion items.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xawQcRUc_NQlKWQzKMfYOg.png" /><figcaption>Matte Leather Sneakers</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Aqv1r__1U2ScMwZxdWFObg.png" /><figcaption>Chunky Sneakers</figcaption></figure><h4>3.2) Fine-tuning a foundation model</h4><p>In section 2, we mentioned that foundation models can also be fine-tuned to enhance their accuracy on a specific use case. Thus, to assess the maximum performance of the Chronos model, we fine-tuned it on our dataset of sneaker time series. We show its accuracy results below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AePj4WdjjRL7yxKQA6HyOQ.png" /><figcaption>Accuracy of Chronos models, before and after fine-tuning, on the Sneakers dataset</figcaption></figure><p>The results of Chronos after being fine-tuned on our dataset are striking. The model achieves the best accuracy across all three error metrics and outperforms the top deep learning models we tested in a previous article. Below, we present two graphs comparing predictions of the two Chronos models, highlighting how the fine-tuned version better captures the specific patterns and nuances of our sneaker time series.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QmztXR-quQXc8NDONSqOYw.png" /><figcaption>White Performance Running Sneakers</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IcPOWfkRH_e1ERkwp8FEKw.png" /><figcaption>Optical White Retro Football Sneakers</figcaption></figure><h3>4) Conclusion</h3><p>In this chapter, we continued our exploration of fashion time series forecasting by evaluating a new class of models called foundation models. These approaches are highly promising:</p><ul><li>They are simple to use, with pre-trained weights <strong>publicly available on Hugging Face.</strong></li><li>They can be used for time series <strong>zero-shot forecasting.</strong></li><li>They can be <strong>fine-tuned</strong> to enhance their accuracy on specific use cases.</li><li>On our fashion forecasting task, <strong>Chronos</strong> and <strong>TimesFM</strong> yield <strong>highly competitive</strong> results.</li></ul><p>While these approaches are still relatively new, their potential is clear. We can be optimistic about future improvements, and we will continue to closely follow advances in this research field.</p><p>To conclude this chapter, we would like to highlight a recent paper by the Amazon Research team introducing a new benchmark dataset, called<a href="https://arxiv.org/abs/2509.26468"> <strong>Fev-Bench</strong></a>, designed to evaluate and rank time series forecasting models, including foundation models. We were pleasantly surprised to see that we were <a href="https://arxiv.org/abs/2202.03224">cited</a> in this paper, as a <strong>sample of Heuritech Fashion time series</strong> was included in Fev-Bench, giving our data a role in this reference set. This means that future models may encounter our fashion forecasting use case during evaluation. Let’s see how the next generation of foundation models rises to the challenge!</p><p>Hope you enjoyed this third post! If you would like to reproduce the graphs and results presented in this article, you can access the linked code repository on <a href="https://github.com/etidav/is_fashion_predictable_foundation_models">github</a>. For more content like this, don’t forget to follow <a href="https://medium.com/@etienne.david">me</a> and <a href="https://medium.com/heuritech">Heuritech</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=44c7d12cd0ba" width="1" height="1" alt=""><hr><p><a href="https://medium.com/heuritech/is-fashion-predictable-the-rise-of-foundation-models-44c7d12cd0ba">Is Fashion Predictable? The Rise of Foundation Models</a> was originally published in <a href="https://medium.com/heuritech">Heuritech, a Luxurynsight Company</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Is fashion predictable ? part 2]]></title>
            <link>https://medium.com/heuritech/is-fashion-predictable-part-2-e66fd321d363?source=rss----8fc6104db0e8---4</link>
            <guid isPermaLink="false">https://medium.com/p/e66fd321d363</guid>
            <category><![CDATA[fashion-forecasting]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Etienne David]]></dc:creator>
            <pubDate>Mon, 14 Apr 2025 15:06:55 GMT</pubDate>
            <atom:updated>2025-12-16T14:27:43.087Z</atom:updated>
            <content:encoded><![CDATA[<h3>Is Fashion Predictable ? From Basic to Accurate Forecasting Models</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DuXP05PJrML9pltiN6N4iQ.png" /><figcaption>Generated with Dall-E 3.</figcaption></figure><p>Hi everyone, I’m Etienne DAVID, a research engineer at Heuritech. Today, we’ll continue exploring fashion forecasting through the lens of mathematical models and AI.</p><p>If you haven’t read my first article on this topic yet, you can find it <a href="https://medium.com/heuritech/is-fashion-predictable-9894d0861f1e">here</a>. In that article, I discuss how we analyze the evolution of thousands of fashion items over time by leveraging social media data and visual recognition algorithms. For a deeper understanding of the visual recognition aspect, I recommend checking out this insightful <a href="https://medium.com/heuritech/a-social-media-image-is-worth-a-thousand-fashion-labels-72423e472587">article</a> by my colleague, Paul Morel.</p><p>Today, I’d like to take things a step further. First, we’ll review some of the most powerful statistical and deep learning models for forecasting. Then, I’ll share complete code examples to demonstrate how to apply these models to any type of signal. Finally, we’ll test their performance on a dataset of fashion time series, tracking the evolution of 100 sneakers in the United States.</p><p>As always, if you’d like to replicate the graphs and results featured in this article, you can access the linked code repository <a href="https://github.com/etidav/is_fashion_predictable_part2">here</a>.</p><h3><strong>1) From Basic to Accurate Forecasting Models</strong></h3><p>In the previous article, we presented two very simple methods: the <strong>snaive method</strong> and the <strong>exponential smoothing method</strong>. In this section, we’ll review several of the most well-known and effective forecasting models from the literature. These models can be classified into two main categories:</p><ol><li><strong>Statistical Models:</strong> These mathematical methods model the distribution of time series data. They typically require minimal tuning, offer explainable predictions, and provide statistical guarantees.</li><li><strong>Deep Learning Models:</strong> The latest state-of-the-art forecasting models fall into this category. With their ability to handle large datasets and integrate diverse, heterogeneous multivariate data, they have achieved unprecedented accuracy across a wide range of applications and datasets.</li></ol><p>Let’s start with the <strong>statistical models</strong>.</p><p><strong>SNAIVE</strong> <strong>and ETS:<br></strong>We already introduced these two models in our previous article. Both are simple approaches that can be quickly implemented. A good practice is to start any forecasting problem with them, as they serve as benchmarks for evaluating the performance of more complex models in future experiments.</p><p><strong>PROPHET (</strong><a href="https://peerj.com/preprints/3190.pdf"><strong>paper</strong></a><strong>, </strong><a href="https://otexts.com/fpp3/prophet.html"><strong>overview</strong></a><strong>): <br></strong>Developed by Meta in 2017, Prophet is one of the most popular tools for time series forecasting and is widely used across industries. Its intuitive design allows users to produce reliable forecasts with minimal effort, even when dealing with complex seasonality and missing data.</p><p><strong>THETAM (</strong><a href="https://www.sciencedirect.com/science/article/abs/pii/S0169207000000662"><strong>paper</strong></a><strong>):<br></strong>The THETA model is a simple yet effective forecasting approach that decomposes a time series into different “theta lines” by applying theta coefficients. This highlights various aspects of the data, such as trends and seasonality. Typically, two theta lines are used: one capturing the long-term trend (often modeled with linear regression) and another focusing on short-term fluctuations (handled via simple exponential smoothing). The forecasts from these components are then combined to produce the final prediction.</p><p><strong>TBATS (</strong><a href="https://robjhyndman.com/papers/ComplexSeasonality.pdf"><strong>paper</strong></a><strong>, </strong><a href="https://otexts.com/fpp2/complexseasonality.html"><strong>overview</strong></a><strong>):<br></strong>The TBATS model — short for <em>Trigonometric, Box-Cox transformation, ARMA errors, Trend, and Seasonal components</em> — is a complex but highly accurate forecasting method. Thanks to its trigonometric multi-seasonality, it effectively handles datasets with multiple seasonal patterns, making it suitable for complex time series data.</p><p><strong>ARIMA (</strong><a href="http://repo.darmajaya.ac.id/4781/1/Time%20Series%20Analysis_%20Forecasting%20and%20Control%20%28%20PDFDrive%20%29.pdf"><strong>paper</strong></a><strong>, </strong><a href="https://otexts.com/fpp3/arima.html"><strong>overview</strong></a><strong>):<br></strong>ARIMA (<em>AutoRegressive Integrated Moving Average</em>) is arguably the most well-known statistical forecasting method. Numerous variations — such as ARMA, SARIMA, and ARIMAX — exist to address a wide range of forecasting tasks. While selecting the appropriate variation and parameters can be challenging, many modern packages offer automated ARIMA implementations that identify the best model configuration for your time series.</p><p>While the previous statistical approaches have many advantages — they are simple to use, require minimal data for calibration, and provide interpretable predictions with a measure of confidence— they can become computationally expensive when applied to large datasets. As a result, over the past decade, a number of <strong>deep learning models</strong> have been introduced, delivering impressive results across a variety of datasets. Here, we’ll present some of them.</p><p><strong>DeepAR(</strong><a href="https://arxiv.org/pdf/1704.04110"><strong>paper</strong></a><strong>):<br></strong>The DeepAR model, introduced in 2019 by researchers at Amazon, uses neural networks to parametrise probabilistic distributions. These distributions are then used to simulate predictions during inference. Based on Recurrent Neural Networks (RNNs), DeepAR was one of the first deep learning-based models to achieve high accuracy with probabilistic forecasts across a broad range of real-world datasets.</p><p><strong>N-BEATS/N-HiTS (</strong><a href="https://arxiv.org/pdf/1905.10437"><strong>paper</strong></a><strong>/</strong><a href="https://arxiv.org/pdf/2201.12886"><strong>paper</strong></a><strong>):<br></strong>N-BEATS and N-HiTS are powerful deep learning models that rely on blocks of Fully Connected Networks (FCNs). These models are grouped together because N-HiTS, released in 2022, is an enhanced version of N-BEATS, which was introduced in 2020. Today, N-HiTS is regarded as one of the most advanced forecasting methods, particularly well-suited for large datasets.</p><p><strong>PatchTST (</strong><a href="https://arxiv.org/pdf/2211.14730"><strong>paper</strong></a><strong>):<br></strong>In my opinion, the PatchTST model is one of the best forecasting models currently available in the literature. It uses a Transformer-based architecture and has delivered impressive accuracy across several benchmark datasets. Released in 2023 by IBM, PatchTST is the first approach to successfully adapt Transformer networks — typically used for Natural Language Processing (NLP) — to time series forecasting.</p><p><strong>TSMixer/TimeMixer (</strong><a href="https://arxiv.org/pdf/2303.06053"><strong>paper</strong></a><strong>/</strong><a href="https://arxiv.org/pdf/2405.14616"><strong>paper</strong></a><strong>):<br></strong>TSMixer and TimeMixer are two of the most recent forecasting models introduced in the literature. Both models share a similar concept: pre-training a deep learning model on a large collection of time series from diverse and heterogeneous sources. These models aim to create a robust system capable of forecasting a wide range of signals by learning patterns across multiple domains. Once pre-trained, they can be applied to specific forecasting tasks or further fine-tuned on targeted datasets to improve performance.</p><h3>2) A Complete Code Base</h3><p>Now that we’ve introduced several forecasting models, this section will present a comprehensive codebase that integrates all of these approaches into a unified framework available <a href="https://github.com/etidav/is_fashion_predictable_part2">here</a>.</p><p>We begin by introducing the abstract class <strong><em>ForecastModel</em></strong>, which defines a general structure for all the forecasting models.</p><pre>from abc import ABC, abstractmethod<br>from typing import Optional, Union<br><br>import pandas as pd<br>from config import PREDICTION_ONE_YEAR<br>from pydantic import BaseModel<br><br><br>class ForecastModel(BaseModel, ABC):<br>    &quot;&quot;&quot;<br>    Abstract class for a forecasting model.<br>    &quot;&quot;&quot;<br><br>    horizon: int = PREDICTION_ONE_YEAR<br>    model_type: Optional[str]<br><br>    @classmethod<br>    @abstractmethod<br>    def from_saved_model(cls, path: str, **kwargs):<br>        pass<br><br>    @classmethod<br>    @abstractmethod<br>    def save_model(cls, path: str):<br>        pass<br><br>    @abstractmethod<br>    def predict(self, historical_data: pd.DataFrame, time_index: str = None) -&gt; pd.DataFrame:<br>        &quot;&quot;&quot;Return the prediction of a forecasting model.<br><br>            Args:<br>                historical_data: A pd.DataFrame gathering time series signals with date as index and time series&#39; name as columns.<br>                time_index: A date in the format &#39;YYYY-MM-DD&#39; where to stop the historical signals and start the<br>                 forecasts. If None is provided, the forecast period will start at the end of the time<br>                 series.<br><br>            Returns:<br>                A pd.DataFrame gathering the predictions.<br><br>        &quot;&quot;&quot;<br><br>    @abstractmethod<br>    def fit(self, historical_data: pd.DataFrame, time_index: Optional[str] = None):<br>        &quot;&quot;&quot;<br>            Model fitting function<br>        &quot;&quot;&quot;<br>        pass</pre><p>Using the <a href="https://nixtlaverse.nixtla.io/statsforecast/index.html"><strong>Statsforecast</strong></a> package developed by <a href="https://www.nixtla.io/">Nixtla</a>, along with a second abstract class, <strong><em>StatsForecastModel</em></strong>, we’ve implemented almost all the statistical models discussed earlier as follows:</p><pre><br>import statsforecast.models as statsforecast_models<br><br><br>class EtsForecastModel(StatsForecastModel):<br>    &quot;&quot;&quot;<br>        Forecast model using AutoTbats method https://nixtlaverse.nixtla.io/statsforecast/src/core/models.html#autotbats<br>    &quot;&quot;&quot;<br>    model_type: StatsForecastModelType = StatsForecastModelType.ets<br>    model_config: str = &quot;ZZZ&quot;<br>    damped: Optional[bool] = None<br>    phi: Optional[float] = None<br><br>    def init_model(self):<br>        self.model = statsforecast_models.AutoETS(<br>            season_length=self.season_length,<br>            model=self.model_config,<br>            damped=self.damped,<br>            phi=self.phi<br>        )<br><br><br>class TbatsForecastModel(StatsForecastModel):<br>    &quot;&quot;&quot;<br>        Forecast model using AutoTbats method https://nixtlaverse.nixtla.io/statsforecast/src/core/models.html#autotbats<br>    &quot;&quot;&quot;<br>    model_type = StatsForecastModelType.tbats<br>    use_boxcox: Optional[bool] = None<br>    use_trend: Optional[bool] = None<br>    use_damped_trend: Optional[bool] = None<br>    use_arma_errors: Optional[bool] = None<br><br>    def init_model(self):<br>        self.model = statsforecast_models.AutoTBATS(<br>            season_length=self.season_length,<br>            use_boxcox=self.use_boxcox,<br>            use_trend=self.use_trend,<br>            use_damped_trend=self.use_damped_trend,<br>            use_arma_errors=self.use_arma_errors<br>        )</pre><p>Following the same approach, we implemented all the deep learning models previously mentioned using the <a href="https://nixtlaverse.nixtla.io/neuralforecast/docs/getting-started/introduction.html"><strong>Neuralforecast</strong></a> package by <a href="https://www.nixtla.io/">Nixtla</a>, along with an abstract class, <strong><em>NeuralForecastModel</em></strong>:</p><pre>import neuralforecast.models as neuralforecast_models<br><br><br>class NHitsForecastModel(NeuralForecastModel):<br>    &quot;&quot;&quot;<br>        Forecast model using NHits method https://nixtla.github.io/neuralforecast/models.nhits.html<br><br>        Args:<br>            n_blocks: List[int], Number of blocks for each stack. Note that len(n_blocks) = len(stack_types).<br>            mlp_units: List[List[int]], Structure of hidden layers for each stack type. Each internal list should contain the number of units of each hidden layer. Note that len(n_hidden) = len(stack_types).<br>            n_freq_downsample: List[int], list with the stack’s coefficients (inverse expressivity ratios). Note that len(stack_types)=len(n_freq_downsample)=len(n_pool_kernel_size).<br>            n_pool_kernel_size: List[int], list with the size of the windows to take a max/avg over. Note that len(stack_types)=len(n_freq_downsample)=len(n_pool_kernel_size).<br>    &quot;&quot;&quot;<br><br>    model_type = NeuralForecastModelType.nhits<br><br>    n_blocks: List[int] = [1, 1, 1]<br>    mlp_units: List[List[int]] = 3 * [[512, 512]]<br>    n_pool_kernel_size: List[int] = [2, 2, 1]<br>    n_freq_downsample: List[int] = [4, 2, 1]<br><br>    def init_model(self):<br><br>        model = neuralforecast_models.NHITS(<br>            input_size=2 * self.horizon,<br>            h=self.horizon,<br>            max_steps=self.max_steps,<br>            learning_rate=self.learning_rate,<br>            batch_size=self.batch_size,<br>            random_seed=self.seed,<br>            n_blocks=self.n_blocks,<br>            mlp_units=self.mlp_units,<br>            n_pool_kernel_size=self.n_pool_kernel_size,<br>            n_freq_downsample=self.n_freq_downsample,<br>            stack_types=[&quot;identity&quot;] * len(self.n_blocks),<br>            num_workers_loader=self.num_workers_loader<br>        )<br>        self.model = NeuralForecast(models=[model], freq=WEEK_FREQUENCY_INDICATOR)<br><br><br>class PatchTSTForecastModel(NeuralForecastModel):<br>    &quot;&quot;&quot;<br>        Forecast model using PatchTST method https://nixtla.github.io/neuralforecast/models.patchtst.html<br><br>        Args:<br>            encoder_layers: int, number of layers for encoder.<br>            n_heads: int, number of multi-head’s attention.<br>            hidden_size: int, units of embeddings and encoders.<br>            linear_hidden_size: int, units of linear layer.<br>    &quot;&quot;&quot;<br><br>    model_type = NeuralForecastModelType.patchtst<br><br>    encoder_layers: int = 3<br>    n_heads: int = 16<br>    hidden_size: int = 128<br>    linear_hidden_size: int = 256<br>    patch_len: int = 16<br><br>    def init_model(self):<br><br>        model = neuralforecast_models.PatchTST(<br>            input_size=2 * self.horizon,<br>            h=self.horizon,<br>            max_steps=self.max_steps,<br>            learning_rate=self.learning_rate,<br>            batch_size=self.batch_size,<br>            random_seed=self.seed,<br>            encoder_layers=self.encoder_layers,<br>            n_heads=self.n_heads,<br>            hidden_size=self.hidden_size,<br>            linear_hidden_size=self.linear_hidden_size,<br>            patch_len=self.patch_len,<br>            num_workers_loader=self.num_workers_loader<br>        )<br>        self.model = NeuralForecast(models=[model], freq=WEEK_FREQUENCY_INDICATOR)</pre><p>The <strong>Statsforecast</strong> and <strong>Neuralforecast</strong> packages are intuitive and powerful tools, consistently maintained and updated by the Nixtla team with the latest forecasting models from the literature. I strongly recommend using them for your forecasting tasks. While I haven’t gone into extensive detail on the code, if you’re interested in exploring it further, I encourage you to check out the complete codebase <a href="https://github.com/etidav/is_fashion_predictable_part2">here</a> and experiment on your own. Now, let’s shift back to our fashion forecasting problem and evaluate how accurately these methods can predict fashion trends.</p><h3>3) Fashion time series forecasting</h3><p>To conclude this second article, we’ll test the models introduced earlier on a dataset of fashion time series, which tracks the evolution of 100 sneaker types in the United States. These time series represent the weekly visibility on social media of 100 sneakers in the U.S., from October 10, 2015, to January 1, 2024. For the forecasting task, we’ll focus on predicting one year ahead. Specifically, we will hide the data for 2023 and, using the remaining historical data, evaluate how well the forecasting models predict the 52 weeks of 2023. Below is an example using the Matte Leather Sneakers. The black portion of the time series represents the data used to train the forecasting models, while the grey portion represents the ground truth (test set), which is hidden during training and used to calculate prediction errors.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mNk1KZ06wrwxp3DBUlUp6g.png" /><figcaption>Matte Leather Sneakers</figcaption></figure><p>Using the previously presented codebase, here’s the script we used to train our forecasting models, generate predictions for the 100 fashion time series, and evaluate the accuracy of these predictions.</p><pre>from neuralforecast_model import (<br>    DeepARForecastModel, NBeatsForecastModel, NeuralForecastModelType, NHitsForecastModel,<br>    PatchTSTForecastModel, TimeMixerForecastModel, TSMixerForecastModel<br>)<br>from prophet_model import ProphetForecastModel, ProphetForecastModelType<br>from snaive_model import SnaiveForecastModel, SnaiveForecastModelType<br>from statsforecast_model import (<br>    ArimaForecastModel, EtsForecastModel, StatsForecastModelType, TbatsForecastModel,<br>    ThetaForecastModel<br>)<br>from utils import (<br>    eval_predictions, load_time_series_csv, mean_errors_ranking<br>)<br><br># Load the fashion time series data<br>fashion_ts = load_time_series_csv(&quot;us_female_sneakers.csv&quot;)<br>fashion_ts_train = fashion_ts.loc[:&quot;2023-01-01&quot;] # Split the dataset into training data up to January 1, 2023<br><br># Define statistical models with their configurations<br>statistical_models = {<br>    SnaiveForecastModelType.snaive:<br>        SnaiveForecastModel(),<br>    ProphetForecastModelType.prophet:<br>        ProphetForecastModel(),<br>    StatsForecastModelType.ets:<br>        EtsForecastModel(model_config=&quot;AAA&quot;, damped=True),<br>    StatsForecastModelType.theta:<br>        ThetaForecastModel(),<br>    StatsForecastModelType.tbats:<br>        TbatsForecastModel(<br>            use_boxcox=True, use_arma_errors=True, use_damped_trend=True, use_trend=True<br>        ),<br>    StatsForecastModelType.arima:<br>        ArimaForecastModel(<br>            d=1,<br>            D=1,<br>            start_p=1,<br>            max_p=1,<br>            start_q=1,<br>            max_q=1,<br>            start_P=0,<br>            max_P=0,<br>            start_Q=2,<br>            max_Q=2<br>        )<br>}<br><br># Define deep learning-based forecasting models<br>deep_models = {<br>    NeuralForecastModelType.deepar: DeepARForecastModel(),<br>    NeuralForecastModelType.nbeats: NBeatsForecastModel(),<br>    NeuralForecastModelType.nhits: NHitsForecastModel(),<br>    NeuralForecastModelType.patchtst: PatchTSTForecastModel(),<br>    NeuralForecastModelType.tsmixer: TSMixerForecastModel(),<br>    NeuralForecastModelType.timemixer: TimeMixerForecastModel(),<br>}<br><br># Fit each deep learning model using the training data<br>for model in deep_models.values():<br>    model.fit(fashion_ts_train)<br><br># Generate forecasts from both statistical and deep learning models<br>models_forecasts = {<br>    **{<br>        model_name: model.predict(fashion_ts_train) for model_name, model in statistical_models.items()<br>    },<br>    **{<br>        model_name: model.predict(fashion_ts_train) for model_name, model in deep_models.items()<br>    }<br>}<br><br># Evaluate the forecasts using the metrics MASE, SMAPE and MAPE<br>error_metrics = eval_predictions(fashion_ts, models_forecasts)<br><br># Rank the models based on mean error metrics and save the results to a CSV file<br>mean_errors_ranking(error_metrics=error_metrics, output_path=&quot;mean_errors_ranking.csv&quot;)</pre><p><strong>3.1) Computational time</strong></p><p>Before assessing the accuracy of the different methods, let’s first take a quick look at the computational time for each approach. The table below shows the training and inference times for each forecasting model.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1010/1*OS_l_Z7y30AYpyPQaR4n-g.png" /></figure><p>Two observations can be made. First, since statistical models require training for each new time series, the training time is equivalent to the inference time. This makes methods in this category slower when applied to large datasets. For example, the ARIMA method takes 30 minutes to forecast our dataset of 100 time series, which makes using such a model on a dataset with thousands of time series costly.</p><p>Second, a single deep learning model can be trained on an entire dataset. In this article, we’re working with a small sample of time series, which is why the training time for deep learning models is relatively short. However, with larger datasets, training these models can take considerably longer. The advantage, though, is that once trained, models can be saved and reused for inference, making them highly efficient at computing prediction on new time series. That said, deep learning models require careful training, including optimising hyperparameters and regular retraining to ensure they continue to perform at their best.</p><p><strong>3.2) Average Error Ranking</strong></p><p>Using the three error metrics introduced in the previous article (MASE, MAPE, SMAPE), we evaluated the performance of the various forecasting methods. Below, we present the average MAPE, SMAPE, and MASE across the 100 forecasts for each model:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1010/1*ys25NnY7HLIpkpi1C-3i4w.png" /></figure><p>We can see that the deep learning model PatchTST achieves the best average accuracy across the three metrics. Two statistical models, TBATS and Prophet, also demonstrate promising results, ranking 4th and 5th when considering the MASE metric. However, two deep learning models, DeepAR and TimeMixer, perform poorly. This doesn’t suggest these methods are unsuitable for our forecasting task, but rather that they were not properly calibrated. We used the same training parameters for all deep learning models, but ideally, we should have conducted a full grid search for each model individually. This underscores the fact that deep learning models are powerful tools, but they require careful tuning.</p><p>In addition to the average results, we can also evaluate the distribution of errors for each method. Below is a graph displaying the MASE distribution for the tested forecasting models. As we can see, PatchTST consistently provides better predictions, with its MASE errors generally lower than those of the other methods.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OZ83FkwVoFukCsYXFsKdtg.png" /><figcaption>Comparison of MASE Across Forecast Models</figcaption></figure><p>Here are some forecast examples. We can observe that many methods effectively capture the various seasonal patterns and the overall trends of the fashion items.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-wR6obJ67ByTvAfUcBk6nw.png" /><figcaption>Matte Leather Sneakers</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qtCB-Bx98x_S5PUH_ZxRgA.png" /><figcaption>Chunky Sneakers</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*E_rEYDER7MxLGJN6v1HrHw.png" /><figcaption>Grey Sneakers</figcaption></figure><h3>4) Is fashion predictable?</h3><p>Looking at the outliers, we can see that a few time series were not accurately predicted by any of the tested methods. One such example is the <strong>White Retro Football Sneakers</strong>. Below, we present the time series along with the predictions from each model.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vn36FaahYV_Udj_UNEiAOA.png" /></figure><p>We can observe that the visibility of this sneaker skyrockets in 2023, yet all the forecasting models fail to capture this sudden increase. Upon reviewing the historical data, there are no early signals or patterns that could have helped even the most advanced mathematical methods predict such a change. Without incorporating external signals, like fashion shows or influencer behaviour, these fashion evolutions remain beyond the reach of mathematical models. This will be the focus of the next article.</p><p>Hope you enjoyed this second post! If you’d like to reproduce the graphs and results presented in this article, you can access the linked code repository <a href="https://github.com/etidav/is_fashion_predictable_part2">here</a>. For more content like this, don’t forget to follow <a href="https://medium.com/@etienne.david">me</a> and <a href="https://medium.com/heuritech">Heuritech</a>. Your support means a lot, and we’d love to have you back for future posts!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e66fd321d363" width="1" height="1" alt=""><hr><p><a href="https://medium.com/heuritech/is-fashion-predictable-part-2-e66fd321d363">Is fashion predictable ? part 2</a> was originally published in <a href="https://medium.com/heuritech">Heuritech, a Luxurynsight Company</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A social media image is worth a thousand fashion labels…]]></title>
            <link>https://medium.com/heuritech/a-social-media-image-is-worth-a-thousand-fashion-labels-72423e472587?source=rss----8fc6104db0e8---4</link>
            <guid isPermaLink="false">https://medium.com/p/72423e472587</guid>
            <category><![CDATA[fashion]]></category>
            <category><![CDATA[computer-vision]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[ai]]></category>
            <dc:creator><![CDATA[Paul Morel]]></dc:creator>
            <pubDate>Thu, 19 Dec 2024 15:51:00 GMT</pubDate>
            <atom:updated>2024-12-19T16:08:27.345Z</atom:updated>
            <content:encoded><![CDATA[<p>At Heuritech we analyze millions of images from social media to understand the adoption of fashion trends of people using visual recognition algorithms. From this, we provide time series, forecasts and many other metrics describing thousands of trends.</p><p>In a recent blogpost, <a href="https://medium.com/u/9335ea9d84a9">Étienne David</a> introduced how it is possible to forecast a fashion trend based on the time series representing its visibility on social media. <a href="https://medium.com/heuritech/is-fashion-predictable-9894d0861f1e">In case you missed it, you can read it here</a>.</p><p>I’m Paul Morel, Data Science Lead at Heuritech. In this article, I will present how we extract meaningful insights from social media images using Deep Learning. Together, we will illustrate the detection of a fashion trend using the example of <strong><em>metal studs jackets for men</em>.</strong></p><h4>Computer Vision at Heuritech</h4><p>Each fashion image on social media contain many layers of valuable insights. At Heuritech, our taxonomy enumerates more than 2,000 clothing attributes (including colors, shapes, types and other attributes) detected on more than 750 million images. By crossing these attributes, we designed a catalog of more than 85,000 fashion trends.</p><p>For our example trend, we need 3 distinct Deep Learning models:</p><ul><li>One detecting the fashion items, including the human and the jacket.</li><li>A second detecting the clothing attributes of the jacket, including the metal studs.</li><li>A third inferring the gender of the human.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/588/1*HzkkdwoWCpUIMwmM5D3NAw.png" /><figcaption>An example of jacket with metal studs. Image courtesy of <a href="https://fr.pinterest.com/pin/64950419616200627/">https://fr.pinterest.com/pin/64950419616200627/</a></figcaption></figure><p>To be able to do that, several considerations are key to understanding how we handle fashion attributes detection, which makes Heuritech unique.</p><h3>Exploring fashion with AI and social media images</h3><h4>Defining and Predicting Specific Classes</h4><p>Let’s focus on how we define and learn to predict a specific class for our clothing attributes detector, such as <em>metal studs. </em>This model performs <strong>image classification</strong>, identifying one or more classes among those it’s been trained to recognize. Most of Heuritech models are doing classification.</p><h4>Acquire the right data, for the right classes</h4><p>The first step is defining classes that make sense for a fashion expert. Keep in mind that these classes will be combined with other ones to define our fashion trends. These classes must be:</p><ul><li><strong>Granular</strong> enough to define and distinguish trends properly, avoiding confusion.</li><li><strong>Exhaustive</strong> to cover all types and attributes of a given clothing while ensuring classes are <strong>mutually exclusive</strong>, i.e. there is no overlap in the classes definition.</li><li>Visible enough to get <strong>decent volumes</strong> of high-quality samples for training.</li></ul><p>One key challenge is avoiding false detections, such as confusing metal studs with rhinestones or pearls. Below are examples of attributes that must not be confused with metal studs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SXOudOAf_rRWgq7uQWZlUw.png" /><figcaption>On the left, an example of rhinestones. On the right, pearls. Both attributes musn’t be confused with metal studs</figcaption></figure><p>One key challenge is avoiding false detections, such as confusing metal studs with rhinestones or pearls. Below are examples of attributes that must not be confused with metal studs.</p><p>We tackle this issue in two ways:</p><ol><li>Learning these classes if they’re useful for detecting other trends.</li><li>Training the model with negative samples of metal studs. However, defining all possible classes a model might “see” is often impractical (too expensive in tagging as there would be too many classes), leading us to rely on open set learning. This field allows models to predict confidently even when encountering unforeseen classes.</li></ol><p>Data quality is king and defining accurately the classes as well as finding the suitable training samples is a long, meticulous job performed by our Fashion experts. Shoutout to them!</p><h4>Building a hierarchy of classes</h4><p>Our classification models don’t simply only pick a single class from the list of trained classes. Many of our models involve both:</p><ul><li><strong>Classifiers</strong> parts detecting single features (e.g., type of top).</li><li><strong>Multilabel </strong>identifying multiple attributes (e.g., sleeve length, neckline shape).</li></ul><p>At the same time. Classes may also have hierarchical relationships. For instance, our clothing attributes model identifies specific denim types (e.g., bleach, tie-dye) while consolidating them under a broader “denim” class. If confidence is low, the model predicts only the broader class.</p><p>For metal studs, no complex hierarchy is required. However, if we wanted a broader trend like “jacket embellishments for men”, we could consolidate predictions of metal studs, pearls, rhinestones, etc., into a parent class.</p><h4>Adjust the training process to fit our need</h4><p>Now that we have the right data for the right model architecture, we train and evaluate the model. A classification model usually predicts a score for every single class between 0 and 1, representing its <em>confidence</em> in detecting the given class. During training, scores above 0.5 are considered detections, and the model is corrected if it makes errors. This threshold is later fine-tuned using a validation set to maximize performance metrics.</p><p>The threshold value impacts 2 important metrics, <strong>precision</strong> and <strong>recall</strong>:</p><ul><li>A higher threshold increases precision but lowers recall.</li><li>A lower threshold improves recall but risks more false positives, harming precision.</li></ul><p>Chosing this threshold value is a tradeoff that needs to be made for each class. The predictions of our models are aggregated to build trend lines, and we want them to be insightful while having enough volume so they can be statistically representative of the given trend.</p><p>At Heuritech, <strong>we value precision twice as much as recall</strong>. To balance this, we use the F-β score, an adjusted harmonic mean of precision and recall where β reflects the weight of recall. For instance, using β = 0.5 prioritizes precision twice as much as recall.</p><figure><img alt="The formula of F-bêta score" src="https://cdn-images-1.medium.com/max/338/1*Wv7Sij5pHvy3KKMQ_vnSFA.png" /><figcaption>The formula of the F-bêta score</figcaption></figure><p>This score is computed for a wide range of possible threshold values, so we can use it to select the threshold that maximizes it.</p><p>Below curve illustrates how precision, recall, F-β and detected volume of <em>metallic</em><strong> </strong><em>studs </em>on clothes evolve with threshold changes, across our valdation set. The optimal threshold maximizes the F-β score while maintaining adequate detected volume.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*ZAdQ5Hz257RDEmG2kZtz8Q.png" /><figcaption>Performance metrics measure for detecting metal studs depending on the threshold value</figcaption></figure><p>Vertical plain and dashed lines represent 2 distinct values of threshold, the one from the model during a previous training (dashed line) and the latest one (plain line). By looking at the intersection with the colored lines, we can find the associated values of the various metrics measured (precision, recall, etc.). Doing so, we see that it is useful to slightly increase the former threshold from ~0.7 to 0.75 to maximize the F-β score.</p><p>We can notice here that the new threshold is the one where the F-β metric is the highest, although we could have better precision by increasing the threshold value. Yet, this would harm too much the predicted volume of detected metallic studs so it is preferrable to keep a non extreme threshold value.</p><p>Provided that we are able to ensure the model has good performance (which is no simple thing, as usual with Deep Learning), we should be good to go to start detection of <em>metal studs</em>.</p><h3>Building a pipeline of model to track fashion trends</h3><p>While we’ve discussed training a single class within a classification model, fashion insights require multiple models working together. Unlike trendy large foundation models, we use a modular pipeline:</p><ul><li><strong>Image-wise models:</strong> Detect fashion objects (e.g., humans, tops, dresses) and classify context (e.g., outdoor vs. indoor, gym).</li><li><strong>Item-specific models:</strong> Analyze detected items for features like attributes, colors, and patterns. For instance, a top classifier detects sleeve length, neckline shape, and type. We also perform regression to spot the color of the clothes.</li><li><strong>Aggregation:</strong> Combine predictions to define trends, such as <em>red V-neck shirts for women</em>.</li></ul><p>By aggregating the images and predictions for a specific geography, we can track a given fashion trends worldwide. Our modular design allows independent updates to specific scopes, such as adding new patterns without retraining unrelated models. Below image showcases the behavior of our deep learning pipeline.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RDj2QDyCxqdrjcWmnq1Z9g.png" /></figure><h3>Conclusion</h3><p>Building deep learning models for fashion involves multiple steps and expertise. This article touched on:</p><ul><li>Training classification models.</li><li>Avoiding common pitfalls like false detections.</li><li>Using modular pipelines for modularity.</li></ul><p>For the sake of simplicity, we didn’t cover many problems that can show up in the detection of trends, even the most obvious ones: <em>how do we ensure the stability and improvement of a given model from one training to an other? How to control the impact of a model on the related trends? Etc.</em></p><p>If you are technical or simply curious about it, please let me know below if you are interested about a detailed article related to this below, by giving it a 👍 or letting me know in the comments below!</p><p>Also, we didn’t tackle the topic of analyzing hundreds of millions of images in reasonable amounts of time and costs, which is a major topic for our solution to work properly. Indeed, <strong>modularity</strong> is one thing, but our approach needs also to be <strong>scalable</strong>. This will be the topic of an upcoming article about <em>Computer Vision Model Serving using NVIDIA AI </em>Triton, stay tuned!</p><p>Last but not least, if you’re passionate about data science and looking for an exciting opportunity, we’re hiring! <a href="https://www.notion.so/heuritech/Data-Scientist-15125e96f2dc809fb503cc98d7ad1591?pvs=4">You can take a look at the job description here</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=72423e472587" width="1" height="1" alt=""><hr><p><a href="https://medium.com/heuritech/a-social-media-image-is-worth-a-thousand-fashion-labels-72423e472587">A social media image is worth a thousand fashion labels…</a> was originally published in <a href="https://medium.com/heuritech">Heuritech, a Luxurynsight Company</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Is fashion predictable?]]></title>
            <link>https://medium.com/heuritech/is-fashion-predictable-9894d0861f1e?source=rss----8fc6104db0e8---4</link>
            <guid isPermaLink="false">https://medium.com/p/9894d0861f1e</guid>
            <category><![CDATA[fashion-forecasting]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Etienne David]]></dc:creator>
            <pubDate>Wed, 13 Nov 2024 10:03:00 GMT</pubDate>
            <atom:updated>2024-11-13T10:15:41.337Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gBvUepu0gOPs6BU6TiCw4g.jpeg" /><figcaption>Generated with Dall-E 3.</figcaption></figure><p>I know that with a title like that, I may receive some negative (or positive?) comments if designers or luxury brands come across my article. Anyway, I’m <a href="https://scholar.google.com/citations?user=wvjteI8AAAAJ&amp;hl=en">Etienne DAVID</a>, research engineer at <a href="https://heuritech.com/">Heuritech</a> and today, we will explore the complex subject of fashion forecasting through the lens of mathematics, machine learning and AI.</p><p>Fashion is a complex and ever-changing sector, especially in recent decades with the emergence of “Fast Fashion” and the consequent acceleration of trend cycles. To understand and predict fashion dynamics using mathematical approaches, the cornerstone will be the data: How can we translate the evolution of fashion into measurable values?</p><h3><strong>1) Translate fashion to time series</strong></h3><p>In response to this first question, Heuritech, a cutting-edge fashion technology company based in Paris, has proposed a surprising solution: analyse images on social media to illustrate the evolution of fashion. The following approach is used:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*STtCDGeMajvJbHvQg-7skg.png" /></figure><p>Here is an example of a Heuritech time series representing the appearance of Chunky Sneakers on social media in the United States from January 1, 2017, to January 1, 2023:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IerI2cQcQVqoifsU_fl8hw.png" /><figcaption>Each point represents the number of posts in the U.S. where the visual recognition framework detected Chunky Sneakers within images.</figcaption></figure><p>As social media data has several biases, we normalise the raw time series above to more accurately represent the fashion evolution of Chunky Sneakers. For instance, if you look at the raw time series at the beginning of 2020, you’ll notice a sudden decrease that may be due to COVID “stay-at-home” quarantines (resulting in fewer outdoor pictures on social media). This effect has been completely removed from the normalised signal shown below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ow4Nb4vJq1_qOABYroqsdw.png" /><figcaption>Normalised time series representing the visibility evolution of Chunky Sneakers in the U.S. on social media.</figcaption></figure><h3>2) Fashion time series forecasting</h3><p>Now that we successfully translated the evolution of fashion into time series, building mathematical predictions is straightforward. Let’s start with two simple statistical models: the seasonal naïve method and the exponential smoothing method (Holt-Winters’ additive version). See <a href="https://otexts.com/fpp2/">this great online book</a> for a complete description of these models.</p><p>We provide below Python classes implementing the two models:</p><pre>import pandas as pd<br>from statsmodels.tsa.api import ExponentialSmoothing<br>from pydantic import BaseModel<br><br>WEEKS_IN_YEAR = 52<br>HORIZON = 52<br><br><br>class EtsForecastModel(BaseModel):<br>    &quot;&quot;&quot;Class defining an ETS (exponential smoothing) model.<br><br>        Args:<br>            season: define the seasonality length.<br>            horizon: define the forecast horizon of the Ets model.<br>    &quot;&quot;&quot;<br><br>    season: int = WEEKS_IN_YEAR<br>    horizon: int = HORIZON<br><br>    def fit_predict_single_ts(self, ts_signal: pd.Series) -&gt; pd.Series:<br>        &quot;&quot;&quot; Fit ETS models and return its prediction.<br><br>            Args:<br>                ts_signal: A pd.Series gathering a single time series signal.<br><br>            Returns:<br>                single_forecast: A pd.Series gathering the ETS prediction.<br>        &quot;&quot;&quot;<br><br>        model = ExponentialSmoothing(<br>            ts_signal, seasonal_periods=self.season, seasonal=&quot;add&quot;, trend=&quot;add&quot;<br>        )<br>        fitted_model = model.fit()<br>        single_forecast = fitted_model.forecast(self.horizon)<br>        single_forecast.name = ts_signal.name<br>        return single_forecast<br><br><br>class SnaiveForecastModel(BaseModel):<br>    &quot;&quot;&quot;Class defining a seasonal naive model that repeats the values of the past year as its prediction.<br><br>        Args:<br>            horizon: define the forecast horizon of the Naive model.<br>    &quot;&quot;&quot;<br>    season: int = WEEKS_IN_YEAR<br>    horizon: int = HORIZON<br><br>    def predict(self, ts_signal: pd.Series) -&gt; pd.Series:<br>        &quot;&quot;&quot; Compute prediction of a Naive model.<br><br>            Args:<br>                ts_signal: A pd.Series gathering a single time series signal.<br><br>            Returns:<br>                single_forecast: A pd.Series gathering the seasonal Naive prediction.<br><br>        &quot;&quot;&quot;<br><br>        historical_data_past_year = ts_signal.tail(52)<br>        nb_repeat, part_repeat = divmod(52, 52)<br>        naive_forecast = [historical_data_past_year] * nb_repeat + [<br>            historical_data_past_year[:part_repeat]<br>        ]<br>        single_forecast = pd.concat(naive_forecast, axis=0, ignore_index=True)<br><br>        forecast_index = pd.date_range(<br>            start=ts_signal.index[-1], periods=52 + 1, freq=ts_signal.index.freq<br>        )[1:]<br>        single_forecast.index = forecast_index<br>        return single_forecast</pre><p>Thus, here is a simple code base that we can use to compute a one-year prediction for Chunky Sneakers in 2024.</p><pre>def load_time_series_csv(filepath: str) -&gt; pd.DataFrame:<br>    df = pd.read_csv(filepath, index_col=0)<br>    df.index = pd.to_datetime(df.index)<br>    df.index.freq = df.index.inferred_freq<br>    return df<br><br><br>fashion_ts = load_time_series_csv(&#39;chunky_sneakers.csv&#39;)<br>fashion_ts_train = fashion_ts.loc[:&quot;2023-01-01&quot;]<br><br>ets_model = EtsForecastModel()<br>ets_prediction = pd.DataFrame(ets_model.fit_predict_single_ts(fashion_ts_train[&quot;chunky_sneakers&quot;]))<br>snaive_model = SnaiveForecastModel()<br>snaive_prediction = pd.DataFrame(snaive_model.predict(fashion_ts_train[&quot;chunky_sneakers&quot;]))</pre><p>Here are the resulting predictions:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DaGhce64OlP0Zwd1Qvl5xg.png" /></figure><h3>3) Forecast evaluation</h3><p>When comparing the predictions with what actually happened in 2024, we can see that both models are quite accurate. The exponential smoothing model effectively captures seasonality and accurately predicts the increase in 2024, unlike the seasonal naïve model, which simply reproduces the previous year’s data. However, this increase appears to be slightly underestimated, as both models fail to fully match the growth at the end of 2023.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rf6bU0xjsg_BZxxUzu6qag.png" /></figure><p>Several error metrics can be used to assess the performance of our two predictions and confirm what we observe in the graph above. Below, we provide the code for three of these metrics:</p><ul><li>Mean Absolute Scaled Error (<a href="https://en.wikipedia.org/wiki/Mean_absolute_scaled_error">MASE</a>)</li></ul><pre>def mase(y_true: pd.DataFrame, y_pred: pd.DataFrame, seasonality: int) -&gt; np.ndarray:<br>    &quot;&quot;&quot;<br>    NOTE: y_true must contain at least `seasonality` time steps before the first time index<br>        of y_pred, plus the number of time steps in y_pred.<br>    &quot;&quot;&quot;<br>    time_split = y_pred.index[0]<br>    index_y_pred = y_true.index.get_loc(time_split)<br>    assert index_y_pred &gt; seasonality + 1, (<br>        f&quot;To compute the MASE, you need {seasonality} time steps of history&quot;<br>        f&quot; before timestamp {time_split}.&quot;<br>    )<br><br>    numerator = np.mean(<br>        np.abs(y_true.values[index_y_pred:index_y_pred + len(y_pred)] - y_pred.values), axis=0<br>    )<br>    gt = y_true.values[seasonality:index_y_pred - 1]<br>    gt_shifted = y_true.values[:index_y_pred - 1 - seasonality]<br>    denominator = np.mean(np.abs(gt - gt_shifted), axis=0)<br>    return numerator / denominator</pre><ul><li>Mean Absolute Percentage Error (<a href="https://en.wikipedia.org/wiki/Mean_absolute_percentage_error">MAPE</a>)</li></ul><pre>def mape(y_true: pd.DataFrame, y_pred: pd.DataFrame) -&gt; np.ndarray:<br>    time_split = y_pred.index[0]<br>    index_y_pred = y_true.index.get_loc(time_split)<br><br>    numerator = y_true.values[index_y_pred:index_y_pred + len(y_pred)] - y_pred.values<br>    denominator = y_true.values[index_y_pred:index_y_pred + len(y_pred)]<br>    mape = np.abs(numerator / denominator)<br>    mape[mape == np.inf] = np.nan<br>    return np.nanmean(mape, axis=0)</pre><ul><li>Symmetric Mean Absolute Percentage Error (<a href="https://en.wikipedia.org/wiki/Symmetric_mean_absolute_percentage_error">SMAPE</a>)</li></ul><pre>def smape(y_true: pd.DataFrame, y_pred: pd.DataFrame) -&gt; np.ndarray:<br>    time_split = y_pred.index[0]<br>    index_y_pred = y_true.index.get_loc(time_split)<br><br>    numerator = np.abs(y_true.values[index_y_pred:index_y_pred + len(y_pred)] - y_pred.values)<br>    denominator = 0.5 * (<br>        np.abs(y_true.values[index_y_pred:index_y_pred + len(y_pred)]) + np.abs(y_pred.values)<br>    )<br>    smape = np.abs(numerator / denominator)<br>    smape[smape == np.inf] = np.nan<br>    return np.nanmean(smape, axis=0)</pre><p>Now that we have these three metrics, we can compute the accuracy of the two predictions made in the previous part. All the values are small, confirming that both predictions are accurate, with the exponential smoothing model outperforming the seasonal naïve method.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RQw_epDB-5xitQc50wTuwQ.png" /><figcaption>Since the three displayed metrics are error metrics, the lower the value, the better the forecast.</figcaption></figure><h3>4) Is fashion predictable?</h3><p>Looking back at the previous sections, it seems we’ve our answer to the question: “is fashion predictable?”. By analysing social media and using simple statistical approaches, we can make accurate predictions of the future evolution of fashion.</p><p>However, the Chunky Sneakers trend remains relatively stable, with slow changes and clear seasonality. It doesn’t fully capture the complexity of the fashion world, where simple forecasting models may no longer suffice. In upcoming articles, we will continue our journey into fashion time series forecasting, working on new fashion time series, testing more powerful forecasting algorithms and assessing their performance.</p><p>If you’d like to replicate the graphs and results presented in this article, you can access the linked code repository <a href="https://github.com/etidav/is_fashion_predictable">here</a>.</p><p>I leave you with a final graph displaying the evolution of Retro Football Sneakers in The United States along with the prediction from the exponential smoothing model for the year 2024. We’ll cover it in a later post !</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DaABIKSyfqoNoS7bh8azNQ.png" /><figcaption>In 2024, Retro Football Sneakers have surged in popularity, but the exponential smoothing model fails to capture this sudden upward trend.</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9894d0861f1e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/heuritech/is-fashion-predictable-9894d0861f1e">Is fashion predictable?</a> was originally published in <a href="https://medium.com/heuritech">Heuritech, a Luxurynsight Company</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Vision Transformers]]></title>
            <link>https://medium.com/heuritech/the-vision-transformers-6650f54e3ade?source=rss----8fc6104db0e8---4</link>
            <guid isPermaLink="false">https://medium.com/p/6650f54e3ade</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[transformers]]></category>
            <category><![CDATA[computer-vision]]></category>
            <dc:creator><![CDATA[Arthur Douillard]]></dc:creator>
            <pubDate>Thu, 03 Jun 2021 09:13:07 GMT</pubDate>
            <atom:updated>2021-06-03T09:13:07.714Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*gDAymNjhGGgiHhD4.jpeg" /><figcaption>No, I’m not going to talk about them.</figcaption></figure><p>There are currently two broads axis of research in Deep Learning: finding better architectures, or finding better losses to train them. Since AlexNet (<a href="https://papers.nips.cc/paper/2012/file/c399862d3b9d6b76c8436e924a68c45b-Paper.pdf">Kriwhevsky et al.</a>), <strong>Convolutional Neural Network</strong> is the main architecture used in Computer Vision. Through convolutions, with its efficient patch prior, many visual tasks were unlocked.</p><p>Many variations of AlexNet were invented, but if we were to name only one, it would be the <strong>ResNet</strong> (<a href="https://arxiv.org/abs/1512.03385">He et al.</a>) and its residual shortcut.</p><p>The main drawback of convolutions is their lack of global reach. A problem, relatively similar to the difficulty of <strong>Recurent Neural Networks</strong> (e.g. RNN, LSTM, GRU) to model long series of tokens. The NLP community saw its “imagenet” moment when the <strong>Transformer</strong> (<a href="https://arxiv.org/abs/1706.03762">Vaswani et al.</a>) architecture was unveiled. First designed with a somewhat complex encoder-decoder, it was later refined in a serie of identical blocks in the BERT (<a href="https://arxiv.org/abs/1810.04805">Devlin et al.</a>) model. Using transfer learning, most (all?) tasks of NLP were attacked via a BERT-like architecture.</p><p>Two questions:</p><p>— What are exactly transformers?</p><p>— And can (should?) we apply them to Computer Vision?</p><h3>1. What are Transformers?</h3><p>I can only recommend the excellent blog post of Jay Alammar “<a href="https://jalammar.github.io/illustrated-transformer/">The Illustrated Transformer</a>“ which explains very well this architecture. But here is a quick recap, a transformer is basically that:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*1iI2NZNGWjSiWy9N.png" /></figure><p>This whole <strong>block</strong> is repeated multiple times, the output of the first goes into the second and so on. Contrary to CNNs or MLPs, the number of dimensions doesn’t change across blocks.</p><p>You can also notice <strong>residuals</strong> twice. They are no different from the residuals in a ResNet, I guess that a trick so good it is found everywhere.</p><h4>1.1. Tokens</h4><p>The four red squares on the left are the <strong>tokens</strong>. There are only four on the image, but actually you can use as much as you (and your RAM) want. A token is simply an piece of data that was embedded. For example in NLP, you could have one token per word of your sentence. From this word, we can use its <strong>word2vec</strong> correspondence giving a latent vector. To also indicate where this word is located in the sentence, we add a positional encoding.</p><p>In this image, there is four tokens entering the block, and four tokens exiting the block. Therefore at the end of the N blocks, we will still have four tokens, but only one of them will be useful! The first token, here denoted by a ‘C’, is a special token called <strong>class token</strong>. It doesn’t belong to any word of the sentence, but is actually a vector that is learned during gradient descent. Once this class token has gone through the N blocks, it will be finally given to a classifier that will predict whatever you training for.</p><p>Put it simply, this class token will go through the network and will extract as much as possible useful information from the <em>word</em> tokens, in order to produce a good representation for the classifier.</p><h4>1.2. Multi-Headed Self-Attention</h4><p>This is the main part of the transformer. First, let’s concentrate on the ‘<strong>self-attention</strong>’.</p><p>We start with the matrix X of shape T x D containing all T tokens. This matrix is going to be linearly transformed (aka matrix multiplication, aka go to a fully-connected layer) three times in parallel:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/258/1*ROoran27vOPUw4W1qyCcwA.png" /></figure><p>They represent respectively the <strong>Q</strong>uery, the <strong>K</strong>ey, and the <strong>V</strong> alue.</p><p>We compute the attention A, a square matrix of shape T x T:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/476/1*XwW6mJeizqn6_KLgRakQMQ.png" /></figure><p>As the name imply, this attention will determine how much a token correspond to another. Notice that the shape of attention matrix A is T x T. For each row <em>i</em>, the value of the column <em>j</em> is the strength of the relationship between the word <em>i </em>and word<em> j</em>.</p><p>We then multiply this attention matrix with the value matrix to <em>select</em> the data:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/230/1*XuR73dK3S6FDVtf67Y60Lw.png" /></figure><p>Where Z is a matrix which has the original shape T x D.</p><p>However, the attention matrix is quite restrictive: if the attention weight between tokens<em> i</em> and <em>j</em> is large, then because of the softmax it will be low between tokens <em>i</em> and <em>u</em>. In order to model multiple kinds of attention, we use <strong>multiple heads</strong>.</p><p>Let’s say we have two heads, then we do the previous self-attention but with different linear transformations:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TQGkH2a9_Q9kUrZXZTJWDw.png" /></figure><p>But then, we have a matrix Z’ which is the concatenation of Z₁ and Z₂ and thus bigger than expected. We simply use again a linear transformation Wₒ of shape 2D x D:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/264/1*N8D9YK7QKX6FgKJvJL2LoQ.png" /></figure><p>Here is a simplified version in PyTorch:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ea0f466a09979833778ce16aea0ef8a2/href">https://medium.com/media/ea0f466a09979833778ce16aea0ef8a2/href</a></iframe><p><em>Note that in practice, to make the dimension of Q/K/V independent to the number of heads, we usually fix the maximum embedding size and split it equally between heads some space.</em></p><h4>1.3. Layer Norm and MLP</h4><p>The rest of the transformer is made of a MLP and two layers norms. The former is simply several fully-connected layers with non-linear activations. The latter are a form of <a href="https://arthurdouillard.com/post/normalization/">normalization layer</a> where the input is subtracted by its mean and divided by its standard deviation, and then is linearly transformed by a set of weights and bias.</p><h3>2. ViT: Vision Transformer</h3><p>Contrary to convolutions and recurrent networks, transformers don’t really have a prior of the input data. So we should easily apply it on images, right?</p><p>Some have incorporated part of the self-attention, as Axial-DeepLab (<a href="https://arxiv.org/abs/2003.07853">Wang et al.</a>). But none to the best of my knowledge, used the whole transformer architecture on images before ViT (<a href="https://arxiv.org/abs/2010.11929">Dosovitskiy et al.</a>). Why? Well, in the case of images the number of tokens is huge. A 224 x 224 image has 50,176 pixels/tokens. This is too big to fit on a GPU.</p><p>The key idea, maybe inspired by BagNet (<a href="https://arxiv.org/abs/1904.00760">Brendel et al.</a>), is to consider a group of pixels as a patch. Instead of thousands of tokens, the image is split into 14 x 14 = 196 tokens/patches, each made of 16 x 16 pixels.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*L6Ah5MoT9KCq_MY2.png" /></figure><p>The transformer architecture is exactly the same as one you could find in NLP. The only difference is how to embed the tokens. In this case, it’s simply a convolution applied patch per patch (called ‘linear projection’ in the image). In addition of positional encoding based on the position of the patch in the image is used.</p><p>The performances of ViT are very impressive. But a major drawback is that this architecture has almost no prior for images. Therefore, while it can potentially reach better results given infinitely large amount of data, it is very hard to train it with few images. The authors of ViT, all from Google, use JFT-300M a large private dataset to pretrain their model on it before transferring the knowledge to ImageNet-{21/1k}.</p><h3>3. DeiT: A more efficient training</h3><p>DeiT (<a href="https://arxiv.org/abs/2012.12877">Touvron et al.</a>) is an extention of ViT with two main contributions: a more efficient training and a transformer-based knowledge distillation.</p><p>Through tons of regularization, the authors manage to train a DeiT from scratch on ImageNet with good performance. Two crucial regularizations are random erasing of the image pixels, and stochastic depth (<a href="https://arxiv.org/abs/1603.09382">Huang et al.</a>). The latter is a kind of dropout, but where a whole transformer block is dropped with only the residual used.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*qMvHodz3zv1IEl5x.png" /></figure><p>The second contribution of DeiT is to propose to improve the training of the transformer by using a teacher model. The teacher/student strategy is often seen where a large trained teacher model produces novel targets to the student through knowledge distillation (<a href="https://arxiv.org/abs/1503.02531">Hinton et al.</a>). Basically, the student is trained to predict the labels of the image but also to mimick the probabilities of the teacher.</p><p>The first interesting conclusion is that it’s better to use a large CNN (a RegNet (<a href="https://arxiv.org/abs/2003.13678">Radosavovic et al.</a>)) as a teacher than a large vision transformer. Intuitively, we may hypothesize that is because a convolution-based teacher has learned different knowledge and thus may diversify better the predictions of the student.</p><p>The second conclusion is that using the output of the student classifier is not the best way to do knowledge distillation. Recall that the transformer’s classifier input is the class token that has gone through all blocks. DeiT instead add a new token, called a <strong>distillation token</strong>, and with it a new classifier. This classifier will be solely devoted to the task of distillation with the teacher, while the original classifier with class token will resume the image classification task.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/620/0*sdjXBILtjdGzR58b.png" /></figure><h3>3. ConViT: Make Prior Great Again</h3><p>ViT needs a 300M dataset to train. DeiT <em>only</em> needs a 1.2M dataset (ImageNet) to train. But can’t we learn with a few thousand of images like a good old resNet can?</p><p>You need a prior to learn with few data point.</p><p>This is the message of ConViT (<a href="https://arxiv.org/abs/2103.10697">D’Ascoli et al.</a>). They modify the usual Self-Attention (SA) into a <strong>Gated Positional Self-Attention</strong> (GPSA):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/806/0*KAJAuKatlcMyXpzB.png" /></figure><p>As shown on the diagram, only the attention part is modified, while the multiplication with the value matrix is left unchanged. This attention is now a linear combination between the self-attention and a positional prior. A <strong>learned gate</strong> (aka a learned vector followed by a sigmoid) balances between both branch, although its initialization enforces at first a strong emphasis on the positional prior. This positional prior, initialized the right way, can mimick a convolutional kernel.</p><p>A locality strength factor α can modulate how big this kernel should be:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/778/0*PaROUhdb7D7JLb0x.png" /></figure><p>The authors find that at the training end, the early transformer blocks (2–7) mainly use the positional prior, while the first and final blocks (8–10) use the global reach of the self-attention.</p><p>With few data, the positional prior has an important role as the following graph shows:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/382/0*LXhr9vwXw71XiwGH.png" /></figure><h3>4. CaiT: Further refinements of DeiT</h3><p>The authors from DeiT later released CaiT (<a href="https://arxiv.org/abs/2103.17239">Touvron et al.</a>), a refinement of of DeiT.</p><p>The first contribution is <strong>LayerScale</strong>, a ponderation scheme for the main branch in the residual architecture. As for ResNet, each block has two branches: an identity branch that often does nothing, and the branch with learnable parameters. In the case of transformers, those parameters are either the MLP or the Multi-headed Self-Attention.</p><p>Previous works (ReZero <a href="https://arxiv.org/abs/2003.04887">Bachlenchner et al.</a>, SkipInit <a href="https://arxiv.org/abs/2002.10444">De et al.</a>, and FixUp <a href="https://arxiv.org/abs/1901.09321">Zhang et al.</a>) wondered if we could train a very deep ResNet without batch normalization. They all found, with minor variations, that it was possible if main branch of a ResNet block was weighted by a learned scalar. LayerScale proposes more or less the same, but with one scale per dimension , initialized to a small ε value:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*xh9Y22pNVDgPmX47.png" /></figure><p>The second contribution of CaiT, is very similar to a contribution of ConViT (authors are partially the same): CaiT also introduces the class token after several blocks. The last few blocks with class tokens implement a <strong>Class Attention</strong>.</p><p>Contrary to <strong>Self-Attention</strong>, this Class Attention <em>freezes</em> the patch tokens:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*a4JregA3voEGj2cl.png" /></figure><p>Put it more simply, the patch tokens aren’t updated anymore after each block of Class Attention. Moreover, the attention is not done between all patches tokens Xp, of shape (T-1) x D, anymore (at a quadratic cost T²), but only with the class token Xc of shape 1xD (at a linear cost T):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/386/1*Z22P7PwdTVaPwXyv1MqF-w.png" /></figure><p>The computational speed up is easily seen as the attention product is not anymore quadratic w.r.t the number of patches. Furthermore, it gives a nice performance gain, as the Self-Attention layers are now allowed to focus on extracting class-agnostic features.</p><h3>5. The Future of Vision Transformers</h3><p>ViT first proves that it was possible to train transformers on visual tasks. DeiT then showed that with carefully designed regularizations, the training could be done on relatively small scale datasets. This contribution, and the fantastic <a href="https://github.com/rwightman/pytorch-image-models">Timm library</a>, opened a gold rush on transformers.</p><p>I won’t enumerate all variants here. Some may be only a slight tweak and will be forgotten, others may prove to be a stepping stone in the transformers world. Only time will tell.</p><p>But, that’s assuming that transformer is indeed the right solution. <strong>Attention is all we need?</strong> Recent research on MLPs (yes, you read correctly) indicates that maybe attention is only a special case of a more general framework.</p><p>We’ll cover it in a later post!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6650f54e3ade" width="1" height="1" alt=""><hr><p><a href="https://medium.com/heuritech/the-vision-transformers-6650f54e3ade">The Vision Transformers</a> was originally published in <a href="https://medium.com/heuritech">Heuritech, a Luxurynsight Company</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The year’s top fashion trends in hip-hop, as seen on YouTube]]></title>
            <link>https://medium.com/heuritech/the-years-top-fashion-trends-in-hip-hop-as-seen-on-youtube-70271aeb701e?source=rss----8fc6104db0e8---4</link>
            <guid isPermaLink="false">https://medium.com/p/70271aeb701e</guid>
            <category><![CDATA[youtube]]></category>
            <category><![CDATA[hip-hop]]></category>
            <category><![CDATA[music-videos-online]]></category>
            <category><![CDATA[rap]]></category>
            <category><![CDATA[fashion]]></category>
            <dc:creator><![CDATA[Jeanne Dupeau]]></dc:creator>
            <pubDate>Fri, 18 Sep 2020 12:01:03 GMT</pubDate>
            <atom:updated>2026-01-16T10:36:04.641Z</atom:updated>
            <content:encoded><![CDATA[<h3>Key takeaways</h3><ul><li><em>Fashion and music exist in mutual creativity, both acting as a zeitgeist for whatever the era’s trends and sentiments.</em></li><li><em>Hip-hop in particular is enjoyed by a large portion of younger generations, and as a result fashion trends tend to crop up from the genre.</em></li><li><em>Heuritech’s analysis of hip-hop music videos reveals the top fashion trends of 2019 and 2020, from Yo Gotti in fur to Ninho in checkers.</em></li></ul><p>Fashion and music are inextricably linked. And they always have been, from Michael Jackson’s shiny glove to Pharrell’s vintage Vivienne Westwood hat. It’s not uncommon that a musical artist is the pioneer of a fashion trend, or even a fashion movement, it’s all about the universe the musician creates. And between Gen Z and millennials’ attachment to social media and penchant for the hip-hop genre, the interaction between fashion and music has never been so rapid fire. Cite Kanye West and his namesake brand Yeezy comes to mind; cite Tupac and one pictures a red bandana and gold chains.</p><p>These associations exist largely thanks to music videos, an art form in its modern form taking off in the 1980s with the rise of MTV. Today, music videos are diffused across social media to be watched on YouTube and other platforms by millions of fans, and with each album release it seems fans expect at least one or two videos to follow. Fashion brands haven’t let these numbers escape them: in Travis Scott’s music video for the song SICKO MODE, for example, he mentions the brand Nike, and has since been collaborating with the sportswear giant on their signature Air Force 1s. Moments like these speak to the power of images over fashion trends. <strong>So what are some of fashion’s major trends in </strong><a href="https://www.thezoereport.com/p/how-fashion-in-music-videos-has-evolved-how-its-stayed-the-same-22808736"><strong>hip-hop music videos</strong></a><strong> in particular?</strong></p><figure><img alt="Travis Scott Cactus Jack AF1s" src="https://cdn-images-1.medium.com/max/562/1*28rDjTJCeQfobvXAM_XxRQ.jpeg" /><figcaption><strong>Travis Scott Cactus Jack AF1s</strong></figcaption></figure><h3>Fashion trends in the past year’s hip-hop music videos on YouTube</h3><p>To answer this question, <a href="https://heuritech.com/">Heuritech</a> analyzed over 600 of the most popular hip-hop music videos on YouTube across 2019 and 2020 in the US and France. Heuritech applied its in-house image recognition technology to do so, a method which allows for the detection of over 2000 attributes and products in each frame, like texture, color, model, and much more. <strong>Over the past year, five main trends stood out in some of hip-hop’s top music videos:</strong></p><h3>1. FUR</h3><p>Of the music videos analyzed, 18% featured some sort of fur, most often worn on coats. It’s a classic look: big fur coat, ostentatious jewelry, hype entourage. In <a href="https://www.youtube.com/watch?v=b_yemTF8N8E">Dadju’s video for “Sous Controle” featuring Niska</a>, the rapper walks into a mansion sporting a long fur coat before jumping into the song itself. In <a href="https://www.youtube.com/watch?v=1PnHB4sLqew">Yo Gotti’s video for “Put A Date On It” featuring Da Baby</a>, Gotti stands at the head of a long dining table donning a red coat embellished with a fur collar. The fur coat is a symbol of beyond-rich, it’s why the look fits in so well with the hip-hop universe. Fur is a status symbol that’s stood the test of time, even in modern rap.</p><figure><img alt="Heuritech’s YouTube video analysis detected fur as fashion trend in hip-hop" src="https://cdn-images-1.medium.com/max/1024/1*DpyxHqYz0YVggZh0T-L9Zw.jpeg" /></figure><h3>2. NEON &amp; FLUORESCENT</h3><p>From neon yellow to lime green, fluorescent colors were heavily featured in 2019 and 2020’s rap videos on YouTube with an 11% share. Featuring <a href="https://www.youtube.com/watch?v=FbcLcSY2au4">Nicki Minaj and Ty Dolla $ign, Megan Thee Stallion’s breakout video “Hot Girl Summer”</a> is filled to the brim with girls in neon green, pink, blue, and more, with some of the set props even awash with fluorescence. <a href="https://www.youtube.com/watch?v=8mW80GC1KXw">Rich the Kid’s video for “Save That”</a>includes children dressed in neon, dancing through a grocery store to the rapper’s music and even joining him to dance at times, equally dressed in a brilliant yellow. At times fluorescent colors tend to communicate a sort of futuristic, almost technological mood, while other times they evoke unbridled energy and enthusiasm. Rich the Kid and Megan Thee Stallion include neon colors as a way to transmit each mood through their music videos, respectively.</p><figure><img alt="Heuritech’s YouTube video analysis detected neon as fashion trend in hip-hop" src="https://cdn-images-1.medium.com/max/1024/1*qXDAFzagxcW6HVNiH_7HwA.jpeg" /></figure><h3>3. TANK TOPS</h3><p>Call it what you may — singlet, string vest, undershirt, Guinea tee — men’s tank tops weren’t missed in hip-hop music videos. With a 10% share of the videos analyzed, this item was exclusively worn in black or white, typically with the rap-classic gold or silver chains to amp up the look. <a href="https://www.youtube.com/watch?v=2KDlDuS6r6I">NLE Choppa’s “Shotta Flow Remix” featuring Blueface</a> takes place at a backyard barbecue, where the rapper is dressed in the embodiment of summer relaxation: oversized jeans and a jersey tank top.</p><figure><img alt="Heuritech’s YouTube video analysis detected tank tops as fashion trend in hip-hop" src="https://cdn-images-1.medium.com/max/1024/1*COBetxX1LuMCUqgVkjPobA.jpeg" /></figure><h3>4. DENIM</h3><p>Denim is one of those classic 90s and 2000s trends, from oversized jeans to denim trucker hats. This year, the trend has cycled back in smaller proportions: fitted skinny jeans, with rips or even acid wash, are a major hit. The trend appears in 17% of all music videos analyzed, which is no small number. In <a href="https://www.youtube.com/watch?v=QZu6OHkkSQY">Kaza’s video for “Béni” featuring Maes</a>, the rappers are filmed in front of suburban buildings, and Maes along with members of their entourage are sporting slim, ripped jeans with oversized jackets. <a href="https://www.youtube.com/watch?v=7g5dA5OZSLA">K Camp’s music video for “Ice Cold”</a> takes place in a 90s-style house, and again, the rapper wears ripped jeans with an oversized jacket.</p><figure><img alt="Heuritech’s YouTube video analysis detected denim as fashion trend in hip-hop" src="https://cdn-images-1.medium.com/max/1024/1*9u_B8u0CKIVjUr2tLYo3Yw.jpeg" /></figure><h3>5. CHECKERED</h3><p>Checkers aren’t always an easy pattern to wear outside of prep school and 221b Baker Street, but this year’s hip-hop artists are breathing life into the preppy print. The pattern appeared in 11% of the music videos analyzed, often on flannel overshirts and jackets. <a href="https://www.youtube.com/watch?v=qrwG3yynNss">Kpoint’s “Ma 6t a craqué” featuring Ninho</a>, and <a href="https://www.youtube.com/watch?v=gmK_gaE5v9A">DaBaby’s “Find My Way”</a> are two videos in which both rappers appear in red and black checkered overshirts, à la Kurt Cobain. In <a href="https://www.youtube.com/watch?v=ppSY98RGyBU">Kodak Black’s “Calling My Spirit,”</a> the women featured in the video sport black-and-white checkered jumpsuits.</p><figure><img alt="Heuritech’s YouTube video analysis detected checkers as fashion trend in hip-hop" src="https://cdn-images-1.medium.com/max/1024/1*UEMG22b2B9P5wDXfMqCw2w.jpeg" /></figure><h3>Hip-hop meets high fashion</h3><p>And when it comes to analyzing fashion trends, hip-hop music videos are a good place to look, particularly those posted to YouTube. In Nielsen Music’s 2020 mid-year report, the music sales tracking company reported that <a href="https://hypebeast.com/2020/7/hip-hop-most-popular-genre-2020-streaming-sales-data-info"><strong>hip-hop is the top genre</strong></a><strong> in the US and France this year.</strong> It’s not surprising given that the two countries are the top two producers of hip-hop in the world, which also helps to explain luxury brands’ interest in rappers and their videos. In the last two years alone, brands from Louis Vuitton to Saint Laurent have released rap-fronted campaigns to draw in younger customers. “It is from <a href="https://fashion-history.lovetoknow.com/fashion-history-eras/hip-hop-fashion">rap and music video</a> that followers are able to determine and validate their assumptions about their lifestyle decisions, including apparel expressions,” states Cornell Professor Van Dyk Lewis.</p><p>And the list of <a href="https://www.fashionbeans.com/article/hip-hop-style/">collaborations between rappers and designers</a> thanks to their lyrics and music videos is seemingly exhaustive, dating back to even the 80s. <a href="https://www.youtube.com/watch?v=5xXhPAud1io">Run-DMC’s 1986 song My Adidas</a> scored the group a million-dollar endorsement, a deal unheard of at the time. Since, the list has only grown, including Versace collabing with 2 Chainz on a sneaker, Dior selecting <a href="https://hiphopcorner.fr/rap-francais-mode-amour-2020">S.Pri Noir</a> as the face of a fragrance campaign, and Chanel partnering with Pharrell on a 2019 collection. Consumers see these collaborations, and they want what they see. Genius notes that in 2018, “the three <a href="https://www.wsj.com/articles/these-are-the-fashion-brands-rappers-namedrop-the-most-11555943601">most-referenced fashion brands</a>–Fendi, Balenciaga, and Gucci–were called out 664 times in rap and R&amp;B songs.” While fashion and music is no one-way street, can anyone be surprised that these brands are some of the most-desired by younger consumers today?</p><figure><img alt="Run DMC in their signature 3-stripe Adidas" src="https://cdn-images-1.medium.com/max/564/1*3_QathWcTAhv28Dwn_KfCg.jpeg" /><figcaption><strong>Run DMC in their signature 3-stripe Adidas</strong></figcaption></figure><h3>The power of music videos in hip-hop’s fashion trends</h3><p>Fashion and music exist in mutual creativity, and it’s clear that their expression is often appreciated via music video. These videos seem frozen in time when one looks back, and in a way they are fashion’s living archives.</p><p>When Ja Rule wore a rare Burberry bucket hat in his <a href="https://www.youtube.com/watch?v=Cj4xsbyUjc4">music video for “Always on Time,”</a> many fans of hip-hop discovered the famous tartan pattern for the first time, and the brand has been present in rappers’ outfits ever since. When A$AP Rocky wore and mentioned Dior in more than a few of his music videos, he became a face of Dior Homme shortly thereafter in 2016. When <a href="https://www.purebreak.com/news/pnl-x-off-white-la-collaboration-streetwear-qu-on-attendait-tous/177838">PNL appeared in custom Off-White</a> in their music video for “Au DD,” a capsule collection between the French rap duo and Virgil Abloh was announced not long after.</p><p>There are seemingly endless instances of <a href="https://www.complex.com/music/2013/03/the-50-greatest-fashion-moments-in-rap-video-history/">rappers mixing with high fashion</a>, and more and more, it seems to go the other way around, with brands instead approaching rappers. The reach of these artists on fashion trends is further backed by <a href="https://heuritech.com/trend-forecasting-fashion-ai/">Heuritech’s analysis</a> of the past year’s top five trends drawn from hip-hop’s top music videos on YouTube: fur, neon, tank tops, denim, and checkered.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=70271aeb701e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/heuritech/the-years-top-fashion-trends-in-hip-hop-as-seen-on-youtube-70271aeb701e">The year’s top fashion trends in hip-hop, as seen on YouTube</a> was originally published in <a href="https://medium.com/heuritech">Heuritech, a Luxurynsight Company</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How Can Fashion Brands Go Viral on TikTok in 2020?]]></title>
            <link>https://medium.com/heuritech/how-can-fashion-brands-go-viral-on-tiktok-in-2020-917604ecdc63?source=rss----8fc6104db0e8---4</link>
            <guid isPermaLink="false">https://medium.com/p/917604ecdc63</guid>
            <category><![CDATA[fashion]]></category>
            <category><![CDATA[digital-fashion]]></category>
            <category><![CDATA[tik-tok]]></category>
            <category><![CDATA[fashiontech]]></category>
            <dc:creator><![CDATA[Jeanne Dupeau]]></dc:creator>
            <pubDate>Wed, 16 Sep 2020 10:04:29 GMT</pubDate>
            <atom:updated>2026-01-16T10:34:52.212Z</atom:updated>
            <content:encoded><![CDATA[<h3>Key takeaways</h3><ul><li><em>Brands are eager to find the best way to be present on TikTok, in the hopes of engaging with the platform’s young user base</em></li><li><em>High potential for user engagement seems to be the key for success on the platform, with tutorial videos and challenges being amongst the most popular video formats</em></li><li><em>TikTok communities have influenced style, with Celine’s SS21 menswear collection titled “The Dancing Kid” being one of the latest examples of this phenomenon</em></li></ul><p>This summer, a number of young TikTok stars including Chase Hudson (<a href="https://www.tiktok.com/@lilhuddy?lang=en">@lilhuddy</a>) and Noen Eubanks (<a href="https://www.tiktok.com/@noeneubanks?lang=en">@noeneubanks</a>) served as the face of Celine, with creative director <a href="https://www.vogue.com/fashion-shows/spring-2021-menswear/celine">Hedi Slimane’s SS21 Gen Z-inspired collection titled “Dancing Kid”</a>, solidifying TikTok’s vital role in the fashion ecosystem. The video sharing platform is particularly popular amongst Gen Z, <a href="https://www.retaildive.com/news/what-the-future-of-tiktok-means-for-retail/584483/">who represent the largest segment of its user base</a>. Thus, it comes as no surprise that luxury brands are eager to figure out how to effectively engage with TikTok users in the hopes of attracting Gen Z to their brands.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*B6HeuHuL6xENWyIg9yTg3w.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*f1xk6njN8v6dDZFyiAcoHg.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*ZORagH63chuFk1TVtrlpeA.jpeg" /><figcaption>Celine’s SS21 menswear collection “The Dancing Kid”</figcaption></figure><h3>Virality on TikTok</h3><p>However, going viral on TikTok is a major challenge for even the biggest brands, as the type of content that is popular on Instagram often does not perform well on TikTok. This is partially because, compared to Instagram, <strong>TikTok is described as being more “authentic” and “spontaneous,”</strong>with the opportunity for user engagement being an important aspect of a video’s success.</p><p>Popular video formats on TikTok include various “challenges”, educational videos, and, of course, lip syncing and dancing. Since the popularity of these video formats rely on the mass participation of the TikTok community, with users recreating their version of a viral dance, for instance, it is clear that a high potential for user engagement seems to be the key for success on the platform.</p><p>Another idiosyncrasy of TikTok compared to other social media is that <strong>the content itself is ostensibly more important than the user creating it.</strong> While there are clearly anomalies to this tendency, as TikTok influencers do exist (take the Hype House, for one), it is much more difficult for fashion brands or celebrities to be successful on the platform simply because they are well known. According to an <a href="https://www.businessoffashion.com/articles/professional/who-will-buy-tiktok">article</a> published by Business of Fashion, the best way for brands to benefit from TikTok is “either by inventing a meme that catches on with users or, more often than not, <a href="https://www.businessoffashion.com/articles/news-analysis/bof-exclusive-tiktok-new-york-fashion-week">finding a way to capitalise</a> on content that went viral organically.”</p><h3>Fashion brands trending on TikTok</h3><p>With this in mind, it makes sense why brands are struggling to be successful on the platform, as engineering a viral moment is difficult, and having one organically appear is pure luck. Gucci is the latest luxury brand to benefit from a viral TikTok moment, with the #GucciModelChallenge where TikTokers emulate the brand’s signature kitschy aesthetic by creating looks from their own wardrobe. At the time of writing this article, this hashtag has generated over 14.5 million views despite Gucci having zero involvement in creating the challenge.</p><p>The “democratic” nature of the platform, where seemingly anyone can become famous if their content resonates with fellow TikTok users, is exactly what makes the app so appealing. For instance, a JW Anderson patchwork crochet cardigan went viral after Harry Styles was seen wearing it during a rehearsal on The Today Show. Being priced at <a href="https://www.jwanderson.com/fr/shopping/colourblock-patchwork-cardigan-14688042">1450€</a>, far beyond the budget of most Gen Zers, one TikTok user, Liv Huffman (<a href="https://www.tiktok.com/@lilbittylivie?lang=en">@lilbittylivie</a>) created her own version of the cardigan in a video that reached <a href="https://www.tiktok.com/@lilbittylivie/video/6838626054928764166?referer_url=https%3A%2F%2Fwww.gq.com%2Fstory%2Ftiktok-diy-fashion-harry-styles&amp;referer_video_id=6838626054928764166">3.6 million views</a>, and inspired thousands of other users to recreate their version of the garment. Following this explosion on TikTok, JW Anderson even released the pattern for the cardigan to encourage others to participate in this DIY trend.</p><figure><img alt="Harry Styles wearing the JW Anderson cardigan that became a TikTok sensation" src="https://cdn-images-1.medium.com/max/1024/1*FauSXEnOiYne4I6xGIMnYA.jpeg" /><figcaption><strong>Harry Styles wearing the JW Anderson cardigan that became a TikTok sensation</strong></figcaption></figure><p>This example is emblematic of the type of content that is well suited to TikTok — according to a recent <a href="https://www.voguebusiness.com/companies/fashion-started-warming-up-to-tiktok-then-turbulence-hit">article</a> by Vogue Business, <strong>“Whenever you’re teaching people something, your engagement is higher,” </strong>which is logical as users are inspired to recreate the content of the video. The prominent DIY community on TikTok is related to the fact that Gen Zers tend to be more environmentally conscious than previous generations, and <a href="https://www.gq.com/story/tiktok-diy-fashion-harry-styles">appreciate hand-made garments</a>.</p><p>Moreover, due to the pandemic, people are spending more time at home and on their devices, with more time to develop hobbies, making the DIY trend particularly relevant for 2020. In fact, the term “craftcore” has recently emerged, describing this hand-made aesthetic and practice, with tie dye, patchwork, and crochet being some stylistic elements of this new subculture.</p><p>Despite the environmental awareness of Gen Z, it is important to mention that fast fashion brands like Boohoo or PrettyLittleThing are still finding success on the platform. Boohoo created a TikTok song along with a challenge, tagged #Itsfromboohoo generating 122.7 million views, while PLT’s #prettychallenge has 34.8 million.</p><h3>Trending subcultures in fashion on the platform</h3><p>The dialogue between fashion and TikTok is informed by the distinctive subcultures that emerge on the platform. For example, <a href="https://www.gq.com/story/hedi-slimane-celine-tiktok">Celine’s most recent men’s collection</a> was inspired by the “eboy” aesthetic that describes a specific archetype of Gen Z, with chunky chains, oversized cardigans, and clashing patterns being the token elements of the style.</p><p>Although it is unclear where subcultures like the eboy/egirl or craftcore begin, TikTok certainly nurtures the development of these communities, making the platform an indispensable form of social media in the fashion industry. <strong>TikTok presents a change to the “influencer industry”, because brands and celebrities cannot rely solely on their fame to succeed on the platform.</strong> Rather, they must create engaging content, like challenges or tutorial style videos that encourage user interaction, in order to be popular on TikTok.</p><h3>The future of TikTok fashion trends</h3><p>Although brand exposure on TikTok sometimes arises by chance, with the #GucciModelChallenge or JW Anderson sweater, it is clear that if fashion brands want their content to go viral on the platform they need to invent new ways to encourage users to engage with their content.</p><p>This is where data drawn from the platform can be highly valuable to brands seeking to peer into the daily behavior of its users: <a href="https://heuritech.com/">Heuritech analyzes images and videos</a> shared on social media in order to historicize and predict fashion trends. Because trends evolve so rapidly on TikTok, it is key to be able to assess thousands, even millions, of images per day. Heuritech currently analyzes over 3 million images per day on Instagram alone — the possibilities for TikTok are good news for luxury brands seeking to be first string in fashion trends. In any case, TikTok’s influence in fashion attests to the importance of social media in predicting future trends, offering a snapshot of consumer behaviours and preferences in the virtual realm.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=917604ecdc63" width="1" height="1" alt=""><hr><p><a href="https://medium.com/heuritech/how-can-fashion-brands-go-viral-on-tiktok-in-2020-917604ecdc63">How Can Fashion Brands Go Viral on TikTok in 2020?</a> was originally published in <a href="https://medium.com/heuritech">Heuritech, a Luxurynsight Company</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Quarantine Rebirth: Men’s Fashion Week Review SS21]]></title>
            <link>https://medium.com/heuritech/quarantine-rebirth-mens-fashion-week-review-ss21-d146fa21f63d?source=rss----8fc6104db0e8---4</link>
            <guid isPermaLink="false">https://medium.com/p/d146fa21f63d</guid>
            <category><![CDATA[ss21]]></category>
            <category><![CDATA[fashion]]></category>
            <category><![CDATA[mens-fashion-week]]></category>
            <dc:creator><![CDATA[Jeanne Dupeau]]></dc:creator>
            <pubDate>Tue, 28 Jul 2020 14:01:01 GMT</pubDate>
            <atom:updated>2026-01-16T10:31:57.518Z</atom:updated>
            <content:encoded><![CDATA[<h3>Key takeaways</h3><ul><li><em>Men’s SS21 digital fashion week represents a turning point in the fashion world, being the first major digital fashion week following Haute Couture, with designers creating innovative new ways of presenting their collections, challenging the traditional format of the fashion show</em></li><li><em>Following this period of crisis, brands are questioning their reason to exist, with the meaning and intention behind their collections being equally as important as the garments themselves</em></li><li><em>A major theme this fashion week was a “return to nature”, with designers showing a renewed appreciation for the natural environment, and favouring more artisanal materials and textiles that require a high level of craftsmanship</em></li></ul><p>This men’s SS21 digital fashion week was a pivotal moment for the fashion world, with both independent designers and luxury maisons being tasked with the challenge of somehow translating the experience of attending a show IRL to the virtual realm. Although there is no true replacement to the “real thing”, many designers took advantage of this unique opportunity to challenge the format of a traditional fashion show, and utilize the possibilities afforded by technology to communicate with their audience in a novel way. Another first related to this (almost) exclusively digital fashion week is the democratization of the viewing experience, as would-be fashion show attendees and the “average” person both see the collection through the screen of their devices.</p><p>Brands were forced to adapt to this new reality, with many coming up with highly innovative ways of presenting their collections in the digital realm. UNDERCOVER’s collection was completely rendered in 3D, with models appearing like avatars from Grand Theft Auto; Sunnei’s “Canvas” collection utilizes CGI to depict models wearing white garments that are completely customisable through the brand’s VR platform; COOL™ created an interactive experience using VR; Kolor’s Junichi Abe developed a 360 degree camera system so viewers can see each look from every angle.</p><figure><img alt="Kolor campaign SS21" src="https://cdn-images-1.medium.com/max/341/0*HER49BAkoi60NRGP.png" /><figcaption>Kolor</figcaption></figure><h3>Narration to Convey Emotion</h3><p>In addition to experimenting with the format of the digital fashion show, several designers took a philosophical approach in attempting to convey a deeper meaning behind the collection that goes beyond the physical garments. A distinctive theme that emerged this fashion week is using narration to convey a sense of emotion, with designers’ videos featuring poetry, novel excerpts, home-video audio recordings, and Nietzsche quotes dubbed over visuals. The Bolognese brand Magliano created a mythological universe, with each model embodying a fictitious character, featured in a video narrated by the novelist Isabella Santacroce. Luchino Magliano, founder of his eponymous label, explains that “<a href="https://highxtar.com/magliano-continues-his-ascent-ss21/?lang=en">Narration is the first form of augmented reality. We asked ourselves how we could overcome the virtual medium to convey the emotion and research behind each object, and we came to the conclusion that the word is the strongest medium.</a>” Given the amount of designers who utilized narration to convey the story behind their collections, it is clear that many others would agree with Magliano.</p><figure><img alt="Still from Magliano SS21 video" src="https://cdn-images-1.medium.com/max/1024/0*_vIr8jhP3kAnxeeQ.png" /><figcaption>Magliano SS21 video</figcaption></figure><h3>Return to nature</h3><p>Ironically, a prevailing theme this fashion week was a “return to nature”, despite collections only being presented in the digital realm. Numerous brands either focused on nature as a guiding theme, or incorporated the natural environment into their collections in some capacity, whether it be floral motifs, lookbooks shot amongst vegetation, or plants physically attached to garments. This gravitation towards nature is ostensibly related to the desire to convey a deeper meaning and a sense of emotion with viewers via the internet, as times of crisis often result in a renewed appreciation for beauty, especially after being locked indoors for several months.</p><figure><img alt="Model poses for Davi" src="https://cdn-images-1.medium.com/max/600/0*Jp4KmLCDPxnfjsyc.jpg" /><figcaption>Davi</figcaption></figure><h3>Bohemian Inspiration</h3><p>A key inspiration for this back to nature theme is the 60s and 70s, which is logical, since the aesthetics of these epochs are defined by political upheaval and a questioning of the established order. Since we are experiencing both of these phenomena today, this free-spirited, bohemian sensibility ostensibly resonates more strongly than it would otherwise, manifesting through the physical garments in the form of paisley, patchwork, ikat patterns, fringe, tinted aviators, and loose, flowing silhouettes, shown by brands like Children of the Discordance, Isabel Marant, Greg Lauren, Etro, and Magliano. Tunics, knitwear, and espadrilles were also token elements of this theme, shown by the brands that were inspired by this free-spirited, bohemian mood.</p><figure><img alt="Model poses for Children of the Discordance" src="https://cdn-images-1.medium.com/max/687/0*FKuc1hqJqUqaY8og.jpg" /><figcaption>Children of the Discordance</figcaption></figure><h3>Hippy Streetwear</h3><p>Another iteration of this natural theme comes from a more streetwear perspective, with brands such as Blue Marble, Etudes, and MSGM combining t-shirts, hoodies, as well as more tailored garments with the typical “hippy” accoutrements, like natural-dyed textiles, beads, rope accessories, psychedelic prints, and vibrant colours paired with muted, “sun-drenched” tones. These details emanate a sense of joy and optimism, with vibrant colours and hallucinogenic motifs symbolising a type of rebirth, as we are entering a new phase of life following this period of confinement. Massimo Giorgetti, creative director of MSGM, states that “<a href="http://hero-magazine.com/shows/msgm-ss21/">for the first time in my life and in the life of the brand, I perceived the fall of the myth of the city as the place to be and the rise of a new desire for nature</a>”. Clearly, Giorgetti is not alone in this desire to be connected to our natural world and have a fresh start.</p><figure><img alt="Model poses for Blue Marble" src="https://cdn-images-1.medium.com/max/748/0*WA4Ra1KkyNTMe6bq.jpg" /><figcaption>Blue Marble</figcaption></figure><h3>Focus on Craftsmanship</h3><p>Lastly, a key trend was a gravitation towards artisanal materials and techniques, with an abundance of embellishment, knits, linen, woven textiles, and embroidery representing a renewed appreciation for the craftsmanship required to create such garments. CMMN SWDN, Ermenegildo Zegna, and Jacquemus are a few examples of those who incorporated these artisanal elements into their collections, combining these “crafty” details with tailoring to create a level of sophistication. Some staple garments amongst brands that explored this theme include espadrilles, tunics, and loose fitting pants, typically in earthy, muted tones.</p><figure><img alt="Model walks down runway for Jacquemus" src="https://cdn-images-1.medium.com/max/687/0*48-CJQgzWOG44_4w.jpg" /><figcaption>Jacquemus</figcaption></figure><p>Ultimately, this fashion week seemed to predict, at least in part, a return to a time where collections were smaller, craftsmanship was rightfully given the spotlight, and nature was directly reflected in the product. In other ways, tradition was challenged, with the digitalisation of many catwalks and look books giving access to more than only industry insiders. What we do know is that these trends inspire us to keep our roots in the ground and our eyes to the sky.</p><p><a href="https://heuritech.com/"><em>Heuritech</em></a><em> empowers fashion teams to monitor in real time both products and trends through cutting-edge image recognition technology applied on millions of social media images every day. If you want to know more, get in touch at info@heuritech.com</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d146fa21f63d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/heuritech/quarantine-rebirth-mens-fashion-week-review-ss21-d146fa21f63d">Quarantine Rebirth: Men’s Fashion Week Review SS21</a> was originally published in <a href="https://medium.com/heuritech">Heuritech, a Luxurynsight Company</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>