Lees ons artikel over

class="lazyload

Assortimentsoptimalisatie is een cruciaal proces in de detailhandel waarbijde ideale productmix wordt samengesteldom aan de vraagvande consument te voldoen, rekening houdend met de vele logistieke beperkingen die daarbij komen kijken. Detailhandelaren moeten ervoor zorgen dat ze de juiste producten, in de juiste hoeveelheden en op het juiste moment aanbieden. Door gebruik te maken van data consumenteninzichten kunnen detailhandelaren weloverwogen beslissingen nemen over welke artikelen ze op voorraad moeten nemen, hoe ze de voorraad moeten beheren en aan welke producten ze prioriteit moeten geven op basis van klantvoorkeuren, seizoensgebonden trends en verkooppatronen.

Voor detailhandelsbedrijven is assortimentsoptimalisatie essentieel om een evenwicht te vinden tussenvariatieenefficiëntie. Een te beperkt aanbod kan klanten afschrikken, terwijl een te groot aanbod kan leiden tot verwarring, overtollige voorraad en lagere winstmarges. Door het productassortiment te optimaliseren, kunnen bedrijven de klanttevredenheid verhogen door ervoor te zorgen dat populaire artikelen beschikbaar zijn en tegelijkertijd slecht verkopende producten te verwijderen die kostbare schapruimte innemen.

Keuzemodelleringis een efficiënte methode om het assortiment te optimaliseren, omdat het een data kader biedt om inzicht te krijgen in de voorkeuren van klanten en te voorspellen hoe zij tussen verschillende producten zullen kiezen. Door verschillende factoren te analyseren, zoals prijsgevoeligheid, productkenmerken en merkloyaliteit, helpt keuzemodellering retailers te bepalen welke producten het meest waarschijnlijk aan de vraag van de klant zullen voldoen.

Uiteindelijk stelt keuze-modellering retailers in staat om de juiste productmix aan te bieden, het assortiment af te stemmen op specifieke klantsegmenten en bovendien de schapruimte te optimaliseren om de winstgevendheid te vergroten of zelfs de prijsstelling van artikelen te beïnvloeden.

Als je nog nooit van keuzemodellering hebt gehoord, kun jeons artikellezen waarin de belangrijkste concepten aan de hand van voorbeelden worden uitgelegd. In dit artikel richten we ons vooral op de manier waarop discrete keuzemodellen kunnen worden gebruikt om een productassortiment te optimaliseren. We bieden codevoorbeelden aan op basis van dechoice-learn-bibliotheek, die is ontworpen om data bij dergelijke toepassingen te ondersteunen.

De bijgevoegde code maakt gebruik van het Python-pakket `choice-learn` en is te vinden in een notebook hier.

Voorbereiding: Python en Choice-Learn installeren

In dit artikel geven we codefragmenten ter illustratie van de uitleg. De code maakt gebruik van deChoice-Learn-bibliotheek, die efficiënte hulpmiddelen biedt voor keuzemodellering en diverse toepassingen, zoals assortimentsoptimalisatie of prijsbepaling. Choice-Learn is beschikbaar via PyPI; je kunt het eenvoudig downloaden met


pip install choice-learn

De dataset: kassabonnen

We gaan de TaFeng-dataset voor boodschappen gebruiken. Je kunt deze downloaden viaKaggleen in je Python-omgeving openen met choice-learn:

van choice_learn.datasets import load_tafeng
tafeng_df = load_tafeng(as_frame=True)
print(tafeng_df.head())
class="lazyload

De dataset bevat meer dan 800.000 afzonderlijke aankopen in een Chinese supermarkt. Voor elke aankoop worden diverse gegevens verstrekt, waaronder het gekochte artikel (PRODUCT_ID), de verkoopprijs (SALES_PRICE) en de leeftijdsgroep van de klant (AGE_GROUP).

Je ziet dat er veel verschillende artikelen worden aangeboden en dat sommige daarvan zelden worden verkocht. Om de logistiek te stroomlijnen, kan de winkelier ervoor kiezen om het aantal aangeboden producten te verminderen. Het doel is in dit geval om de optimale selectie van te verkopen artikelen te bepalen.

Om dit te bereiken, richten we ons op de best verkochte artikelen, aangezien de kans groter is dat deze opnieuw worden gekocht en ze een cruciale rol zullen spelen bij het samenstellen van een efficiënter en winstgevender assortiment.Let wel: we doen dit voornamelijk om het voorbeeld te vereenvoudigen en alle artikelen zouden in het assortiment kunnen blijven.

# Alleen de 20 best verkochte producten behouden
tafeng_df = tafeng_df.loc[
tafeng_df.PRODUCT_ID.isin(tafeng_df.PRODUCT_ID.value_counts().index[:20])
].reset_index(drop=True)
# NaN-waarden verwijderen
tafeng_df = tafeng_df.loc[
tafeng_df.AGE_GROUP.isin([“25-29”, “40-44”, “45-49”, “>65”, “30-34”, “35-39”, “50-54”, “55-59”, “60-64”] )
].reset_index(drop=True)
print(tafeng_df.head())

