, September 29, 2022

0 kết quả được tìm thấy

Data Driven Growth (P.4): Dự đoán lòng trung thành của khách hàng - Churn Prediction

  • Đăng bởi  Kieu Hoa
  •  Jun 15, 2022

  •   12 min reads
Data Driven Growth (P.4): Dự đoán lòng trung thành của khách hàng - Churn Prediction

Dự đoán lòng trung thành của khách hàng với Phân loại nhị phân XGBoost (XGBoost Binary Classification)

Trong ba phần trước, chúng ta đã khám phá ra việc theo dõi các chỉ số cần thiết, phân khúc khách hàng - RFM dự đoán giá trị vòng đời của khách hàng.

Trong bài viết này, chúng ta sẽ tìm hiểu về tỷ lệ giữ chân người dùng hay còn gọi là Tỷ lệ duy trì (Retention Rate) là một trong những chỉ số quan trọng nhất.

Tỷ lệ giữ chân người dùng là một dấu hiệu cho thấy sản phẩm phù hợp với nhu cầu của thị trường (product market fit) như thế nào. Nếu PMF (product market fit) thấp, bạn sẽ thấy khách hàng đang bỏ mình đi dần.

Một trong những công cụ mạnh để cải thiện tỷ lệ giữ chân người dùng là Churn Prediction. Bằng cách sử dụng kỹ thuật này, bạn có thể tìm ra ai có khả năng rời đi trong khoảng thời gian nhất định.

Trong bài viết này, chúng ta sẽ sử dụng tập dữ liệu Telco và thực hiện các bước sau để phát triển mô hình Churn Prediction:

  • Phân tích dữ liệu thăm dò (Exploratory data analysis)
  • Feature engineering
  • Tìm cách các tính năng ảnh hưởng đến tỷ lệ giữ chân người dùng bằng cách sử dụng Hồi quy logistic
  • Xây dựng mô hình phân loại với XGBoost

Phân tích dữ liệu thăm dò (Exploratory data analysis)

Chúng ta bắt đầu kiểm tra dữ liệu của mình và trực quan hóa, cách nó tương tác với nhãn (có bị xáo trộn hay không?). Hãy bắt đầu với việc nhập dữ liệu và print mười hàng đầu tiên:

df_data = pd.read_csv('churn_data.csv')
df_data.head(10)

Output:

Cách tốt hơn để xem tất cả các cột và kiểu dữ liệu là sử dụng phương thức .info():

Có vẻ dữ liệu của chúng ta thuộc hai loại:

  • Các đặc trưng phân loại: gender (giới tính), streaming tv (truyền hình trực tuyến), payment method (phương thức thanh toán)...
  • Các đặc trưng số: tenure (thời gian chiếm hữu), monthly charges (phí hàng tháng), total charges (tổng phí)...

Bắt đầu từ những đặc trưng phân loại, chúng ta sẽ làm sáng tỏ và xem các đặc trưng này có hữu ích trong việc xác định khách hàng rời đi hay không.

Lưu ý: trong tập dữ liệu của chúng ta, cột Churn là chuỗi có các giá trị Có/Không. Chúng ta chuyển Có/Không thành số nguyên để dễ sử dụng hơn trong phân tích của mình.

df_data.loc[df_data.Churn=='No','Churn'] = 0 
df_data.loc[df_data.Churn=='Yes','Churn'] = 1

Giới tính (Gender)

Bằng cách sử dụng khối lệnh bên dưới, chúng ta dễ dàng hình dung tỷ lệ Churn (tỷ lệ khách hàng rời bỏ) (1-Retention Rate) trông như thế nào đối với mỗi giá trị:

