Przejdź do głównej treści

Data Science w marketingu: przewidywanie wskaźnika churn klientów

Dowiedz się, jak używać modeli uczenia maszynowego w Pythonie do przewidywania wskaźników odejść klientów, zamieniając dane marketingowe w konkretne insighty.
Zaktualizowano 31 sie 2026  · 10 min Czytać

Eksploruj z AI

ChatGPTClaudePerplexity

 

Wprowadzenie 

W ostatnich 10–15 latach, wraz z rozwojem technologii cyfrowych, strategie marketingowe uległy znacznym zmianom. Znane marki i mniejsze podmioty zebrały ogromne ilości danych o transakcjach, zakupach klientów, preferencjach, sile nabywczej, aktywności zakupowej, demografii, recenzjach itd. Wszystkie te dane mogą pomóc marketerom zrozumieć zachowania klientów na różnych etapach — od zamiaru zakupu, przez faktyczny zakup, po stawanie się stałym klientem. Tu właśnie wchodzi do gry potencjał data science.

Data science zamienia marketingowe big data w działania, nawet jeśli na pierwszy rzut oka bywa to mniej intuicyjne, np. poprzez ujawnianie nieoczywistych wzorców zachowań konsumenckich i współwystąpień. W rezultacie marketerzy widzą wyraźniejszy obraz grupy docelowej, mogą pozyskiwać nowych klientów i utrzymywać obecnych, optymalizować strategie marketingowe, zwiększać widoczność firmy, tworzyć skuteczniejsze kampanie reklamowe, włączać nowe kanały i w efekcie znacząco maksymalizować przychody firmy.

Jednym z najczęstszych zastosowań data science w marketingu jest przewidywanie wskaźnika churn klientów. Przyjrzyjmy się temu tematowi bliżej.

Zastosowanie data science w marketingu: przewidywanie wskaźnika churn klientów

Churn klientów to skłonność klientów do anulowania subskrypcji używanej usługi i tym samym zaprzestania bycia klientem tej usługi. Wskaźnik churn to odsetek klientów, którzy odeszli w określonym przedziale czasu. To przeciwieństwo wskaźnika wzrostu bazy klientów, który śledzi nowych klientów.

Wskaźnik churn to bardzo ważny wskaźnik satysfakcji klientów i ogólnej kondycji biznesowej firmy. Poza naturalnym odejściem, które zawsze występuje w każdym biznesie, lub sezonowością typową dla niektórych usług, istnieją inne czynniki, które mogą oznaczać, że w firmie coś poszło nie tak i wymaga naprawy. Do tych czynników należą:

  • brak lub niska jakość obsługi klienta,
  • negatywne doświadczenia klientów,
  • przejście do konkurenta z lepszymi warunkami lub cenami,
  • zmiana priorytetów klientów,
  • długoletni klienci nie czują satysfakcji,
  • usługa nie spełniła oczekiwań klientów,
  • problemy finansowe,
  • zabezpieczenia przed oszustwami przy płatnościach klientów.

Wysoki wskaźnik churn to poważny problem dla każdej firmy z następujących powodów:

  • Koreluje z utratą przychodów firmy.
  • Pozyskanie nowych klientów kosztuje znacznie więcej niż utrzymanie obecnych. To szczególnie prawdziwe na rynkach o dużej konkurencji.
  • W przypadku odejść spowodowanych słabą obsługą klienta reputacja firmy może zostać mocno nadszarpnięta przez negatywne opinie niezadowolonych byłych klientów w mediach społecznościowych lub na portalach z recenzjami.

Utrzymanie klientów to kluczowy element strategii biznesowej wszystkich usług subskrypcyjnych. Aby przewidywać wskaźnik churn i podjąć odpowiednie działania zapobiegawcze, trzeba zebrać i przeanalizować informacje o zachowaniach klientów (odstępy między zakupami, łączny okres bycia klientem, anulowania, rozmowy i wiadomości follow-up, aktywność online) i ustalić, które atrybuty i ich kombinacje są charakterystyczne dla klientów zagrożonych odejściem. Wiedząc z wyprzedzeniem, którzy klienci mogą wkrótce odejść — zwłaszcza ci o wysokiej wartości lub długim stażu — firma może skupić się właśnie na nich i opracować skuteczną strategię, by spróbować przekonać ich do pozostania. Podejście może obejmować telefon z ofertą specjalną, prezentem, zniżką, podniesieniem pakietu w tej samej cenie lub innym spersonalizowanym doświadczeniem.

Technicznie przewidywanie churn to typowy problem klasyfikacji w uczeniu maszynowym, w którym klientów etykietuje się jako „tak” lub „nie” w kontekście ryzyka odejścia. Przeanalizujmy ten przypadek w Pythonie na danych z rzeczywistego świata.