Laten we de leeftijdscategorieën ook coderen met one-hot-waarden per tien jaar:

# De leeftijdscategorieën coderen
tafeng_df[“twintigers”] = tafeng_df.apply(lambda row: 1 if row[“AGE_GROUP”] == “25-29” else 0,axis=1)
tafeng_df[“thirties”] = tafeng_df.apply(
lambda row: 1 if row[“AGE_GROUP”] in ([“30-34”, “35-39”]) else 0,axis=1
)
tafeng_df[“forties”] = tafeng_df.apply(
lambda row: 1 if row[“AGE_GROUP”] in ([“40-44”, “45-49”]) else 0,axis=1
)
tafeng_df[“fifties”] = tafeng_df.apply(
lambda row: 1 if row[“AGE_GROUP”] in ([“50-54”, “55-59”]) else 0,axis=1
)
tafeng_df[“sixties_and_above”] = tafeng_df.apply(
lambda row: 1 if row[“AGE_GROUP”] in ([“60-64”, “>65”]) else 0,axis=1
)

Nu onze data klaar data , moeten we eenChoiceDataset aanmaken, het object data inchoice-learn. Hierbij moeten we de kenmerken specificeren die de context beschrijven waarin een aankoop plaatsvindt:

  • Klantkenmerken(gemeenschappelijke kenmerken): de leeftijdscategorie
  • Productkenmerken(productdetails): de prijs van het artikel

Een belangrijk aspect van keuzemodellering is dat we de kenmerken vanalle beschikbare artikelen op het moment van aankoop nodig hebben, en niet alleen die van het gekozen artikel. Zo kunnen we analyseren hoe de prijzen van verschillende producten de beslissing van de klant beïnvloeden. Aangezien deze informatie niet direct in de dataset beschikbaar is, gaan we ervan uit dat bij elke aankoop de prijzen van de andere artikelen gelijk blijven aan die bij de vorige verkoop.

# Product-ID naar index
id_to_index =
for i, product_id in enumerate(np.sort(tafeng_df.PRODUCT_ID.unique())):
id_to_index[product_id] = i
# De prijzen van de artikelen initialiseren
prices = [[0] for _ in range(len(id_to_index))] for k, v in id_to_index.items():
prices[v][0] = tafeng_df.loc[tafeng_df.PRODUCT_ID == k].SALES_PRICE.to_numpy()[0] # Maak de arrays die de ChoiceDataset zullen vormen
shared_features = [] items_features = [] choices = [] # Voor elk gekocht item slaan we het volgende op:
# – de leeftijdsrepresentatie (one-hot) van de klant
# – de prijs van alle verkochte artikelen
for i, row in tafeng_df.iterrows():
item_index = id_to_index[row.PRODUCT_ID] prices[item_index][0] = row.SALES_PRICE
shared_features.append(
row[["twenties", "thirties", "forties", "fifties", "sixties_and_above"]].to_numpy()
)
items_features.append(prices)
choices.append(item_index)

Nu we alle gegevens hebben, kunnen wede ChoiceDataset aanmaken:

fromdata import ChoiceDataset
dataset = ChoiceDataset(
shared_features_by_choice=shared_features,
shared_features_by_choice_names=[‘twenties’, ‘thirties’, ‘forties’, ‘fifties’, ‘sixties_and_above’],
items_features_by_choice=items_features,
items_features_by_choice_names=[“SALES_PRICE”],
choices=choices
)

Het keuzemodel definiëren en schatten

We zullen een keuzemodel ontwikkelen en schatten dat de kans voorspelt dat een klant een specifiek artikel kiest uit een volledig assortiment van vergelijkbare producten. Op basis van de beschikbare dataset definiëren we de volgende nutsfunctie voor een artikelidat door een klantj wordt overwogen:

class="lazyload

Deze functie geeft het nut (of de tevredenheid) weer dat een klant ontleent aan de keuze voor een bepaald artikel, waarbij zowel de leeftijd van de klant als de prijs van het artikel een rol spelen.

Raadpleeg ons eerstebericht voor meer informatie over hoe we een nutfunctie opstellen. Merk op dat een ander logisch model – dat we hier echter achterwege hebben gelaten om het eenvoudig te houden – zou kunnen zijn om één prijsgevoeligheid per leeftijdscategorie te schatten.

Hier is de code om een dergelijk model te schatten met choice-learn:

