<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Archives Social media - Open Forecasting</title>
	<atom:link href="https://openforecast.org/category/social-media/feed/" rel="self" type="application/rss+xml" />
	<link>https://openforecast.org/category/social-media/</link>
	<description>How to look into the future</description>
	<lastBuildDate>Sun, 03 May 2026 10:18:09 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2015/08/cropped-usd-05-32x32.png&amp;nocache=1</url>
	<title>Archives Social media - Open Forecasting</title>
	<link>https://openforecast.org/category/social-media/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>smooth in python: ETS with explanatory variables</title>
		<link>https://openforecast.org/2026/05/05/smooth-in-python-ets-with-explanatory-variables/</link>
					<comments>https://openforecast.org/2026/05/05/smooth-in-python-ets-with-explanatory-variables/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Tue, 05 May 2026 08:03:37 +0000</pubDate>
				<category><![CDATA[ETS]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[smooth for Python]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[extrapolation methods]]></category>
		<category><![CDATA[smooth]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4128</guid>

					<description><![CDATA[<p>We continue our series of posts on the functions from the smooth package for Python/R. Today we will see how to enhance your exponential smoothing with explanatory variables. What? Yes, you heard me! Let&#8217;s dive in! We all know that in real life sales don&#8217;t just evolve over time on their own. Any univariate model, [&#8230;]</p>
<p>Message <a href="https://openforecast.org/2026/05/05/smooth-in-python-ets-with-explanatory-variables/">smooth in python: ETS with explanatory variables</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>We continue our series of posts on the functions from the smooth package for Python/R. Today we will see how to enhance your exponential smoothing with explanatory variables. What? Yes, you heard me! Let&#8217;s dive in!</p>
<p>We all know that in real life sales don&#8217;t just evolve over time on their own. Any univariate model, such as ARIMA or ETS is just a way to approximate a complex reality. In practice, there are many factors affecting the demand for your product. What would happen if the price on your product increases? What if you run a promotion (e.g. &#8220;Buy One, Get One Free&#8221;)? Your competitor&#8217;s strategy impacts the demand for your product as well&#8230; There&#8217;s lots of different factors, and some of them can be quite useful in demand forecasting. But can we join the dynamic univariate models with regression?</p>
<p>Yes, we can! Although ETS is thought as a pure univariate model, it is easy to extend to include explanatory variables. There are several great papers showing how it works (e.g. <a href="https://doi.org/10.1016/j.ijpe.2015.09.011">Kourentzes &#038; Petropoulos, 2016</a>), and in fact the <code>es()</code> function from the smooth package for R was used as a benchmark in <a href="https://doi.org/10.1016/j.ijforecast.2021.11.013">the M5 competition</a>.</p>
<p>So, consider a situation where you have weekly sales of a product with some recorded promotions (encoded as dummy variables). We will use a time series from the fcompdata package for Python. The first image shows how the series looks, the vertical lines show when promotions happen. The series itself seems to be seasonal, roughly repeating peaks and troughs every 52 observations (every year). Also, we see that there are two types of promotions, and when they happen sales tend to increase. So, including them should improve the model fit, and if the company decides to run promotions again, the model will forecast demand better. I will start by fitting the ETS(M,N,M) to the data:</p>
<pre class="decode">from smooth import ES
from fcompdata import PromoData

y = PromoData.y

model = ES(model="MNM", lags=52, holdout=True, h=13)
model.fit(y)
model.predict(h=13)
model.plot(7)</pre>
<p><strong>NOTE</strong>: PromoData has a specific structure with several attributes. PromoData.x contains the in-sample data, PromoData.xx has the holdout &#8211; this is consistent with the Mcomp package for R. The new features in python are:</p>
<ul>
<li>PromoData.y &#8211; concatenated training and test sets,</li>
<li>PromoData.xregx &#8211; matrix of explanatory variables for the training set,</li>
<li>PromoData.xregxx &#8211; matrix of explanatory variables for the test set,</li>
<li>PromoData.xreg &#8211; the full (concatenated) matrix of explanatory variables.</li>
</ul>
<p>The following image shows the model fit and the point forecasts from the ETS(M,N,M):</p>
<div id="attachment_4132" style="width: 310px" class="wp-caption aligncenter"><a href="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-04-17-smooth-posts-03-ETSX-02.png&amp;nocache=1"><img fetchpriority="high" decoding="async" aria-describedby="caption-attachment-4132" src="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-04-17-smooth-posts-03-ETSX-02-300x214.png&amp;nocache=1" alt="ETS(M,N,M) fit and forecast for the promotional data example" width="300" height="214" class="size-medium wp-image-4132" srcset="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-04-17-smooth-posts-03-ETSX-02-300x214.png&amp;nocache=1 300w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-04-17-smooth-posts-03-ETSX-02.png&amp;nocache=1 700w" sizes="(max-width: 300px) 100vw, 300px" /></a><p id="caption-attachment-4132" class="wp-caption-text">ETS(M,N,M) fit and forecast for the promotional data example</p></div>
<p>As expected, because the model does not take promotions into account, it fits the data as best as it can and produces forecasts that are oblivious of the potential external effects on sales. We can improve it by including the promotional dummies:</p>
<pre class="decode">X_train = PromoData.xreg
X_test =  PromoData.xregxx

model = ES(model="MNM", lags=52, holdout=True, h=13)
model.fit(y, X_train)
model.predict(h=13, X=X_test)
model.plot(7)</pre>
<div id="attachment_4131" style="width: 310px" class="wp-caption aligncenter"><a href="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-04-17-smooth-posts-03-ETSX-03.png&amp;nocache=1"><img decoding="async" aria-describedby="caption-attachment-4131" src="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-04-17-smooth-posts-03-ETSX-03-300x214.png&amp;nocache=1" alt="ETS(M,N,M) with explanatory variables" width="300" height="214" class="size-medium wp-image-4131" srcset="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-04-17-smooth-posts-03-ETSX-03-300x214.png&amp;nocache=1 300w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/05/2026-04-17-smooth-posts-03-ETSX-03.png&amp;nocache=1 700w" sizes="(max-width: 300px) 100vw, 300px" /></a><p id="caption-attachment-4131" class="wp-caption-text">ETS(M,N,M) with explanatory variables</p></div>
<p>The image above shows the fit and the point forecasts from the ETSX(M,N,M) model that now takes the promotions into account. This is quite an improvement in comparison with the previous one. Furthermore, if we can control when to have promotions and what types of promotions to run, we can change the values in the `X_test` matrix and see what demand to expected in that situation. So, this gives an analyst a tool for a more advanced sensitivity analysis.</p>
<p>Read more about the ETSX <a href="https://openforecast.org/adam/ADAMX.html">here</a>.<br />
Install smooth: <code>pip install smooth</code><br />
<a href="https://github.com/config-i1/smooth/wiki/Explanatory-Variables">ETSX wiki on github</a>.</p>
<p>Message <a href="https://openforecast.org/2026/05/05/smooth-in-python-ets-with-explanatory-variables/">smooth in python: ETS with explanatory variables</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/05/05/smooth-in-python-ets-with-explanatory-variables/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>smooth in python: ETS with model selection</title>
		<link>https://openforecast.org/2026/04/22/smooth-in-python-ets-with-model-selection/</link>
					<comments>https://openforecast.org/2026/04/22/smooth-in-python-ets-with-model-selection/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Wed, 22 Apr 2026 00:06:43 +0000</pubDate>
				<category><![CDATA[ETS]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[smooth for Python]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[ADAM]]></category>
		<category><![CDATA[extrapolation methods]]></category>
		<category><![CDATA[smooth]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4111</guid>

					<description><![CDATA[<p>As some of you have heard, the smooth package is now on PyPI. So, I&#8217;ve decided to write a series of posts showcasing how some of its functions work. We start with the basics, ETS. ETS stands for the &#8220;Error-Trend-Seasonal&#8221; model or ExponenTial Smoothing. It is a statistical model that relies on time series decomposition [&#8230;]</p>
<p>Message <a href="https://openforecast.org/2026/04/22/smooth-in-python-ets-with-model-selection/">smooth in python: ETS with model selection</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>As some of you have heard, the smooth package is now on PyPI. So, I&#8217;ve decided to write a series of posts showcasing how some of its functions work. We start with the basics, ETS.</p>
<p>ETS stands for the &#8220;Error-Trend-Seasonal&#8221; model or ExponenTial Smoothing. It is a statistical model that relies on time series decomposition and updates the unobserved states (level/trend/seasonal) based on the mistakes it makes. In a way, you can call it an adaptive model that changes its forecast based on the most recent available information. It is relatively simple to explain and work with, and it has performed well in a variety of competitions (M3, M4, M5, for example).</p>
<p>The smooth package implements an advanced form of ETS in the ADAM and a more basic one in the ES classes. In fact, ES is just a wrapper of ADAM, it is the conventional model, with just some tuning. Both support all 30 ETS models, have automated model selection and forecast combination, allow producing point forecasts and a variety of prediction intervals types. In fact, if you want a straightforward robust implementation of ETS, give ES a try.</p>
<p>Here&#8217;s how to use it in Python:</p>
<pre class="decode">from smooth import ES
from fcompdata import M3

# Pick a series from the M3 competition for demonstration
series = M3[2568]
y = series.x
freq = series.period

# Fit ES with the automatic model selection
model = ES(lags=freq, h=18, holdout=True)
model.fit(y)
print(model)</pre>
<p>Running this produces output similar to this:</p>
<pre>Time elapsed: 0.4 seconds
Model estimated using ES() function: ETS(MAM)
With backcasting initialisation
Distribution assumed in the model: Normal
Loss function type: likelihood; Loss function value: 724.8524
Persistence vector g:
 alpha   beta  gamma
0.0065 0.0000 0.0000
Sample size: 98
Number of estimated parameters: 4
Number of degrees of freedom: 94
Information criteria:
      AIC      AICc       BIC      BICc
1457.7047 1458.1348 1468.0446 1469.0306

Forecast errors:
ME: -580.9985; MAE: 604.0204; RMSE: 710.5457
sCE: -149.9347%; Asymmetry: -2.5%; sMAE: 8.6598%; sMSE: 1.0378%
MASE: 0.2653; RMSSE: 0.2452; rMAE: 0.2555; rRMSE: 0.2163</pre>
<p>A few things worth noting from the output:</p>
<ul>
<li>ES automatically selected ETS(MAM) based on the AICc value &#8211; a multiplicative error, additive trend, multiplicative seasonality model &#8211; as the best fit</li>
<li>It used backcasting for the model initialisation (default), which speeds up the process and requires fewer parameters to estimate</li>
<li>It kept the last 18 observation for the holdout, produced autoforecasts for it and calculated several forecast errors. This is handy if you want to directly compare different smooth models on a time series.</li>
</ul>
<p>But why are we here? We want to forecast! So, here it is:</p>
<pre class="decode">
model.predict(h=18, interval="prediction")
model.plot(7)
</pre>
<p>This should produce an image similar to the one attached to the post. As simple as that.</p>
<p>Now it&#8217;s your turn! :)</p>
<p>🔗 Install smooth: pip install smooth<br />
📖 <a href="https://github.com/config-i1/smooth/wiki">smooth wiki</a></p>
<p>Message <a href="https://openforecast.org/2026/04/22/smooth-in-python-ets-with-model-selection/">smooth in python: ETS with model selection</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/04/22/smooth-in-python-ets-with-model-selection/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>The real Dunning-Kruger effect</title>
		<link>https://openforecast.org/2026/03/23/the-real-dunning-kruger-effect/</link>
					<comments>https://openforecast.org/2026/03/23/the-real-dunning-kruger-effect/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Mon, 23 Mar 2026 09:03:35 +0000</pubDate>
				<category><![CDATA[Social media]]></category>
		<category><![CDATA[statistics]]></category>
		<category><![CDATA[theory]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4096</guid>

					<description><![CDATA[<p>Many of you have seen this image on the Internet — I&#8217;ve seen it myself a few times on LinkedIn lately. People say it depicts the &#8220;Dunning-Kruger&#8221; effect&#8230; But did you know this is actually an internet meme with little to do with the original paper? Here is one of the recent examples, a screenshot [&#8230;]</p>
<p>Message <a href="https://openforecast.org/2026/03/23/the-real-dunning-kruger-effect/">The real Dunning-Kruger effect</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Many of you have seen this image on the Internet — I&#8217;ve seen it myself a few times on LinkedIn lately. People say it depicts the &#8220;Dunning-Kruger&#8221; effect&#8230; But did you know this is actually an internet meme with little to do with the original paper?</p>
<p>Here is one of the recent examples, a screenshot of <a href="https://www.linkedin.com/posts/fotios-petropoulos-04536023_dear-mr-i-reduce-forecast-error-by-30-share-7437246645530140672-NXnT">the post of Fotios Petropoulos</a> about the effect.</p>
<div id="attachment_4098" style="width: 282px" class="wp-caption aligncenter"><a href="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/03/2026-03-22-Dunning-Kruger-Petropoulos.png&amp;nocache=1"><img decoding="async" aria-describedby="caption-attachment-4098" src="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/03/2026-03-22-Dunning-Kruger-Petropoulos-272x300.png&amp;nocache=1" alt="A LinkedIn post by Fotios Petropoulos" width="272" height="300" class="size-medium wp-image-4098" srcset="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/03/2026-03-22-Dunning-Kruger-Petropoulos-272x300.png&amp;nocache=1 272w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/03/2026-03-22-Dunning-Kruger-Petropoulos.png&amp;nocache=1 556w" sizes="(max-width: 272px) 100vw, 272px" /></a><p id="caption-attachment-4098" class="wp-caption-text">A LinkedIn post by Fotios Petropoulos</p></div>
<p>In the original paper, <a href="https://psycnet.apa.org/doi/10.1037/0022-3514.77.6.1121">Kruger and Dunning (1999)</a> ran experiments with undergraduates on humour, logical reasoning, and grammar. Participants completed a test and estimated their percentile rank. The authors then sorted participants into four quartiles by actual performance and computed averages for actual and self-assessed performance for each quartile. The plots in their paper &#8211; the real Dunning–Kruger effect &#8211; are just four data points per line, not a smooth curve over a learning journey (second image).</p>
<p>What did they find? People in the bottom quartile substantially overestimated their performance, often believing they were average or above. Top performers slightly underestimated their standing. The key finding is an asymmetry in miscalibration: low performers overestimate, high performers slightly underestimate.</p>
<p>This has almost nothing to do with the popular &#8220;experience vs. confidence&#8221; image. The original X‑axis is performance quartile at a single point in time; the meme&#8217;s X‑axis is a vague notion of &#8220;experience&#8221; through time. The original Y‑axis is the assessed test percentile; the meme&#8217;s is a free‑floating &#8220;confidence&#8221; construct. In the actual data, perceived performance increases with actual performance &#8211; there is no early spike, no &#8220;valley of despair,&#8221; no &#8220;slope of enlightenment.&#8221; That swooping curve is an internet-era graphic never reported by Kruger and Dunning, and it misleadingly frames the effect as a personal development trajectory the paper never studied.</p>
<p>There is also a serious critique of the original paper from statistical point of view. For example, <a href="https://doi.org/10.1016/j.intell.2020.101449">Gignac and Zajenkowski (2020)</a> showed that sorting people into quartiles and plotting average self-assessment against average performance can, by itself, generate the characteristic pattern &#8211; purely as a statistical artefact. In their own empirical data, miscalibration was roughly constant across ability levels, consistent with measurement noise rather than a special cognitive deficit in low performers. You can actually reproduce the pattern using two random uncorrelated variables. Here is a simple example in R:</p>
<pre class="decode">set.seed(41)

x <- rnorm(10000, 100, 10)
y <- rnorm(10000, 100, 10)
plot(x,y)
xQ <- quantile(x)
yQ <- quantile(y)

yMeans <- xMeans <- vector("numeric",4)

for(i in 1:4){
    xMeans[i] <- mean(x[x<xQ[i+1] &#038; x>xQ[i]])
    yMeans[i] <- mean(y[x<xQ[i+1] &#038; x>xQ[i]])
}

plot(1:4, xMeans, type="b", ylim=range(xMeans,yMeans),
     xlab="Real performance", ylab="Assessed performance",
     lwd=2)
lines(yMeans, lwd=2, lty=2)
points(yMeans, lwd=2)
legend("topleft",
       legend=c("Actual performance", "Assessed performance"),
       lwd=2, lty=c(1,2), pch=1)</pre>
<p>Which produces the image like this:</p>
<div id="attachment_4100" style="width: 310px" class="wp-caption aligncenter"><a href="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/03/2026-03-22-Dunning-Kruger-R.png&amp;nocache=1"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-4100" src="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/03/2026-03-22-Dunning-Kruger-R-300x175.png&amp;nocache=1" alt="Dunning-Kruger plot reproduction" width="300" height="175" class="size-medium wp-image-4100" srcset="https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/03/2026-03-22-Dunning-Kruger-R-300x175.png&amp;nocache=1 300w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/03/2026-03-22-Dunning-Kruger-R-1024x597.png&amp;nocache=1 1024w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/03/2026-03-22-Dunning-Kruger-R-768x448.png&amp;nocache=1 768w, https://openforecast.org/wp-content/webpc-passthru.php?src=https://openforecast.org/wp-content/uploads/2026/03/2026-03-22-Dunning-Kruger-R.png&amp;nocache=1 1200w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a><p id="caption-attachment-4100" class="wp-caption-text">Dunning-Kruger plot reproduction</p></div>
<p>If you introduce a correlation between the two variables, the images starts looking even more similar to the ones from the original paper.</p>
<p>So there might be a real effect &#8211; many follow-up studies have measured it with more rigorous tools &#8211; but Dunning and Kruger&#8217;s method was not the right one to establish it. And that image with experience vs confidence is just a meme and a serious misconception that should not be used.</p>
<p>P.S. If you wonder who the &#8220;leading expert&#8221; that Fotios Petropoulos refers to in his post is &#8211; it&#8217;s me. Not sure why he doesn&#8217;t tag me properly.</p>
<p>Message <a href="https://openforecast.org/2026/03/23/the-real-dunning-kruger-effect/">The real Dunning-Kruger effect</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/03/23/the-real-dunning-kruger-effect/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>There&#8217;s no such thing as &#8220;deterministic forecast&#8221;</title>
		<link>https://openforecast.org/2026/03/02/there-s-no-such-thing-as-deterministic-forecast/</link>
					<comments>https://openforecast.org/2026/03/02/there-s-no-such-thing-as-deterministic-forecast/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Mon, 02 Mar 2026 22:45:31 +0000</pubDate>
				<category><![CDATA[Social media]]></category>
		<category><![CDATA[Theory of forecasting]]></category>
		<category><![CDATA[extrapolation methods]]></category>
		<category><![CDATA[statistics]]></category>
		<category><![CDATA[theory]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4081</guid>

					<description><![CDATA[<p>Sometimes I see people referring to a &#8220;deterministic&#8221; forecast, and I have some personal issues with this. Because if you apply a model to data then there is nothing deterministic about your forecasts! In many contexts, &#8220;deterministic&#8221; has a precise meaning: no randomness, no uncertainty. A deterministic solution to an optimisation problem (e.g. linear programming) [&#8230;]</p>
<p>Message <a href="https://openforecast.org/2026/03/02/there-s-no-such-thing-as-deterministic-forecast/">There&#8217;s no such thing as &#8220;deterministic forecast&#8221;</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Sometimes I see people referring to a &#8220;deterministic&#8221; forecast, and I have some personal issues with this. Because if you apply a model to data then there is nothing deterministic about your forecasts!</p>
<p>In many contexts, &#8220;deterministic&#8221; has a precise meaning: no randomness, no uncertainty. A deterministic solution to an optimisation problem (e.g. linear programming) implies that there are no random inputs or outputs once the model and its parameters are fixed. Forecasting is different. As <a href="https://onlinelibrary.wiley.com/doi/10.1002/(SICI)1099-131X(199612)15:7%3C495::AID-FOR640%3E3.0.CO;2-O">Chatfield</a> and many others have pointed out, forecasting has multiple sources of uncertainty, and there is essentially zero chance that the future will unfold exactly as any single number suggests.</p>
<p>Yes, some people use &#8220;deterministic&#8221; as a synonym for &#8220;point forecast&#8221;. But that label is still misleading, because a point forecast is not uncertainty-free &#8211; it is just one summary of a predictive distribution (often the conditional mean, sometimes the median or another functional).</p>
<p>Here’s a quick reality check you can do yourself. Take a dataset, apply your model, and write down the point forecast for the next few observations. Now add one new observation, re-estimate, and forecast again (the image in this post depicts exactly that, but with 50 forecasts produced on different subsamples of data). The point forecast will change unless you are dealing with an exotic situation with non-random data (e.g. every day, you sell exactly 100 units). So, which of the two was the &#8220;deterministic&#8221; forecast? If forecasts were truly deterministic in the strict sense, you would not get multiple plausible values from small, reasonable changes in the sample.</p>
<p>This happens because any forecasting method (statistical or ML) depends on data and on modelling choices: parameter estimation, feature selection, splitting rules, tuning, even decisions like &#8220;use α=0.1&#8221;. Those choices can be fixed across samples of data, but fixing them does not remove uncertainty &#8211; it only hides it. The randomness is still there in the data and in the fact that we only observe a sample of it.</p>
<p>So when you see someone mentioning &#8220;deterministic forecast&#8221;, it&#8217;s worth translating it mentally to: &#8220;a point forecast, probably a conditional mean&#8221;. If you care about decisions and risk, you should know that there is an uncertainty associated with this so called &#8220;deterministic forecast&#8221;, and that it should not be ignored. But this is a topic for another discussion in another post.</p>
<p>Message <a href="https://openforecast.org/2026/03/02/there-s-no-such-thing-as-deterministic-forecast/">There&#8217;s no such thing as &#8220;deterministic forecast&#8221;</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/03/02/there-s-no-such-thing-as-deterministic-forecast/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Scaling of error measures</title>
		<link>https://openforecast.org/2026/02/23/scaling-of-error-measures/</link>
					<comments>https://openforecast.org/2026/02/23/scaling-of-error-measures/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Mon, 23 Feb 2026 13:36:12 +0000</pubDate>
				<category><![CDATA[Forecast evaluation]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[Theory of forecasting]]></category>
		<category><![CDATA[error measures]]></category>
		<category><![CDATA[theory]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=4054</guid>

					<description><![CDATA[<p>Apparently, we need to talk about scaling of error measures because this is not as obvious as it seems. In forecasting literature, since early days of the area, there has been a general consensus that the forecast errors from the individual time series should not be analysed and aggregated as is. This is because you [&#8230;]</p>
<p>Message <a href="https://openforecast.org/2026/02/23/scaling-of-error-measures/">Scaling of error measures</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Apparently, we need to talk about scaling of error measures because this is not as obvious as it seems.</p>
<p>In forecasting literature, since early days of the area, there has been a general consensus that the forecast errors from the individual time series should not be analysed and aggregated as is. This is because you can have very different time series capturing dynamics of very different processes.</p>
<p>Indeed, if you forecast sales of apples in kilograms, your actual value would be apples in kilograms, and your point forecast would also be in the same units. Subtracting one from another tells us how many kilograms of apples we missed with the forecast we produced. But if we then take the average between forecast errors for apples and beer, we would be aggregating things in different units, which contradicts some basic aggregating principles.</p>
<p>Furthermore, if the company sells thousands of kilograms of apples and jet engines, aggregating forecast errors on those (e.g. 3000 vs 3) might introduce all types of issues, because the models performance on apples might mask the performance of the model on jet engines. Still, the jet engines are much more expensive than apples and getting them accurately might be more important for the company than forecasting apples.</p>
<p>So, forecasting literature has agreed that the forecast errors need to be somehow scaled to make the errors unitless and not to distort performance of models on time series with different volumes. There are several ways of doing that, including the poor ones and reasonable ones. The state of the art at the moment is to divide error measures by some in-sample statistics to avoid potential holdout-sample distortion. Using mean absolute differences (MAD) for this (thus ending up with MASE or RMSSE) is considered as a standard. A couple of years ago, <a href="/2019/08/25/are-you-sure-youre-precise-measuring-accuracy-of-point-forecasts/">I have written a post about advantages and disadvantages of several scaling methods</a>.</p>
<p>But there is one method that I haven&#8217;t looked at and which is not very well discussed in the forecasting literature. It relies on the monetary value of forecasts. We could multiply each individual forecast error &#8220;e&#8221; by the price of the product &#8220;p&#8221; (thus moving to the missed income per product) and then divide everything by the overall income (price times quantity) from different products. This can be written as:</p>
<p>\begin{equation}<br />
\text{monetary Mean Error} = \frac{\sum_{j=1}^n (p_j \times e_j)} {\sum_{j=1}^n (p_j \times q_j)}<br />
\end{equation}</p>
<p>(the above formula can be modified to have squares or absolute values of the error). This way we switch from the original units to the monetary values and each error would tell you the percentage of the missed income in the overall one. This is a useful measure because it connects models performance with some managerial decisions and it takes the value of product into account (thus we do not mask the expensive jet engines with cheap apples).</p>
<p>However, it might have a potential issue similar to what the MAE/Mean or wMAPE has: if the sales of the product are not stationary, the denominator would change, thus driving the proportion either up or down, irrespective of how good the forecast is. I am not sure whether this needs to be addressed, because there is an argument that if the income from a product has increased and the error hasn&#8217;t changed, then this means that the proportion of the missed income decreased, which makes sense. But if we need to address this, we can switch to the MAD multiplied by price in the denominator to address this issue. In fact, this was sort of done in <a href="https://doi.org/10.1016/j.ijforecast.2021.11.013">M5 competition</a> that used a weighted RMSSE, relying on the income from each product over the last 4 weeks of data.</p>
<p>But here is one more interesting thing about this error measure. If we <strong>assume that prices for all products are exactly the same</strong>, they will disappear from the numerator and the denominator, leaving us with just sum of errors divided by the overall sales of all products. This still maintains the original idea of the proportion of the missed income, but now has a very strong assumption, which is probably not correct in the real life (apples and engines for the same price?). Furthermore, this would mask the performance of the model for the expensive products again. I personally don&#8217;t like this measure and find the assumption unrealistic and potentially misleading. Having said that, I can see some cases where this could still be acceptable and useful (e.g. similar products with similar dynamics and similar prices).</p>
<p>Summarising:</p>
<ol>
<li>If you are conducting a forecasting experiment without a specific context, I&#8217;d recommend using RMSSE or some other similar measure with scaling.</li>
<li>If you have prices of products, income-based scaling might be more informative.</li>
<li>Setting all prices to the same value does not sound appealing to me, but I understand that there is a context where this might work.</li>
</ol>
<p>Message <a href="https://openforecast.org/2026/02/23/scaling-of-error-measures/">Scaling of error measures</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/02/23/scaling-of-error-measures/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Forecasting Competitions Datasets in Python</title>
		<link>https://openforecast.org/2026/01/26/forecasting-competitions-datasets-in-python/</link>
					<comments>https://openforecast.org/2026/01/26/forecasting-competitions-datasets-in-python/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Mon, 26 Jan 2026 09:29:25 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[Competitions]]></category>
		<category><![CDATA[time series]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=3955</guid>

					<description><![CDATA[<p>Here is one small, unexpected piece of news: I now have my first package on PyPI! It’s called fcompdata, and let me tell you a little bit about it. When I test my functions in R, I usually use the M1, M3, and tourism competition datasets because they are diverse enough, containing seasonal, non-seasonal, trended, [&#8230;]</p>
<p>Message <a href="https://openforecast.org/2026/01/26/forecasting-competitions-datasets-in-python/">Forecasting Competitions Datasets in Python</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Here is one small, unexpected piece of news: I now have my first package on PyPI! It’s called <a href="https://pypi.org/project/fcompdata/">fcompdata</a>, and let me tell you a little bit about it.</p>
<p>When I test my functions in R, I usually use the M1, M3, and tourism competition datasets because they are diverse enough, containing seasonal, non-seasonal, trended, and non-trended time series of different frequencies (yearly, quarterly, monthly). The total number of these series is 5,315, which is large enough but not too heavy for my PC. So, when I run something on those datasets, it becomes like a stress test for the forecasting approach, and I can see where it fails and how it can be improved. I consider this type of test a toy experiment — something to do before applying anything to real-world data.</p>
<p>In R, there are the Mcomp and Tcomp packages that contain these datasets, and I like how they are organised. You can do something like this:</p>
<pre class="decode">series <- Mcomp::M3[[2568]]
ourModel <- adam(series$x)
ourForecast <- forecast(model, h=series$h)
ourError <- series$xx - ourForecast$mean</pre>
<p>Each series from the dataset contains all the necessary attributes to run the experiment without trouble. This is easy and straightforward. Plus, I don’t need to download or organise any data — I just use the installed package.</p>
<p>When I started vibe coding in Python, I realised that I missed this functionality. So, with the help of Claude AI, I created a Python script to download the data from the Monash repository and organise it the way I liked. But then I realised two things, which motivated me to package it:</p>
<ol>
<li>I needed to drag this script with me to every project I worked on. It would be much easier to just run "pip install fcompdata" and forget about everything else.</li>
<li>Some series in the Monash repository differ from those in the R package.</li>
</ol>
<p>Wait, what?! Really?</p>
<p>Yes. The difference is tiny — it’s a matter of rounding. For example, series N350 from the M1 competition data (T169 from the quarterly data subset) has three digits in the R package and only two if downloaded from the Monash repository (Zenodo website).</p>
<p>Who cares?! It's just one digit difference, right?</p>
<p>Well, if you want to reproduce results across different languages, this tiny difference might become your nightmare. So, I care (and probably nobody else in the world), and I decided to create a proper Python package. You can now do this in Python and relax:</p>
<pre class="decode">pip install fcompdata

from fcompdata import M1, M3, Tourism
series = M3[2568]</pre>
<p>The "series" object is now an instance of the MCompSeries class that has the same attributes as in R: series.x, series.h, series.xx, etc.</p>
<p>As simple as that!</p>
<p>One more thing: I’ve added support for the M4 competition data, which — when imported — will be downloaded and formatted properly. The dataset is large (100k time series), and I personally don’t like it. I even wrote <a href="https://openforecast.org/2020/03/01/m-competitions-from-m4-to-m5-reservations-and-expectations/">a post about it back in 2020</a>. But if I want the package to be useful to a wider audience, I shouldn’t impose my personal preferences — you should decide for yourselves whether to use it or not.</p>
<p>P.S. Submitting to PyPI gave me a good understanding of the submission process for Python and why it can be such a mess. My package was published just a few seconds after submission — nobody looked at it, nobody ran any tests. CRAN does a variety of checks to ensure you don’t submit garbage. PyPI doesn’t care. So, I’ve gained more respect for CRAN after submitting this package to PyPI.</p>
<p>Message <a href="https://openforecast.org/2026/01/26/forecasting-competitions-datasets-in-python/">Forecasting Competitions Datasets in Python</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/01/26/forecasting-competitions-datasets-in-python/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Risky business: how to select your model based on risk preferences</title>
		<link>https://openforecast.org/2026/01/19/risky-business-how-to-select-your-model-based-on-risk-preferences/</link>
					<comments>https://openforecast.org/2026/01/19/risky-business-how-to-select-your-model-based-on-risk-preferences/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Mon, 19 Jan 2026 11:28:04 +0000</pubDate>
				<category><![CDATA[Applied forecasting]]></category>
		<category><![CDATA[Papers]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[Theory of forecasting]]></category>
		<category><![CDATA[error measures]]></category>
		<category><![CDATA[extrapolation methods]]></category>
		<category><![CDATA[Information criteria]]></category>
		<category><![CDATA[model combination]]></category>
		<category><![CDATA[model selection]]></category>
		<category><![CDATA[papers]]></category>
		<category><![CDATA[theory]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=3950</guid>

					<description><![CDATA[<p>What do you use for model selection? Do you select the best model based on its cross-validated performance, or do you use in-sample measures like AIC? If so, there is a way to improve your selection process further. JORS recently published the paper of Nikos Kourentzes and I based on a simple but powerful idea: [&#8230;]</p>
<p>Message <a href="https://openforecast.org/2026/01/19/risky-business-how-to-select-your-model-based-on-risk-preferences/">Risky business: how to select your model based on risk preferences</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>What do you use for model selection? Do you select the best model based on its cross-validated performance, or do you use in-sample measures like AIC? If so, there is a way to improve your selection process further.</p>
<p>JORS recently published the paper of Nikos Kourentzes and I based on a simple but powerful idea: instead of using summary statistics (like the mean RMSE of cross-validated errors), you should consider the entire distribution and choose a specific quantile. This aligns with <a href="https://openforecast.org/2024/03/27/what-does-lower-error-measure-really-mean/">my previous post on error measures</a>, but here is the core intuition:</p>
<p>The distribution of error measures is almost always asymmetric. If you only look at the average, you end up with a &#8220;mean temperature in the hospital&#8221; statistic, which doesn&#8217;t reflect how models actually behave. Some models perform great on most series but fail miserably on a few.</p>
<p>What can we do in this case? We can look at quantiles of distribution.</p>
<p>For example, if we use 84th quantile, we compare the models based on their &#8220;bad&#8221; performance, situations where they fail and produce less accurate forecasts. If you choose the best performing model there, you will end up with something that does not fail as much. So your preferences for the model become risk-averse in this situation.</p>
<p>If you focus on the lower quantile (e.g. 16th), you are looking at models that do well on the well-behaved series and ignore how they do on the difficult ones. So, your model selection preferences can be described as risk-tolerant, because you are accept that the best performing model might fail on a difficult time series.</p>
<p>Furthermore, the median (50th quantile, the middle of sample), corresponds to the risk-neutral situation, because it ignores the tails of the distribution.</p>
<p>What about the mean? This is a risk-agnostic strategy, because it says nothing about the performance on the difficult or easy time series &#8211; it takes everything and nothing in it at the same time, hiding the true risk profile.</p>
<p>So what?</p>
<p>In the paper, we show that using a risk-averse strategy tends to improve overall forecasting accuracy in day-to-day situations. Conversely, a risk-tolerant strategy can be beneficial when disruptions are anticipated, as standard models are likely to fail anyway.</p>
<p>So, next time you select a model, think about the measure you are using. If it’s just the mean RMSE, keep in mind that you might be ignoring the inherent risks of that selection.</p>
<p>P.S. While the discussion above applies to the distribution of error measures, our paper specifically focused on point AIC (in-sample performance). But it is a distance measure as well, so the logic explained above holds.</p>
<p>P.P.S. Nikos wrote a <a href="https://www.linkedin.com/posts/nikos-kourentzes-3660515_forecasting-datascience-analytics-activity-7414687127269007360-pLAh">post about this paper here</a>.</p>
<p>P.P.P.S. And here is <a href="https://github.com/trnnick/working_papers/blob/fd1973624e97fc755a9c2401f05c78b056780e34/Kourentzes_2026_Incorporating%20risk%20preferences%20in%20forecast%20selectionk.pdf">the link to the paper</a>.</p>
<p>Message <a href="https://openforecast.org/2026/01/19/risky-business-how-to-select-your-model-based-on-risk-preferences/">Risky business: how to select your model based on risk preferences</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2026/01/19/risky-business-how-to-select-your-model-based-on-risk-preferences/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AID paper rejected from the IJPR</title>
		<link>https://openforecast.org/2025/11/14/aid-paper-rejected-from-the-ijpr/</link>
					<comments>https://openforecast.org/2025/11/14/aid-paper-rejected-from-the-ijpr/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Fri, 14 Nov 2025 11:12:16 +0000</pubDate>
				<category><![CDATA[Papers]]></category>
		<category><![CDATA[Social media]]></category>
		<category><![CDATA[intermittent demand]]></category>
		<category><![CDATA[papers]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=3941</guid>

					<description><![CDATA[<p>So, our paper with Anna Sroginis got rejected from a special issue of the International Journal of Production Research after a second round of revision. And here is what I think about this! First things first, why am I writing this post? I want to share failures with the community, because I am tired of [&#8230;]</p>
<p>Message <a href="https://openforecast.org/2025/11/14/aid-paper-rejected-from-the-ijpr/">AID paper rejected from the IJPR</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>So, <a href="/2025/04/11/svetunkov-sroginis-2025-model-based-demand-classification/">our paper with Anna Sroginis</a> got rejected from a special issue of the International Journal of Production Research after a second round of revision. And here is what I think about this!</p>
<p>First things first, <strong>why am I writing this post</strong>? I want to share failures with the community, because I am tired of all the success stories. It is okay not to win, and this happens much more often than it seems.</p>
<p>Now, about the paper. In the first round of revisions, four reviewers looked at it and provided their comments. We expanded the paper accordingly, making it now 46 pages long (ouch!). We introduced inventory simulations and showed how using some basic principles improves forecasting accuracy and can lead to a reduction in inventory costs.</p>
<p>In the second round, the AE added one more reviewer. After careful consideration, two of the reviewers recommended major revisions, while the other two suggested a strong rejection, claiming that the paper does not make new and significant contributions to the production research literature.</p>
<p>Obviously, I disagree with this evaluation. Based on the reviewers’ comments, I have a feeling they didn’t read the paper in full (their main concerns relate to Section 3, and some of these could have been resolved if they had reached Section 5). But this probably also means that the paper in its current state is too big and needs to be rewritten to become more focused. Maybe this is what confused the reviewers.</p>
<p>So, what&#8217;s next?</p>
<p>We will amend it to address the reviewers’ comments, shorten it a bit to make it more focused, and then submit to another OR-related journal.</p>
<p>And while we are doing that, I have <a href="https://arxiv.org/abs/2504.05894v2">updated the arXiv version of the paper</a> to show what we did after the first round, and here is a brief summary of the main findings:</p>
<ul>
<li>Using a stockout dummy variable and capturing the level of data correctly (removing the effect of stockouts) improves the accuracy of forecasting approaches;</li>
<li>The stockouts detection should be done for both the training and the test sets. If the series with stockouts are not removed from the test set, the forecasts would be evaluated incorrectly;</li>
<li>Splitting the demand into demand sizes and demand occurrence, producing forecasts for each of the parts and then combining the result substantially improves the accuracy;</li>
<li>Using the feature for regular/intermittent demand improves the forecasting accuracy, but does not seem to impact the inventory performance. Note that this separation is straightforward in AID: if after removing the stockouts, there are some zeroes left, the demand is identified as intermittent;</li>
<li>The further split into smooth/lumpy leads to slight improvements in terms of accuracy, without a substantial impact on the inventory;</li>
<li>The split into count/fractional demand does not bring value in terms of forecasting accuracy or inventory performance.</li>
</ul>
<p>Message <a href="https://openforecast.org/2025/11/14/aid-paper-rejected-from-the-ijpr/">AID paper rejected from the IJPR</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2025/11/14/aid-paper-rejected-from-the-ijpr/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Several crucial steps in demand forecasting with ML</title>
		<link>https://openforecast.org/2025/10/08/several-crucial-steps-in-demand-forecasting-with-ml/</link>
					<comments>https://openforecast.org/2025/10/08/several-crucial-steps-in-demand-forecasting-with-ml/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Wed, 08 Oct 2025 10:32:41 +0000</pubDate>
				<category><![CDATA[Social media]]></category>
		<category><![CDATA[Theory of forecasting]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=3935</guid>

					<description><![CDATA[<p>When I read posts written by some ML experts, I sometimes notice that they either overlook or do not clearly explain a few crucial steps in demand forecasting. In this post, I want to highlight the three most important ones based on my personal experience. First and foremost, stationarity (see the proper definition of the [&#8230;]</p>
<p>Message <a href="https://openforecast.org/2025/10/08/several-crucial-steps-in-demand-forecasting-with-ml/">Several crucial steps in demand forecasting with ML</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>When I read posts written by some ML experts, I sometimes notice that they either overlook or do not clearly explain a few crucial steps in demand forecasting. In this post, I want to highlight the three most important ones based on my personal experience.</p>
<p>First and foremost, <strong>stationarity</strong> (see the proper definition of the term <a href="/adam/ARIMAIntro.html">here</a>). Time series often exhibit either a changing level or clear trends. While some models (such as ETS) take care of that directly via specific components, others need some preliminary steps before being applied. The simplest thing one can do is to take differences of the original data if it shows any form of non-stationarity and model the rates of change instead of just demand. For ML, this is extremely important because typical approaches (such as decision trees, k-NN, neural networks) cannot extrapolate. So, getting rid of the trend and/or ensuring that the level does not change over time will help ML approaches do the job they are supposed to do. And don&#8217;t use the global trend (see image in the post), as time series rarely exhibit a constant increase or decrease. In real life, the trend is usually stochastic, implying that the average sales change at a varying rate, not a fixed one.</p>
<p>Second, real time series often exhibit <strong>heteroscedasticity</strong> (i.e. the variance of the data increases with the level). The simplest way to stabilise the variance is to take logarithms of the data. This is not a universal solution, but it works in many cases. This way, the error in the model should have a constant variance. A more advanced approach is to use the Box-Cox transformation, but this requires estimating the parameter lambda, which is not always straightforward. The main issue with this arises when working with intermittent demand, where some unpredictable zeroes occur (the logarithm of zero equals -infinity). In that case, you might want to take logarithms of demand sizes (non-zero values) instead of the demand itself and switch to a mixture model. Another simple but inelegant trick is to add one to every observation and then take logarithms. This works but breaks my heart.</p>
<p>Third, <strong>seasonality</strong> is extremely important in time series. There are many ways one can capture it. The simplest is by introducing dummy variables, but this might cause issues because, in reality, seasonality often changes over time (see <a href="/2025/09/22/evolving-seasonality/">this recent post</a>). So, a better way of capturing it is either by extracting the seasonal component from STL or ETS and using it as a feature or by using the lagged values of your data. Depending on the specific situation and approach, there can be many other ways of capturing seasonality, and frankly, I struggle to come up with a universal one.</p>
<p>Bonus: if you work with intermittent demand, splitting it into demand sizes and demand occurrence might boost the accuracy of your approach if the underlying levels are captured correctly. Anna Sroginis and I show this improvement for LightGBM, regression, and simple local level approaches <a href="/2025/04/11/svetunkov-sroginis-2025-model-based-demand-classification/">in our paper</a> (currently under revision).</p>
<p>P.S. Kandrika and I will deliver a course on &#8220;Demand Forecasting Principles with examples in R&#8221; in November, where we will discuss these and other important aspects of demand forecasting. You can still sign up for it <a href="https://www.lancaster.ac.uk/centre-for-marketing-analytics-and-forecasting/grow-with-us/demand-forecasting-with-r/">here</a></p>
<p>Message <a href="https://openforecast.org/2025/10/08/several-crucial-steps-in-demand-forecasting-with-ml/">Several crucial steps in demand forecasting with ML</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2025/10/08/several-crucial-steps-in-demand-forecasting-with-ml/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Evolving seasonality</title>
		<link>https://openforecast.org/2025/09/22/evolving-seasonality/</link>
					<comments>https://openforecast.org/2025/09/22/evolving-seasonality/#respond</comments>
		
		<dc:creator><![CDATA[Ivan Svetunkov]]></dc:creator>
		<pubDate>Mon, 22 Sep 2025 19:21:09 +0000</pubDate>
				<category><![CDATA[Social media]]></category>
		<category><![CDATA[Theory of forecasting]]></category>
		<category><![CDATA[extrapolation methods]]></category>
		<category><![CDATA[Seasonality]]></category>
		<guid isPermaLink="false">https://openforecast.org/?p=3928</guid>

					<description><![CDATA[<p>Here is another fascinating aspect of the seasonal profile in your data: it can evolve over time due to changing consumer preferences. How so? Let me explain. I&#8217;ve worked with a couple of companies where there were some examples of data with drastically changing seasonal patterns over just a few years. For example, Before Covid [&#8230;]</p>
<p>Message <a href="https://openforecast.org/2025/09/22/evolving-seasonality/">Evolving seasonality</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Here is another fascinating aspect of the seasonal profile in your data: it can evolve over time due to changing consumer preferences. How so? Let me explain.</p>
<p>I&#8217;ve worked with a couple of companies where there were some examples of data with drastically changing seasonal patterns over just a few years. For example, Before Covid (BC), the consumer behaviour could be different than After the Disruption (AD): people started ordering online some products that they used to buy in shops. Some practitioners told me that the seasonal patterns in their data had changed so dramatically that historical data BC had become practically useless.</p>
<p>Why is this important?</p>
<p>If you don&#8217;t recognise that the seasonal patterns can change and simply use seasonal dummy variables (for example, in regression or decision trees), you&#8217;ll run into problems, as these approaches won&#8217;t capture the evolving profile. The same applies to classical decomposition (see <a href="/adam/ClassicalDecomposition.html">Section 3.2 of ADAM</a>), since it assumes a fixed seasonal structure. In fact, any model that assumes fixed seasonality would fail in this situation, and you may not even notice (see image in the post, where the model fails to capture the profile correctly because it assumes that it is fixed).</p>
<p>What can we do with that?</p>
<p>The solution is to use approaches that allow seasonality to evolve over time. ARIMA and ETS handle this via their parameters, while STL decomposition produces a dynamic seasonal profile. In regression or decision trees, you could incorporate lagged sales to partially account for this, or bring in the seasonal component from STL/ETS as an additional feature.</p>
<p>All good? Not quite, because there is a nasty small grey elephant hidden in this room.</p>
<p>Even if your chosen method allows seasonality to evolve, you must ensure that forecasting uncertainty reflects this properly. If the seasonal pattern in your training set changed drastically, what prevents it from shifting again in the test set? This is particularly critical if you need predictive distributions, such as for setting safety stock levels or generating prediction intervals. Ignoring the fact that the seasonality might change further could make your predictive distribution narrower than expected, leading to potential lost sales.</p>
<p>The good news: ARIMA and ETS handle this naturally, as components&#8217; uncertainty translates directly to the holdout variance. In ML, it is more complicated, because you would need to invest time in proper feature engineering to explicitly capture the potential seasonality changes. Unfortunately, I haven&#8217;t done much in the latter direction, so I cannot give you a good recipe. Any thoughts what to do here?</p>
<p>And what do you do in the situation like that?</p>
<p>Message <a href="https://openforecast.org/2025/09/22/evolving-seasonality/">Evolving seasonality</a> first appeared on <a href="https://openforecast.org">Open Forecasting</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://openforecast.org/2025/09/22/evolving-seasonality/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