df_plot = df_data.groupby('gender').Churn.mean().reset_index()
plot_data = [
    go.Bar(
        x=df_plot['gender'],
        y=df_plot['Churn'],
        width = [0.5, 0.5],
        marker=dict(
        color=['green', 'blue'])
    )
]
plot_layout = go.Layout(
        xaxis={"type": "category"},
        yaxis={"title": "Churn Rate"},
        title='Gender',
        plot_bgcolor  = 'rgb(243,243,243)',
        paper_bgcolor  = 'rgb(243,243,243)',
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

Output:

Tỷ lệ Churn theo giới tính (Churn Rate by Gender)

Phân tích giới tính đối với tỷ lệ churn:

Khách hàng nữ có khả năng rời đi cao hơn khách hàng nam, nhưng sự khác biệt này rất nhỏ (~ 0,8%).

Hãy lặp lại điều này đối với tất cả các cột phân loại. Để không lặp lại những gì đã làm với gender, bạn có thể tìm thấy code cho tất cả ở phía bên dưới:

Bây giờ chúng ta đi qua các đặc trưng có sự khác biệt đáng kể giữa các giá trị:

Dịch vụ Internet

Tỷ lệ Churn theo Dịch vụ Internet

Biểu đồ này cho thấy những khách hàng sử dụng dịch vụ Internet cáp quang (Fiber optic) có nhiều khả năng rời đi nhất.

Chúng ta vẫn thường hy vọng tỷ lệ rời đi của khách hàng khi sử dụng cáp quang sẽ thấp hơn. Bởi vì họ sử dụng dịch vụ cao cấp hơn. Nhưng điều này vẫn xảy ra do giá cao, cạnh tranh, dịch vụ chăm sóc khách hàng cùng những lý do khác.

Hợp đồng (Contract)

Tỷ lệ Churn theo hợp đồng

Như dự kiến, hợp đồng ngắn hạn hơn có nghĩa là tỷ lệ churn cao hơn.

Hỗ trợ ky thuật (Tech Support)

Tỷ lệ Churn theo hỗ trợ kỹ thuật

Khách hàng không được hỗ trợ kỹ thuật thường có khả năng rời đi cao hơn (chênh lệch ~ 25%).

Phương thức thanh toán (Payment Method)

Việc thanh toán tự động khiến khách hàng có nhiều khả năng ở lại hơn (chênh lệch ~ 30%).

Các đặc trưng khác

Dưới đây là những biểu đồ của các đặc trưng khác, bạn có thể tham khảo.

Chúng ta đã hoàn thành các đặc trưng phân loại. Tiếp theo, hãy xem các đặc trưng số trông như thế nào:

Tenure (thời gian chiếm hữu)

Để xem xu hướng giữa Tenure và Tỷ lệ Churn trung bình, hãy xây dựng một biểu đồ phân tán:

df_plot = df_data.groupby('tenure').Churn.mean().reset_index()
plot_data = [
    go.Scatter(
        x=df_plot['tenure'],
        y=df_plot['Churn'],
        mode='markers',
        name='Low',
        marker= dict(size= 7,
            line= dict(width=1),
            color= 'blue',
            opacity= 0.8
           ),
    )
]
plot_layout = go.Layout(
        yaxis= {'title': "Churn Rate"},
        xaxis= {'title': "Tenure"},
        title='Tenure based Churn rate',
        plot_bgcolor  = "rgb(243,243,243)",
        paper_bgcolor  = "rgb(243,243,243)",
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

Rõ ràng tenure cao hơn có nghĩa là Tỷ lệ Churn thấp hơn. Chúng ta sẽ áp dụng như vậy cho Monthly và Total Charges:

Output:

Tỷ lệ Churn theo phí hàng tháng và tổng phí

Thật không may, không có xu hướng giữa Tỷ lệ Churn và Monthly & Total Charges.

Feature Engineering

Trong phần này, chúng ta sẽ chuyển đổi các dữ liệu thô để trích xuất thêm thông tin từ chúng. Chiến lược của chúng ta như sau:

1- Nhóm các cột số bằng cách sử dụng kỹ thuật phân tổ (Clustering techniques)

2- Áp dụng Label Encoder cho các đặc trưng phân loại là nhị phân

3- Áp dụng get_dummies() cho các đặc trưng phân loại có nhiều giá trị

Cột số (Numerical Columns)

Như chúng ta đã biết từ phần EDA. Chúng ta có ba cột số:

  • Tenure (Thời gian chiếm hữu)
  • Monthly Charges (Phí hàng tháng)
  • Total Charges (Tổng chi phí)

Chúng ta áp dụng các bước sau để tạo nhóm:

1. Sử dụng phương pháp Elbow để xác định số lượng cụm thích hợp

2. Áp dụng logic K-mean cho cột đã chọn và thay đổi cách đặt tên

3. Quan sát profile của các cụm

Hãy kiểm tra xem các bước này hoạt động như thế nào đối với Tenure trong thực tế:

Cluster profiles:

Chúng ta có 3 cụm với thời gian trung bình là 7,5, 33,9 và 63

Tỷ lệ Churn đối với mỗi cụm:

Tỷ lệ Churn theo tenure clusters

Đây là cách nó trông như thế nào sau khi áp dụng giống nhau cho Monthly & Total Charges:

Monthly Charge:

Monthly Charge Clusters profile
Tỷ lệ Churn theo monthly charge clusters

Total Charge:

Total Charge Clusters profile
Tỷ lệ Churn theo total charge clusters

Cột phân loại

Label Encoder chuyển đổi các cột phân loại thành số bằng cách gán các số nguyên cho các giá trị riêng biệt. Ví dụ: cột giới tính có hai giá trị: Nữ & Nam. Label encoder sẽ chuyển đổi nó thành 1 và 0.

Phương thức get_dummies() tạo các cột mới từ các cột phân loại bằng cách gán 0 & 1

Hãy xem cả hai trong đoạn code dưới đây:

#import Label Encoder
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
dummy_columns = [] #array for multiple value columns
for column in df_data.columns:
    if df_data[column].dtype == object and column != 'customerID':
        if df_data[column].nunique() == 2:
            #apply Label Encoder for binary ones
            df_data[column] = le.fit_transform(df_data[column]) 
        else:
            dummy_columns.append(column)
#apply get dummies for selected columns
df_data = pd.get_dummies(data = df_data,columns = dummy_columns)

Kiểm tra dữ liệu trông như thế nào đối với các cột đã chọn:

Như bạn thấy, các cột gender & Partner trở thành những cột số và chúng ta có ba cột mới của TenureCluster.

Đã đến lúc phù hợp với mô hình hồi quy logistic và trích xuất insights để đưa ra quyết định kinh doanh tốt hơn.

Hồi quy logistic (Logistic Regression)

Dự đoán churn là một bài toán phân loại nhị phân. Khách hàng rời bỏ hoặc ở lại trong một khoảng thời gian nhất định.

Hồi quy logistic là một mô hình mạnh mẽ và cung cấp các kết quả có thể hiểu được. Như chúng ta đã làm, hãy sắp xếp các bước cần thực hiện để xây dựng mô hình Hồi quy logistic:

1. Chuẩn bị dữ liệu (đầu vào cho mô hình)

2. Điều chỉnh và xem tóm tắt mô hình

Dưới đây là bản tóm tắt.

Chúng ta có hai kết quả quan trọng từ báo cáo này. Khi bạn chuẩn bị một mô hình Dự đoán Churn, bạn sẽ phải đối mặt với những câu hỏi dưới đây:

  1. Điểm nào khiến khách hàng rời đi và ở lại?
  2. Những điều quan trọng nhất là gì? Chúng ta nên tập trung vào điều gì?

Đối với câu hỏi đầu tiên, bạn nên nhìn vào cột thứ 4 (P>|z|). Nếu giá trị P tuyệt đối nhỏ hơn 0,05, nghĩa là tính năng đó ảnh hưởng đến Churn theo cách có ý nghĩa thống kê. Ví dụ như:

  • SeniorCitizen
  • InternetService_DSL
  • OnlineSecurity_NO

Sau đó là câu hỏi thứ hai. Chúng ta muốn giảm Tỷ lệ Churn thì nên bắt đầu từ đâu? Câu hỏi này theo góc nhìn khoa học có nghĩa là:

Tính năng nào sẽ mang lại ROI tốt nhất nếu tôi tăng/giảm một đơn vị?

Câu hỏi này có thể được trả lời bằng cách nhìn vào cột coef. Hệ số mũ giúp chúng ta biết sự thay đổi dự kiến trong Tỷ lệ Churn nếu thay đổi một đơn vị. Áp dụng dòng code bên dưới, chúng ta sẽ thấy phiên bản chuyển đổi của tất cả các hệ số:

np.exp(res.params)

Ví dụ: thay đổi một đơn vị trong Monthly Charge nghĩa là cải thiện ~ 3,4% tỷ lệ chênh lệch nếu những thứ khác không đổi. Từ bảng trên, chúng ta có thể xác định được đặc trưng nào quan trọng hơn.

Hiện tại, mọi thứ đã sẵn sàng đối với việc xây dựng mô hình phân loại.

Mô hình phân loại nhị phân với XGBoost

Để XGBoost phù hợp với dữ liệu, chúng ta nên chuẩn bị các bộ đặc trưng (X) và nhãn (y) và thực hiện phân tách đào tạo & kiểm tra.

#create feature set and labels
X = df_data.drop(['Churn','customerID'],axis=1)
y = df_data.Churn
#train and test split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.05, random_state=56)
#building the model & printing the score
xgb_model = xgb.XGBClassifier(max_depth=5, learning_rate=0.08, objective= 'binary:logistic',n_jobs=-1).fit(X_train, y_train)
print('Accuracy of XGB classifier on training set: {:.2f}'
       .format(xgb_model.score(X_train, y_train)))
print('Accuracy of XGB classifier on test set: {:.2f}'
       .format(xgb_model.score(X_test[X_train.columns], y_test)))

Nhờ sử dụng mô hình đơn giản này, chúng ta đạt được độ chính xác 81%:

Tỷ lệ Churn thực tế trong tập dữ liệu là 26,5% (phản ánh 73,5% đối với hiệu suất mô hình). Điều này cho thấy mô hình của chúng ta là một mô hình hữu ích. Tốt hơn nên kiểm tra mô hình phân loại để biết mô hình bị lỗi ở đâu.

y_pred = xgb_model.predict(X_test)
print(classification_report(y_test, y_pred))

Chúng ta có thể giải thích báo cáo ở trên như thể mô hình cho chúng ta biết, 100 khách hàng sẽ ngừng hoạt động, 67 trong số đó sẽ ngừng hoạt động  (0.67 precision).

Và trên thực tế, có khoảng 220 khách hàng sẽ bỏ cuộc (0.45 recall). Đặc biệt, recall là vấn đề chính và chúng ta có thể cải thiện hiệu suất tổng thể của mô hình bằng cách:

  • Thêm nhiều dữ liệu hơn (chúng ta có khoảng 2 nghìn hàng cho ví dụ này)
  • Thêm nhiều đặc trưng hơn
  • Feature engineering khác
  • Thử các mô hình khác
  • Điều chỉnh siêu tham số (Hyper-parameter)

Trong tương lai, hãy xem mô hình của chúng ta hoạt động chi tiết như thế nào. Trước hết, chúng ta muốn biết mô hình sử dụng đặc trưng nào từ tập dữ liệu. Ngoài ra, cái nào là quan trọng nhất?

Để giải quyết câu hỏi này, chúng ta có thể sử dụng đoạn mã dưới đây:

from xgboost import plot_importance
fig, ax = plt.subplots(figsize=(10,8))
plot_importance(xgb_model, ax=ax)
Tầm quan trọng của các đặc trưng đối với Mô hình XGBoost

Từ mô hình, chúng ta có thể thấy tầm quan trọng của TotalChargesMonthlyCharges hơn so với các đặc trưng khác.

Cuối cùng, cách tốt nhất để sử dụng mô hình này là chỉ định Xác suất Churn cho từng khách hàng, tạo phân khúc và xây dựng chiến lược. Để có được xác suất churn từ mô hình, hãy sử dụng đoạn mã bên dưới:

df_data['proba'] = xgb_model.predict_proba(df_data[X_train.columns])[:,1]

Tập dữ liệu của chúng ta trông giống như bên dưới:

Xác suất Churn của khách hàng

Bài viết được dịch từ đây.

Bài viết cùng seri

Bài viết liên quan

Master data là gì? Sự khác nhau giữa Master data và Transaction data

Master data là tập hợp các định danh thống nhất và các thuộc tính mở rộng. Nó mô tả các thực thể cốt lõi của doanh nghiệp bao gồm khách hàng,.......

Master data là gì? Sự khác nhau giữa Master data và Transaction data
Danh mục các loại biểu đồ trong Data Visualization

Bạn có thể tìm thấy danh sách các loại biểu đồ, nó sẽ hoạt động như một hướng dẫn đầy hữu ích giúp bạn lựa chọn được biểu đồ phù hợp với nhu cầu của bản thân....

Danh mục các loại biểu đồ trong Data Visualization
Data Analysis with Excel: Analysis ToolPak

Bộ công cụ Analysis ToolPak trên Excel sẽ giúp bạn tiết kiệm thời gian và đơn giản hóa các bước phân tích dữ liệu tài chính, thống kê ....

Data Analysis with Excel: Analysis ToolPak
Data Analysis with Excel: Solver

Excel có một công cụ được gọi là solver cung cấp các lệnh và các tính năng tùy chỉnh để giải quyết các vấn đề quyết định....

Data Analysis with Excel: Solver
Data Analysis with Excel: What-If Analysis

What-If Analysis trong Excel cho phép bạn thử các giá trị (scenarios) khác nhau cho các công thức....

Data Analysis with Excel: What-If Analysis
You've successfully subscribed to 200Lab Blog
Great! Next, complete checkout for full access to 200Lab Blog
Xin chào mừng bạn đã quay trở lại
OK! Tài khoản của bạn đã kích hoạt thành công.
Success! Your billing info is updated.
Billing info update failed.
Your link has expired.