
Introducere
În ultimii 10–15 ani, odată cu progresul tehnologiilor digitale, strategiile de marketing s-au schimbat considerabil. Branduri celebre și piețe mai mici au colectat o cantitate vastă de date despre tranzacții, achizițiile clienților, preferințe, putere de cumpărare, activitate de cumpărare, demografie, recenzii etc. Toate aceste date îi pot ajuta pe marketeri să înțeleagă comportamentul clienților în diferite etape, de la intenția de a cumpăra ceva până la achiziția efectivă și transformarea într-un client constant. Aici intervine potențialul data science.
Data science transformă big data-ul de marketing în insighturi acționabile, chiar dacă uneori acestea sunt mai puțin intuitive la prima vedere, de exemplu anumite tipare și co-apariții neclare ale comportamentului consumatorilor. Drept rezultat, marketerii pot vedea mai clar publicul țintă, pot atrage clienți noi și îi pot păstra pe cei existenți, își pot optimiza strategiile de marketing, pot crește vizibilitatea companiei, pot crea campanii publicitare mai reușite, pot implica noi canale și, la rândul lor, pot maximiza semnificativ veniturile companiei.
Unul dintre cele mai tipice cazuri de utilizare a data science în marketing este predicția ratei de churn a clienților. Hai să discutăm acest subiect pe larg.
Caz de utilizare Data Science în marketing: predicția ratei de churn a clienților
Churn-ul clienților reprezintă tendința acestora de a-și anula abonamentele la un serviciu pe care îl foloseau și, astfel, de a înceta să mai fie clienți ai acelui serviciu. Rata de churn a clienților este procentul de clienți pierduți într-un interval de timp predefinit. Este opusul ratei de creștere a clienților, care urmărește noii clienți.
Rata de churn a clienților este un indicator foarte important al satisfacției clienților și al stării generale de sănătate a afacerii. Dincolo de churn-ul natural, care are loc mereu în orice afacere, sau de churn-ul sezonier, tipic pentru unele servicii, există și alți factori care pot însemna că ceva nu merge bine în companie și ar trebui remediat. Acești factori sunt:
- lipsa sau calitatea scăzută a suportului pentru clienți,
- experiențe negative ale clienților,
- migrarea către un competitor cu condiții sau prețuri mai bune,
- schimbarea priorităților clienților,
- clienții vechi nu se mai simt mulțumiți,
- serviciul nu a îndeplinit așteptările clienților,
- probleme financiare,
- protecție antifraudă la plățile clienților.
O rată mare de churn reprezintă o problemă serioasă pentru orice companie din următoarele motive:
- Corelează cu pierderi de venituri pentru companie.
- Costă mult mai mult să achiziționezi clienți noi decât să-i păstrezi pe cei existenți. Acest lucru este cu atât mai adevărat pe piețele foarte competitive.
- În cazul unui churn cauzat de servicii de relații cu clienții slabe, reputația companiei poate fi grav afectată de recenziile negative lăsate de foști clienți nemulțumiți pe rețelele sociale sau pe site-urile de recenzii.
Retenția clienților este o componentă esențială a strategiei de business pentru toate serviciile bazate pe abonament. Pentru a prezice rata de churn și a lua măsuri preventive corespunzătoare, este necesar să colectezi și să analizezi informații despre comportamentul clienților (intervale de achiziție, perioada totală ca și client, anulări, apeluri și mesaje de follow-up, activitate online) și să identifici ce atribute și combinații ale acestora sunt caracteristice clienților cu risc de plecare. Să știi din timp care clienți ar putea renunța în curând, mai ales în cazul celor cu venituri mari sau cu vechime, poate ajuta compania să se concentreze exact pe ei și să dezvolte o strategie eficientă pentru a-i convinge să rămână. Abordarea poate include un apel către astfel de clienți cu o ofertă specială: un cadou, un discount, un upgrade de abonament la același preț sau orice altă experiență personalizată.
Tehnic, predicția churn-ului este o problemă tipică de clasificare în machine learning, în care clienții sunt etichetați „da” sau „nu” în privința riscului de a renunța sau nu. Hai să investigăm acest caz de utilizare în Python pe date din lumea reală.
Vom modela churn-ul într-un model de afaceri telecom, unde clienții pot avea mai multe servicii la o companie de telecomunicații sub un singur contract-cadru. Setul de date conține caracteristicile activității curățate a clienților și o etichetă de churn care specifică dacă un client a renunțat sau nu.
Hai să aruncăm o privire pe date și să explorăm distribuția ratei de churn:
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% dintre clienți au renunțat, ceea ce este o rată destul de ridicată. Totuși, comparativ cu cazul precedent de data science, acest set de date nu pare să aibă o problemă severă de dezechilibru între clase.
Acum vom preprocesa datele pentru a aplica ulterior tehnici de machine learning în vederea predicției churn-ului. Asta include împărțirea datelor în seturi de antrenare și testare și extragerea caracteristicilor și a variabilei-țintă:
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)
Primul algoritm de modelare pe care îl vom folosi pentru a prezice etichetele de churn și a estima acuratețea rezultatelor este un model simplu de clasificare prin regresie logistică:
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
În continuare, să adăugăm încă o funcționalitate modelului nostru de regresie logistică, și anume rularea lui pe date scalate cu regularizare L1 pentru a efectua selecția de caracteristici concomitent cu construirea modelului. Valori diferite ale parametrului C (care este inversul forței de regularizare) afectează acuratețea modelului. Deocamdată, să setăm C la 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
Acum vom ajusta parametrul C pentru regularizarea L1 ca să descoperim valoarea optimă care reduce complexitatea modelului, menținând în același timp performanțe bune. În acest scop, vom itera prin valori diferite ale lui C și vom construi instanțe de regresie logistică pentru fiecare, precum și vom calcula metricile de performanță.
Lista C a fost creată în prealabil cu valorile posibile ale parametrului. Tabloul l1_metrics a fost construit cu 3 coloane, prima fiind valorile C, iar următoarele două fiind locuri rezervate pentru numărul de coeficienți nenuli și scorul de acuratețe al modelului. Hai să încercăm această abordare:
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
Observăm că valori mai mici ale lui C micșorează numărul de coeficienți nenuli (adică, caracteristicile folosite la modelare), reducând complexitatea modelului, dar scad și acuratețea. Se pare că valoarea C de 0,05 este optimă: reduce numărul de caracteristici la 18, oferind în același timp un scor de acuratețe ușor mai mare decât cel al modelului fără regularizare.
Acum să încercăm un alt algoritm de modelare – modelul arbore de decizie:
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
Pentru a alege un model mai precis evitând supraînvățarea, putem încerca să ajustăm adâncimea arborelui (parametrul max_depth) și să identificăm valoarea optimă. Tehnic, procesul este foarte similar cu cel de selecție a parametrului C optim al modelului de regresie logistică de mai sus: aici vom itera prin mai multe valori ale lui max_depth, vom antrena câte un arbore de decizie pentru fiecare și apoi vom calcula metricile de performanță.
Lista depth_list a fost creată în prealabil cu valorile posibile ale parametrului. Tabloul depth_tuning a fost construit cu 2 coloane, prima fiind completată cu valorile candidate pentru adâncime, iar cealaltă fiind un loc rezervat pentru scorul de acuratețe. Să aplicăm această abordare și să găsim adâncimea optimă a arborelui:
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
Așadar, scorul de acuratețe crește inițial odată cu adâncimea, apoi începe să scadă. La max_depth de 5, arborele arată cel mai mare scor de acuratețe, așadar putem considera această valoare drept adâncimea optimă a arborelui.
După identificarea celor mai bune valori de parametri pentru modelele de regresie logistică și arbore de decizie, hai să reconstruim acele modele și apoi să detectăm și să interpretăm principalii factori care determină creșterea sau scăderea churn-ului.
Pentru modelul de regresie logistică, vom extrage și explora exponenții coeficienților rezultați:
# 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
Vedem că variabila cu cel mai mare efect asupra șanselor de churn este tenure. În general, exponenții coeficienților mai mici decât 1 scad șansele, în timp ce cei mai mari decât 1 le cresc.
Pentru modelul arbore de decizie, vom extrage și afișa regulile if-else:
# 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)

Am obținut o vizualizare arborescentă clară, care poate fi interpretată ca un set de reguli if-else pornind de sus. Vedem din nou că vechimea clientului (tenure) este cea mai importantă variabilă care influențează churn-ul. Arborele poate fi construit cu mai multe niveluri, ceea ce va oferi mai multe insighturi despre alte variabile.
Ca direcții posibile de continuare, putem încerca ajustări suplimentare ale parametrilor modelului, folosirea unor abordări diferite de împărțire train/test, aplicarea și compararea altor algoritmi de machine learning și analizarea diverselor tipuri de scoruri pentru a evalua performanța modelului.
Dacă ești curios să aprofundezi predicția ratei de churn și alte aplicații ale data science în marketing, acest curs despre Machine Learning pentru marketing în Python poate fi un bun punct de plecare.