van choice_learn.models importeer ConditionalLogit
model = ConditionalLogit(optimizer="Adam",batch_size=1024,epochs=300,lr=0.002)
voor age_category in [“twintigers”, “dertigers”, “veertigers”, “vijftigers”, “zestigers_en_ouder”]:
model.add_coefficients(
coefficient_name=age_category, feature_name=age_category,items_indexes=list(range(20))
)
model.add_shared_coefficient(
coefficient_name="price", feature_name="SALES_PRICE",items_indexes=list(range(20))
)
hist = model.fit(dataset)

Je kunt controleren of het model goed aansluit bij de dataset:

import matplotlib.pyplot as plt
plt.plot(hist[“train_loss”])
plt.xlabel(“Epoch”)
plt.ylabel(“Negative Log Likelihood”)
plt.show(
class="lazyload

Het optimale assortiment samenstellen

Nu we de aankoopkansen kennen, kunnen we de gemiddelde omzet per klant van assortimentAberekenenmet behulp vande volgende formule:

class="lazyload

Om het assortiment te vinden dat de omzet maximaliseert, zouden we alle mogelijke combinaties kunnen evalueren en degene met de hoogste gemiddelde omzet kunnen selecteren. Een efficiëntere aanpak is echter het gebruik vanlineaire programmering (LP). Hier zullen we ons richten op het gebruik van deChoice-Learn-implementatievan de assortimentsoptimalisator.

Het is belangrijk om onderscheid te maken tussen het maximaliseren van de omzet en het maximaliseren van de winstmarges. Hoewel de omzet belangrijk is, houden winstmarges rekening met de kosten die aan elk product verbonden zijn. Afhankelijk van je doel kun je ervoor kiezen om te streven naar winst in plaats van naar pure omzet.

Om het assortiment te optimaliseren, moeten we een aantal belangrijke gegevens verstrekken:

  • Het gewicht dat we aan elke leeftijdscategorie willen toekennen; laten we uitgaan van hun aandeel in het klantenbestand
  • Het nut van elk item (berekend door ons keuzemodel) voor elke leeftijdscategorie
  • De waarde die voor elk item moet worden geoptimaliseerd (in dit geval de omzet)
  • De omvang van het assortiment (bijvoorbeeld 12 artikelen)

Zo werkt het metchoice-learn:


from choice_learn.toolbox.assortment_optimizer import LatentClassAssortmentOptimizer
# Prijs van elk artikel
future_prices = np.stack([items_features[-1]]*5,axis=0)
age_category = np.eye(5).astype("float32")
# Bereken het nut van elk artikel op basis van de prijs en elke leeftijdscategorie
predicted_utilities = model.compute_batch_utility(shared_features_by_choice=age_category,
                                                  items_features_by_choice=future_prices,
                                                  available_items_by_choice=np.ones((5, 20)),
                                                 choices=None
                                                  )
age_category_weights = np.sum(shared_features,axis=0) / len(shared_features)
opt = LatentClassAssortmentOptimizer(
solver="or-tools", # Te gebruiken solver, ofwel "or-tools" of "gurobi" (als u een licentie hebt)
class_weights=age_category_weights, # Gewichten van elke klasse
class_utilities=np.exp(predicted_utilities), # nut in de vorm (n_classes, n_items)
itemwise_values=future_prices[0][:, 0], # Waarden die voor elk item moeten worden geoptimaliseerd, hier de prijs die wordt gebruikt om de omzet te berekenen
assortment_size=12) # Gewenste omvang van het assortiment
assortment, opt_obj = opt.solve()

Als je de code uitvoert, zou je ongeveer het volgende moeten zien:


class="lazyload

Het optimale assortiment voor het maximaliseren van de omzet wordt aangegeven door de elementen met waarde 1 in de vector. Dit assortiment levert theoretisch een gemiddelde omzet per klant op van 134 yuan. Je kunt andere combinaties bekijken, maar die zullen allemaal resulteren in een lagere gemiddelde omzet.

Een andere doelstelling zou kunnen zijn om het aantal verkopen te maximaliseren. In dit scenario wordt de waarde per artikel voor de optimalisatie voor alle artikelen op 1 gezet, wat tot een ander optimaal assortiment leidt.

De efficiëntie van deze methode wordt duidelijk wanneer er aanvullende beperkingen worden toegevoegd. Zo moet u bijvoorbeeld rekening houden met beperkte schapruimte in uw winkel. In dat geval kunt u het assortiment zo optimaliseren dat de totale omvang van de artikelen de beschikbare schapruimte niet overschrijdt. Deze aanvullende beperking, samen met andere factoren zoals prijsstrategieën, wordthier geïllustreerd.


Conclusie

Als je bezig bent met assortimentsoptimalisatie of prijsbepaling, is keuzemodellering een geweldig hulpmiddel; neem er zeker eens een kijkje naar. Choice-Learn biedt veel interessante voorbeelden opGitHub. Neem eens een kijkje en geef het een sterretje als je het nuttig vindt!