Ga naar hoofdinhoud

Data science in marketing: klantverloop voorspellen

Leer hoe je met machine learning-modellen in Python klantverloop voorspelt en marketingdata omzet in betekenisvolle inzichten.
Bijgewerkt 31 aug 2026  · 10 min lezen

Verkennen met AI

ChatGPTClaudePerplexity

 

Introductie 

In de afgelopen 10-15 jaar, met de opkomst van digitale technologieën, zijn marketingstrategieën aanzienlijk veranderd. Bekende merken en kleinere spelers hebben enorme hoeveelheden data verzameld over transacties, aankopen, voorkeuren, koopkracht, koopgedrag, demografie, reviews, enzovoort. Al deze data kan marketeers helpen om klantgedrag in verschillende fases te begrijpen: van de intentie om iets te kopen, tot de daadwerkelijke aankoop en het uitgroeien tot een vaste klant. Daar komt het potentieel van data science om de hoek kijken.

Data science zet big data in marketing om in concrete, uitvoerbare inzichten, ook als die op het eerste gezicht minder intuïtief zijn, zoals niet-voor-de-hand-liggende patronen in consumentengedrag en co-occurenties. Zo krijgen marketeers een helderder beeld van hun doelgroep, kunnen ze nieuwe klanten aantrekken en bestaande behouden, hun marketingstrategieën optimaliseren, de zichtbaarheid van het bedrijf vergroten, succesvollere advertentiecampagnes opzetten, nieuwe kanalen inzetten en uiteindelijk de omzet aanzienlijk maximaliseren.

Een van de meest typische data-science-toepassingen in marketing is het voorspellen van klantverloop (churn). Laten we dit onderwerp in meer detail bespreken.

Data-science-usecase in marketing: klantverloop voorspellen

Klantverloop is de neiging van klanten om hun abonnement op een dienst die ze gebruiken op te zeggen en dus te stoppen als klant van die dienst. Het klantverlooppercentage is het percentage klanten dat in een vooraf gedefinieerd tijdsinterval is afgehaakt. Het is het tegenovergestelde van het groeipercentage, dat nieuwe klanten bijhoudt.

Het klantverlooppercentage is een zeer belangrijke indicator voor klanttevredenheid en de algehele gezondheid van het bedrijf. Naast natuurlijk verloop, dat in elk bedrijf voorkomt, of seizoensgebonden verloop, typisch voor sommige diensten, zijn er andere factoren die erop kunnen wijzen dat er in het bedrijf iets misgaat en moet worden bijgestuurd. Deze factoren zijn:

  • gebrekkige of lage kwaliteit van klantondersteuning,
  • negatieve klantervaringen,
  • overstappen naar een concurrent met betere voorwaarden of prijsstrategie,
  • veranderde prioriteiten van klanten,
  • langdurige klanten voelen zich niet meer tevreden,
  • de dienst voldeed niet aan de verwachtingen van klanten,
  • financiële problemen,
  • fraudepreventie bij betalingen van klanten.

Een hoog verlooppercentage is om de volgende redenen een serieus probleem voor elk bedrijf:

  • Het hangt samen met omzetverlies voor het bedrijf.
  • Nieuwe klanten werven kost veel meer geld dan bestaande klanten behouden. Dit geldt zeker voor zeer competitieve markten.
  • Als het afhaken komt door slechte klantenservice, kan de reputatie van het bedrijf zwaar worden beschadigd door negatieve reviews van ontevreden ex-klanten op sociale media of reviewsites.

Klantbehoud is een cruciaal onderdeel van de bedrijfsstrategie voor alle abonnementsdiensten. Om het verlooppercentage te voorspellen en de juiste preventieve maatregelen te nemen, is het nodig om informatie over klantgedrag te verzamelen en te analyseren (aankoopintervallen, totale duur als klant, opzeggingen, follow-upgesprekken en -berichten, online activiteit) en te achterhalen welke kenmerken en combinaties daarvan typerend zijn voor klanten die risico lopen om te vertrekken. Als je vooraf weet welke klanten binnenkort kunnen afhaken, vooral bij klanten met hoge omzet of een lange looptijd, kan het bedrijf zich precies op hen richten en een effectieve strategie ontwikkelen om ze te overtuigen te blijven. De aanpak kan bestaan uit een belletje met een speciale aanbieding, korting, een upgrade van het abonnement voor dezelfde prijs of een andere gepersonaliseerde ervaring.

Technisch gezien is churn-voorspelling een typische classificatieopgave in machine learning, waarbij klanten worden gelabeld als "ja" of "nee" in termen van risico op afhaken of niet. Laten we deze usecase in Python onderzoeken met echte data.

We gaan churn modelleren in het telecomdomein, waar klanten meerdere diensten bij één telecombedrijf kunnen afnemen onder één hoofdovereenkomst. De dataset bevat kenmerken van opgeschoonde klantactiviteit en een churnlabel dat aangeeft of een klant is afgehaakt of niet.