Będziemy modelować churn w telekomunikacji, gdzie klienci mogą mieć wiele usług u jednego operatora w ramach jednej umowy głównej. Zbiór danych zawiera cechy oczyszczonej aktywności klientów oraz etykietę churn określającą, czy klient odszedł.

Przyjrzyjmy się danym i rozkładowi wskaźnika 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% klientów odeszło, co jest dość wysokim wynikiem. W porównaniu z poprzednim przypadkiem użycia data science ten zbiór danych nie wydaje się jednak mieć poważnego problemu z niezrównoważeniem klas.

Teraz przetworzymy wstępnie dane, by zastosować techniki uczenia maszynowego do przewidywania churn. Obejmuje to podział danych na zbiory treningowy i testowy oraz wyodrębnienie cech i zmiennej docelowej:

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)

Pierwszym algorytmem modelowania, którego użyjemy do przewidywania etykiet churn i oceny dokładności wyników, będzie prosta regresja logistyczna:

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

Następnie dodajmy funkcjonalność do naszego modelu regresji logistycznej — uruchomimy go na przeskalowanych danych z regularyzacją L1, aby przeprowadzić selekcję cech równolegle z budową modelu. Różne wartości parametru C (odwrotność siły regularyzacji) wpływają na dokładność modelu. Na razie ustawmy C na 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

Teraz dostroimy parametr C dla regularyzacji L1, aby znaleźć optymalną wartość, która zmniejsza złożoność modelu przy zachowaniu dobrych metryk wydajności. W tym celu przeiterujemy przez różne wartości C, zbudujemy modele regresji logistycznej dla każdej z nich i obliczymy metryki.

Lista C została przygotowana wcześniej z możliwymi wartościami parametru. Tablica l1_metrics ma 3 kolumny: pierwsza to wartości C, a kolejne dwie to miejsca na liczbę niezerowych współczynników i dokładność modelu. Wypróbujmy to podejście:

 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

Widzimy, że niższe wartości C zmniejszają liczbę niezerowych współczynników (czyli cech użytych w modelu), redukując złożoność modelu, ale jednocześnie obniżają jego dokładność. Wygląda na to, że C równe 0,05 jest optymalne: redukuje liczbę cech do 18, a jednocześnie daje dokładność nieco wyższą niż model bez regularyzacji.

Teraz spróbujmy innego algorytmu — drzewa decyzyjnego:

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

Aby wybrać dokładniejszy model i uniknąć przeuczenia, możemy dostroić głębokość drzewa (parametr max_depth) i określić jej optymalną wartość. Technicznie proces jest bardzo podobny do wyboru optymalnego C w modelu regresji logistycznej powyżej: przeiterujemy przez wiele wartości max_depth, wytrenujemy drzewo dla każdej z nich, a następnie obliczymy metryki.

Lista depth_list została przygotowana wcześniej z możliwymi wartościami parametru. Tablica depth_tuning ma 2 kolumny: pierwsza jest wypełniona kandydatami głębokości, a druga to miejsce na dokładność. Zastosujmy to podejście i znajdźmy optymalną głębokość drzewa:

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

Widzimy więc, że dokładność początkowo rośnie wraz z głębokością, a potem zaczyna spadać. Przy max_depth równym 5 drzewo osiąga najwyższą dokładność, więc tę wartość możemy uznać za optymalną głębokość.

Po ustaleniu najlepszych wartości parametrów dla regresji logistycznej i drzewa decyzyjnego odbudujmy te modele, a następnie wykryjmy i zinterpretujmy główne czynniki podbijające lub obniżające churn.

W przypadku regresji logistycznej wyodrębnimy i przeanalizujemy eksponenty otrzymanych współczynników:

# 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

Widzimy, że cechą o największym wpływie na szanse odejścia jest staż klienta (tenure). Ogólnie eksponenty współczynników mniejsze niż 1 zmniejszają szanse, a większe niż 1 je zwiększają.

Dla drzewa decyzyjnego wyodrębnimy i zwizualizujemy reguły 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)

Drzewo decyzyjne uczenia maszynowego

Otrzymaliśmy czytelną wizualizację drzewa decyzyjnego, którą można interpretować jako zestaw reguł if-else zaczynających się od góry. Ponownie widać, że staż klienta to najważniejsza zmienna wpływająca na churn. Drzewo można zbudować z większą liczbą warstw, co da więcej wglądów w pozostałe zmienne.

Potencjalnie warto dalej dostrajać parametry modelu, stosować różne podejścia do podziału train/test, porównywać inne algorytmy uczenia maszynowego oraz analizować różne metryki oceny działania modelu.

Jeśli chcesz głębiej wejść w przewidywanie wskaźnika churn i inne zastosowania data science w marketingu, dobrym miejscem na start może być ten kurs: Machine Learning for Marketing in Python.

Tematy
Data Science
Uczenie maszynowe