Sitemap
Heuritech, a Luxurynsight Company

Heuritech is a cutting-edge artificial intelligence company that provides fashion & sportwears brands with predictive analytics on trends.

Is fashion predictable?

6 min readNov 13, 2024

--

Press enter or click to view image in full size
Generated with Dall-E 3.

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 Etienne DAVID, research engineer at Heuritech and today, we will explore the complex subject of fashion forecasting through the lens of mathematics, machine learning and AI.

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?

1) Translate fashion to time series

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:

Press enter or click to view image in full size

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:

Press enter or click to view image in full size
Each point represents the number of posts in the U.S. where the visual recognition framework detected Chunky Sneakers within images.

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:

Press enter or click to view image in full size
Normalised time series representing the visibility evolution of Chunky Sneakers in the U.S. on social media.

2) Fashion time series forecasting

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 this great online book for a complete description of these models.

Get Etienne David’s stories in your inbox

Join Medium for free to get updates from this writer.

We provide below Python classes implementing the two models:

import pandas as pd
from statsmodels.tsa.api import ExponentialSmoothing
from pydantic import BaseModel

WEEKS_IN_YEAR = 52
HORIZON = 52


class EtsForecastModel(BaseModel):
"""Class defining an ETS (exponential smoothing) model.

Args:
season: define the seasonality length.
horizon: define the forecast horizon of the Ets model.
"""

season: int = WEEKS_IN_YEAR
horizon: int = HORIZON

def fit_predict_single_ts(self, ts_signal: pd.Series) -> pd.Series:
""" Fit ETS models and return its prediction.

Args:
ts_signal: A pd.Series gathering a single time series signal.

Returns:
single_forecast: A pd.Series gathering the ETS prediction.
"""

model = ExponentialSmoothing(
ts_signal, seasonal_periods=self.season, seasonal="add", trend="add"
)
fitted_model = model.fit()
single_forecast = fitted_model.forecast(self.horizon)
single_forecast.name = ts_signal.name
return single_forecast


class SnaiveForecastModel(BaseModel):
"""Class defining a seasonal naive model that repeats the values of the past year as its prediction.

Args:
horizon: define the forecast horizon of the Naive model.
"""
season: int = WEEKS_IN_YEAR
horizon: int = HORIZON

def predict(self, ts_signal: pd.Series) -> pd.Series:
""" Compute prediction of a Naive model.

Args:
ts_signal: A pd.Series gathering a single time series signal.

Returns:
single_forecast: A pd.Series gathering the seasonal Naive prediction.

"""

historical_data_past_year = ts_signal.tail(52)
nb_repeat, part_repeat = divmod(52, 52)
naive_forecast = [historical_data_past_year] * nb_repeat + [
historical_data_past_year[:part_repeat]
]
single_forecast = pd.concat(naive_forecast, axis=0, ignore_index=True)

forecast_index = pd.date_range(
start=ts_signal.index[-1], periods=52 + 1, freq=ts_signal.index.freq
)[1:]
single_forecast.index = forecast_index
return single_forecast

Thus, here is a simple code base that we can use to compute a one-year prediction for Chunky Sneakers in 2024.

def load_time_series_csv(filepath: str) -> pd.DataFrame:
df = pd.read_csv(filepath, index_col=0)
df.index = pd.to_datetime(df.index)
df.index.freq = df.index.inferred_freq
return df


fashion_ts = load_time_series_csv('chunky_sneakers.csv')
fashion_ts_train = fashion_ts.loc[:"2023-01-01"]

ets_model = EtsForecastModel()
ets_prediction = pd.DataFrame(ets_model.fit_predict_single_ts(fashion_ts_train["chunky_sneakers"]))
snaive_model = SnaiveForecastModel()
snaive_prediction = pd.DataFrame(snaive_model.predict(fashion_ts_train["chunky_sneakers"]))

Here are the resulting predictions:

Press enter or click to view image in full size

3) Forecast evaluation

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.

Press enter or click to view image in full size

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:

  • Mean Absolute Scaled Error (MASE)
def mase(y_true: pd.DataFrame, y_pred: pd.DataFrame, seasonality: int) -> np.ndarray:
"""
NOTE: y_true must contain at least `seasonality` time steps before the first time index
of y_pred, plus the number of time steps in y_pred.
"""
time_split = y_pred.index[0]
index_y_pred = y_true.index.get_loc(time_split)
assert index_y_pred > seasonality + 1, (
f"To compute the MASE, you need {seasonality} time steps of history"
f" before timestamp {time_split}."
)

numerator = np.mean(
np.abs(y_true.values[index_y_pred:index_y_pred + len(y_pred)] - y_pred.values), axis=0
)
gt = y_true.values[seasonality:index_y_pred - 1]
gt_shifted = y_true.values[:index_y_pred - 1 - seasonality]
denominator = np.mean(np.abs(gt - gt_shifted), axis=0)
return numerator / denominator
  • Mean Absolute Percentage Error (MAPE)
def mape(y_true: pd.DataFrame, y_pred: pd.DataFrame) -> np.ndarray:
time_split = y_pred.index[0]
index_y_pred = y_true.index.get_loc(time_split)

numerator = y_true.values[index_y_pred:index_y_pred + len(y_pred)] - y_pred.values
denominator = y_true.values[index_y_pred:index_y_pred + len(y_pred)]
mape = np.abs(numerator / denominator)
mape[mape == np.inf] = np.nan
return np.nanmean(mape, axis=0)
  • Symmetric Mean Absolute Percentage Error (SMAPE)
def smape(y_true: pd.DataFrame, y_pred: pd.DataFrame) -> np.ndarray:
time_split = y_pred.index[0]
index_y_pred = y_true.index.get_loc(time_split)

numerator = np.abs(y_true.values[index_y_pred:index_y_pred + len(y_pred)] - y_pred.values)
denominator = 0.5 * (
np.abs(y_true.values[index_y_pred:index_y_pred + len(y_pred)]) + np.abs(y_pred.values)
)
smape = np.abs(numerator / denominator)
smape[smape == np.inf] = np.nan
return np.nanmean(smape, axis=0)

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.

Press enter or click to view image in full size
Since the three displayed metrics are error metrics, the lower the value, the better the forecast.

4) Is fashion predictable?

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.

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.

If you’d like to replicate the graphs and results presented in this article, you can access the linked code repository here.

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 !

Press enter or click to view image in full size
In 2024, Retro Football Sneakers have surged in popularity, but the exponential smoothing model fails to capture this sudden upward trend.

--

--