Laten we naar de data kijken en de verdeling van churn verkennen:

import pandas as pd

telcom = pd.read_csv('telco.csv')
print(f'Number of customers: {telcom.shape[0]:,}\n'
      f'Churn values: {set(telcom['Churn'])}\n\n'
      f'Churn distribution, %:\n{round(telcom.groupby(['Churn']).size()/telcom.shape[0]*100).convert_dtypes()}')
Number of customers: 7,032
Churn values: {0, 1}

Churn distribution, %:
Churn
0    73
1    27
dtype: float64

27% van de klanten haakte af, wat vrij hoog is. Vergeleken met de vorige data-science-usecase lijkt deze dataset echter geen ernstig probleem met klassenonevenwicht te hebben.

Nu gaan we de data voorbewerken om vervolgens machine-learningtechnieken toe te passen voor churn-voorspelling. Dit omvat het splitsen van de data in train- en testsets en het extraheren van de features en de doelvariabele:

from sklearn.model_selection import train_test_split

target = ['Churn']
custid = ['customerID']

cols = [col for col in telcom.columns if col not in custid + target]

X = telcom[cols]
y = telcom[target]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)

Het eerste algoritme dat we gebruiken om churnlabels te voorspellen en de nauwkeurigheid te schatten, is een eenvoudige classificatiemodel met logistische regressie:

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

lr = LogisticRegression()
lr.fit(X_train, y_train)
predictions = lr.predict(X_test)
print(f'Test accuracy: {round(accuracy_score(y_test, predictions), 4)}')
Test accuracy: 0.8009

Vervolgens voegen we extra functionaliteit toe aan ons model met logistische regressie, namelijk het draaien op geschaalde data met L1-regularisatie om featureselectie uit te voeren tijdens het modelleren. Verschillende waarden van de C-parameter (de inverse van de regularisatiekracht) beïnvloeden de nauwkeurigheid. Voor nu zetten we C op 0,025:

lr = LogisticRegression(penalty='l1', C=0.025, solver='liblinear')
lr.fit(X_train, y_train)
predictions = lr.predict(X_test)
print(f'Test accuracy: {round(accuracy_score(y_test, predictions), 4)}')
Test accuracy: 0.7969

Nu gaan we de C-parameter voor L1-regularisatie afstemmen om de optimale waarde te vinden die de modelcomplexiteit vermindert en toch goede prestatiecijfers behoudt. Hiervoor itereren we over verschillende C-waarden, bouwen we voor elke waarde een model met logistische regressie en berekenen we de prestatiemetingen.

De lijst C is vooraf aangemaakt met mogelijke waarden voor de parameter. De array l1_metrics is opgebouwd met 3 kolommen: de eerste bevat de C-waarden, de volgende twee zijn placeholders voor het aantal niet-nulcoëfficiënten en de nauwkeurigheidsscore van het model. Laten we deze aanpak proberen:

 C  Non-Zero Coeffs  Accuracy
0  1.0000             23.0  0.801479
1  0.5000             22.0  0.799204
2  0.2500             21.0  0.802048
3  0.1000             20.0  0.802617
4  0.0500             18.0  0.802048
5  0.0250             13.0  0.796928
6  0.0100              5.0  0.790102
7  0.0050              3.0  0.783276
8  0.0025              2.0  0.745734

We zien dat lagere C-waarden het aantal niet-nulcoëfficiënten (oftewel: features voor het model) verkleinen en zo de modelcomplexiteit reduceren, maar ook de nauwkeurigheid doen afnemen. Het lijkt erop dat C = 0,05 optimaal is: het reduceert het aantal features tot 18 en levert een nauwkeurigheid die iets hoger is dan die van het niet-geregulariseerde model.

Nu proberen we een ander algoritme: het beslisboommodel:

from sklearn.tree import DecisionTreeClassifier

clf = DecisionTreeClassifier()
clf.fit(X_train, y_train)
predictions = clf.predict(X_test)
print(f'Test accuracy: {round(accuracy_score(y_test, predictions), 4)}')
Test accuracy: 0.7275

Om een preciezer model te kiezen en overfitting te vermijden, kunnen we de boomdiepte (de parameter max_depth) afstemmen en de optimale waarde bepalen. Technisch lijkt dit proces sterk op het selecteren van de optimale C-parameter van het model met logistische regressie hierboven: we itereren over meerdere waarden van max_depth, fitten voor elke waarde een beslisboom en berekenen vervolgens de prestatiemetingen.

De lijst depth_list is vooraf aangemaakt met mogelijke waarden voor de parameter. De array depth_tuning heeft 2 kolommen: de eerste is gevuld met de diepte-kandidaten en de tweede is een placeholder voor de nauwkeurigheidsscore. Laten we deze aanpak toepassen en de optimale boomdiepte vinden:

depth_list = list(range(2, 15))
depth_tuning = np.zeros((len(depth_list), 2))
depth_tuning[:, 0] = depth_list

for index in range(len(depth_list)):
    clf = DecisionTreeClassifier(max_depth=depth_list[index])
    clf.fit(X_train, y_train)
    predictions = clf.predict(X_test)
    depth_tuning[index, 1] = accuracy_score(y_test, predictions)
   
col_names = ['Max_Depth', 'Accuracy']
print(pd.DataFrame(depth_tuning, columns=col_names))
 Max_Depth  Accuracy
0         2.0  0.756542
1         3.0  0.783276
2         4.0  0.782708
3         5.0  0.791809
4         6.0  0.778157
5         7.0  0.780432
6         8.0  0.757110
7         9.0  0.762230
8        10.0  0.763936
9        11.0  0.752560
10       12.0  0.745165
11       13.0  0.732651
12       14.0  0.727531

We zien dus dat de nauwkeurigheid eerst toeneemt bij meer diepte en daarna weer afneemt. Bij een max_depth van 5 geeft de boom de hoogste nauwkeurigheid; we kunnen deze waarde dus als optimale boomdiepte beschouwen.

Nadat we de beste parameterwaarden voor zowel logistische regressie als beslisbomen hebben bepaald, bouwen we die modellen opnieuw op en zoeken we de belangrijkste factoren die churn omhoog of omlaag drijven, en interpreteren we die.

Voor het model met logistische regressie gaan we de exponenten van de resulterende coëfficiënten extraheren en verkennen:

# Reconstructing the best model
lr = LogisticRegression(penalty='l1', C=0.05, solver='liblinear')
lr.fit(X_train, y_train)
predictions = lr.predict(X_test)

# Combining feature names and coefficients into one dataframe
feature_names = pd.DataFrame(X_train.columns, columns=['Feature'])
log_coef = pd.DataFrame(np.transpose(lr.coef_), columns=['Coefficient'])
coefficients = pd.concat([feature_names, log_coef], axis=1)

# Calculating exponents of the coefficients
coefficients['Exp_Coefficient'] = np.exp(coefficients['Coefficient'])

# Removing coefficients that are equal to zero
coefficients = coefficients[coefficients['Coefficient']!=0]
print(coefficients.sort_values(by=['Exp_Coefficient']))
                          Feature  Coefficient  Exp_Coefficient
21                          tenure    -0.907750         0.403431
4                 PhoneService_Yes    -0.820517         0.440204
17               Contract_Two year    -0.595271         0.551413
8                  TechSupport_Yes    -0.418254         0.658195
16               Contract_One year    -0.414158         0.660896
5               OnlineSecurity_Yes    -0.412228         0.662173
6                 OnlineBackup_Yes    -0.143100         0.866667
3                   Dependents_Yes    -0.039299         0.961463
7             DeviceProtection_Yes    -0.017465         0.982687
11            PaperlessBilling_Yes     0.071389         1.073999
1                SeniorCitizen_Yes     0.097904         1.102857
19  PaymentMethod_Electronic check     0.188533         1.207477
22                  MonthlyCharges     0.901454         2.463182

We zien dat de feature met de grootste impact op de odds van afhaken tenure is. In het algemeen verlagen coëfficiënten met exponenten kleiner dan 1 de odds, terwijl die groter dan 1 ze verhogen.

Voor het beslisboommodel gaan we de if-else-regels extraheren en plotten:

# Reconstructing the best model
clf = DecisionTreeClassifier(max_depth=5)
clf.fit(X_train, y_train)
predictions = clf.predict(X_test)

from sklearn import tree
import graphviz

# Exporting a graphviz object from the trained decision tree
exported = tree.export_graphviz(decision_tree=clf,
                                out_file=None,
                                feature_names=cols,
                                precision=1,
                                class_names=['Not churn', 'Churn'],
                                filled=True)
graph = graphviz.Source(exported)
display(graph)

Machine learning-beslisboom

We hebben een duidelijke beslisboomvisualisatie gekregen die je kunt interpreteren als een set if-else-regels, van bovenaf beginnend. Ook hier zien we dat klantduur (tenure) de belangrijkste variabele is die churn aanstuurt. De beslisboom kan met meer lagen worden opgebouwd, wat extra inzicht geeft in andere variabelen.

Als mogelijke vervolgstappen kunnen we de modelparameters verder afstemmen, andere manieren van train/test-splitsing proberen, andere machine-learningalgoritmen toepassen en vergelijken, en verschillende scoretypen analyseren om de modelprestaties te beoordelen.

Ben je benieuwd om dieper in churn-voorspelling en andere toepassingen van data science in marketing te duiken? Dan is deze cursus Machine Learning for Marketing in Python een goed startpunt.

Onderwerpen
Data Science
Machine Learning
Gerelateerd

blog

AI vanaf nul leren in 2026: een complete gids van de experts

Ontdek alles wat je moet weten om in 2026 AI te leren, van tips om te beginnen tot handige resources en inzichten van industrie-experts.
Adel Nehme's photo

Adel Nehme

15 min

Meer ZienMeer Zien