ข้ามไปยังเนื้อหาหลัก

วิทยาศาสตร์ข้อมูลในการตลาด: การพยากรณ์อัตราการยกเลิกใช้บริการของลูกค้า

เรียนรู้การใช้โมเดลแมชชีนเลิร์นนิงด้วย Python เพื่อพยากรณ์อัตราการยกเลิกใช้บริการของลูกค้า แปลงข้อมูลการตลาดให้เป็นอินไซต์ที่นำไปปฏิบัติได้จริง
อัปเดตแล้ว 31 ส.ค. 2569  · 10 นาที อ่าน

สำรวจด้วย AI

ChatGPTClaudePerplexity

 

บทนำ 

ตลอด 10-15 ปีที่ผ่านมา เมื่อเทคโนโลยีดิจิทัลก้าวหน้า กลยุทธ์การตลาดก็เปลี่ยนแปลงไปอย่างมาก แบรนด์ชั้นนำและตลาดขนาดเล็กต่างเก็บข้อมูลปริมาณมหาศาลเกี่ยวกับธุรกรรม การซื้อของลูกค้า ความชอบ กำลังซื้อ กิจกรรมการซื้อ ข้อมูลประชากร รีวิว ฯลฯ ข้อมูลทั้งหมดนี้ช่วยให้นักการตลาดเข้าใจพฤติกรรมของลูกค้าในแต่ละช่วง ตั้งแต่มีความตั้งใจจะซื้อ ไปจนถึงการซื้อจริงและกลายเป็นลูกค้าประจำ ตรงนี้เองที่ศักยภาพของวิทยาศาสตร์ข้อมูลเข้ามามีบทบาท

วิทยาศาสตร์ข้อมูลช่วยแปลงบิ๊กดาต้าการตลาดให้เป็นอินไซต์ที่นำไปใช้ได้จริง แม้บางครั้งอาจดูไม่เป็นธรรมชาติในแวบแรก เช่น รูปแบบพฤติกรรมผู้บริโภคที่ไม่ชัดเจนและเหตุการณ์ร่วมต่างๆ ผลลัพธ์คือ นักการตลาดจะเห็นภาพที่ชัดเจนขึ้นของกลุ่มเป้าหมาย ดึงดูดลูกค้าใหม่และรักษาลูกค้าเดิม ปรับกลยุทธ์การตลาดให้เหมาะสม เพิ่มการมองเห็นของบริษัท สร้างแคมเปญโฆษณาที่สำเร็จมากขึ้น เปิดช่องทางใหม่ และท้ายที่สุดช่วยเพิ่มรายได้ของบริษัทได้อย่างมีนัยสำคัญ

หนึ่งในกรณีใช้งานที่พบบ่อยที่สุดของวิทยาศาสตร์ข้อมูลในการตลาดคือ การพยากรณ์อัตราการยกเลิกใช้บริการของลูกค้า มาลองเจาะลึกหัวข้อนี้กัน

กรณีใช้งานวิทยาศาสตร์ข้อมูลในการตลาด: การพยากรณ์อัตราการยกเลิกใช้บริการของลูกค้า

การยกเลิกใช้บริการของลูกค้า คือแนวโน้มที่ลูกค้ายกเลิกการสมัครใช้บริการที่เคยใช้อยู่ และหยุดเป็นลูกค้าของบริการนั้น อัตราการยกเลิกใช้บริการคือสัดส่วนของลูกค้าที่เลิกใช้ภายในช่วงเวลาที่กำหนด ซึ่งเป็นด้านตรงข้ามกับอัตราการเติบโตของลูกค้าที่ติดตามลูกค้าใหม่

อัตราการยกเลิกใช้บริการเป็นตัวชี้วัดที่สำคัญมากของความพึงพอใจของลูกค้าและสุขภาพธุรกิจโดยรวมของบริษัท นอกเหนือจากการเลิกใช้ตามธรรมชาติซึ่งเกิดขึ้นในทุกธุรกิจ หรือการเลิกใช้ตามฤดูกาลที่พบในบริการบางประเภท ยังมีปัจจัยอื่นๆ ที่อาจบ่งชี้ว่ามีบางอย่างในบริษัทที่ผิดพลาดและควรแก้ไข ปัจจัยเหล่านี้ได้แก่:

  • การสนับสนุนลูกค้าที่ไม่มีหรือมีคุณภาพต่ำ
  • ประสบการณ์เชิงลบของลูกค้า
  • ย้ายไปหาคู่แข่งที่มีเงื่อนไขหรือกลยุทธ์ราคาดีกว่า
  • ลำดับความสำคัญของลูกค้าเปลี่ยนไป
  • ลูกค้าที่ใช้มานานรู้สึกไม่พึงพอใจ
  • บริการไม่เป็นไปตามความคาดหวังของลูกค้า
  • ปัญหาด้านการเงิน
  • การป้องกันการทุจริตในการชำระเงินของลูกค้า

อัตราการยกเลิกใช้บริการที่สูงเป็นปัญหาร้ายแรงสำหรับทุกบริษัทด้วยเหตุผลต่อไปนี้:

  • สัมพันธ์กับการสูญเสียรายได้ของบริษัท
  • ต้องใช้งบประมาณมากกว่ามากในการหาลูกค้าใหม่เมื่อเทียบกับการรักษาลูกค้าเดิม โดยเฉพาะในตลาดที่มีการแข่งขันสูง
  • หากการเลิกใช้เกิดจากบริการลูกค้าที่แย่ ชื่อเสียงของบริษัทอาจเสียหายหนักจากรีวิวเชิงลบที่อดีตลูกค้าที่ไม่พอใจโพสต์บนโซเชียลมีเดียหรือเว็บไซต์รีวิว

การรักษาลูกค้าเป็นองค์ประกอบสำคัญของกลยุทธ์ธุรกิจสำหรับบริการแบบสมัครสมาชิกทั้งหมด เพื่อพยากรณ์อัตราการยกเลิกใช้บริการและดำเนินมาตรการป้องกันที่เหมาะสม จำเป็นต้องรวบรวมและวิเคราะห์ข้อมูลพฤติกรรมของลูกค้า (ช่วงห่างการซื้อ ระยะเวลาที่เป็นลูกค้าโดยรวม การยกเลิก การโทรหรือส่งข้อความติดตามผล กิจกรรมออนไลน์) และหาว่าคุณลักษณะใดและการผสมผสานแบบใดที่เป็นลักษณะของลูกค้าที่มีความเสี่ยงจะออกไป การรู้ล่วงหน้าว่าลูกค้าคนไหนอาจเลิกใช้ในเร็วๆ นี้ โดยเฉพาะในกรณีลูกค้าที่ทำรายได้สูงหรือใช้มานาน จะช่วยให้บริษัทโฟกัสได้ตรงจุดและพัฒนากลยุทธ์ที่มีประสิทธิภาพเพื่อพยายามโน้มน้าวให้พวกเขาอยู่ต่อ วิธีการอาจรวมถึงการโทรหาลูกค้ากลุ่มนี้พร้อมข้อเสนอพิเศษ เช่น ของขวัญ ส่วนลด อัปเกรดแพ็กเกจในราคาเดิม หรือประสบการณ์ที่ปรับให้เหมาะกับแต่ละราย

ในเชิงเทคนิค การพยากรณ์การยกเลิกใช้บริการเป็นปัญหาการจัดกลุ่มประเภท (classification) แบบทั่วไปของแมชชีนเลิร์นนิง โดยลูกค้าจะถูกติดป้ายเป็น "ใช่" หรือ "ไม่ใช่" ในแง่ของความเสี่ยงในการเลิกใช้ มาศึกษากรณีใช้งานนี้ในภาษา Python ด้วยข้อมูลจริงกัน

เราจะจำลองการเลิกใช้บริการในโมเดลธุรกิจโทรคมนาคม ซึ่งลูกค้าสามารถมีหลายบริการกับบริษัทโทรคมนาคมภายใต้สัญญาหลักเดียว ชุดข้อมูลมีฟีเจอร์ของกิจกรรมลูกค้าที่ผ่านการทำความสะอาดแล้วและป้ายกำกับการเลิกใช้ที่ระบุว่าลูกค้ายกเลิกหรือไม่

มาดูข้อมูลและสำรวจการกระจายของอัตราการเลิกใช้บริการ:

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% เลิกใช้บริการ ซึ่งถือว่าสูงทีเดียว เมื่อเทียบกับกรณีใช้งานวิทยาศาสตร์ข้อมูลก่อนหน้า ชุดข้อมูลนี้ดูเหมือนไม่มีปัญหาความไม่สมดุลของคลาสที่รุนแรง

ต่อไปจะเตรียมข้อมูลก่อนเพื่อประยุกต์ใช้เทคนิคแมชชีนเลิร์นนิงสำหรับทำการพยากรณ์การเลิกใช้บริการ ซึ่งรวมถึงการแบ่งข้อมูลเป็นชุดฝึกและชุดทดสอบ และการแยกฟีเจอร์กับตัวแปรเป้าหมาย:

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)

อัลกอริทึมการทำแบบจำลองตัวแรกที่ใช้ในการพยากรณ์ป้ายกำกับการเลิกใช้และประเมินความแม่นยำของผลลัพธ์ คือโมเดลจำแนกประเภทแบบโลจิสติกรีเกรสชันอย่างง่าย:

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

ต่อไป มาเพิ่มความสามารถให้โมเดลโลจิสติกรีเกรสชัน โดยรันกับข้อมูลที่สเกลแล้วพร้อมการทำ L1 regularization เพื่อคัดเลือกฟีเจอร์ไปพร้อมกับการสร้างโมเดล ค่า C (ซึ่งเป็นส่วนกลับของความแรงของการทำ regularization) ต่างกันจะส่งผลต่อความแม่นยำของโมเดล ตอนนี้ตั้งค่า C ไว้ที่ 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

ตอนนี้จะปรับจูนพารามิเตอร์ C สำหรับ L1 regularization เพื่อค้นหาค่าที่เหมาะสมซึ่งช่วยลดความซับซ้อนของโมเดลโดยยังคงตัวชี้วัดประสิทธิภาพที่ดีไว้ เพื่อจุดประสงค์นี้จะลองไล่ค่าของ C หลายค่า สร้างอินสแตนซ์โลจิสติกรีเกรสชันแต่ละค่า และคำนวณตัวชี้วัดประสิทธิภาพ

มีรายการ C ที่เตรียมไว้ล่วงหน้าพร้อมค่าพารามิเตอร์ที่เป็นไปได้ อาร์เรย์ l1_metrics ถูกสร้างด้วย 3 คอลัมน์ โดยคอลัมน์แรกเป็นค่า C และอีกสองคอลัมน์เป็นช่องว่างสำหรับจำนวนค่าสัมประสิทธิ์ที่ไม่เป็นศูนย์และคะแนนความแม่นยำของโมเดล มาลองใช้แนวทางนี้กัน:

 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

จะเห็นว่าค่า C ที่ต่ำลงทำให้จำนวนค่าสัมประสิทธิ์ที่ไม่เป็นศูนย์ (เช่น ฟีเจอร์สำหรับการทำโมเดล) ลดลง ส่งผลให้ความซับซ้อนของโมเดลลดลง แต่ก็ทำให้ความแม่นยำของโมเดลลดลงด้วย ดูเหมือนว่าค่า C ที่ 0.05 จะเหมาะสมที่สุด: ลดจำนวนฟีเจอร์เหลือ 18 รายการ ขณะให้ความแม่นยำสูงกว่าแบบไม่ทำ regularization เล็กน้อย

ต่อไป มาลองใช้อัลกอริทึมการทำแบบจำลองอีกแบบหนึ่ง คือโมเดลดีซิชันทรี:

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

เพื่อเลือกโมเดลที่แม่นยำขึ้นโดยหลีกเลี่ยงการฟิตมากเกินไป ลองปรับความลึกของต้นไม้ (พารามิเตอร์ max_depth) และหาค่าที่เหมาะสม ทางเทคนิคกระบวนการนี้คล้ายกับการเลือกค่าพารามิเตอร์ C ที่เหมาะสมของโลจิสติกรีเกรสชันด้านบน คือจะไล่ค่าของ max_depth หลายค่า ฟิตต้นไม้สำหรับแต่ละค่า แล้วคำนวณตัวชี้วัดประสิทธิภาพ

มีรายการ depth_list ที่เตรียมไว้ล่วงหน้าพร้อมค่าพารามิเตอร์ที่เป็นไปได้ อาร์เรย์ depth_tuning ถูกสร้างด้วย 2 คอลัมน์ โดยคอลัมน์แรกบันทึกค่าความลึกที่เป็นผู้สมัคร และอีกคอลัมน์เป็นช่องว่างสำหรับคะแนนความแม่นยำ มาประยุกต์แนวทางนี้เพื่อหาความลึกของต้นไม้ที่เหมาะสมกัน:

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

ดังนั้น คะแนนความแม่นยำจะเพิ่มขึ้นเมื่อความลึกมากขึ้นช่วงหนึ่ง ก่อนจะเริ่มลดลง ที่ค่า max_depth เท่ากับ 5 ต้นไม้ให้คะแนนความแม่นยำสูงสุด จึงอาจพิจารณาค่านี้ว่าเป็นความลึกที่เหมาะสม

หลังจากระบุค่าพารามิเตอร์ที่ดีที่สุดสำหรับทั้งโลจิสติกรีเกรสชันและดีซิชันทรีแล้ว มาสร้างโมเดลเหล่านั้นใหม่ แล้วตรวจจับและตีความปัจจัยหลักที่ทำให้การเลิกใช้บริการเพิ่มหรือลดลง

สำหรับโมเดลโลจิสติกรีเกรสชัน จะดึงและสำรวจเลขชี้กำลังของค่าสัมประสิทธิ์ที่ได้:

# 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

จะเห็นว่าฟีเจอร์ที่มีผลมากที่สุดต่ออัตราส่วนโอกาสในการเลิกใช้คือ tenure โดยทั่วไป เลขชี้กำลังของค่าสัมประสิทธิ์ที่ต่ำกว่า 1 จะลดอัตราส่วนโอกาส ขณะที่ค่ามากกว่า 1 จะเพิ่มอัตราส่วนโอกาส

สำหรับโมเดลดีซิชันทรี จะดึงและพล็อตกฎ 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)

ดีซิชันทรีของแมชชีนเลิร์นนิง

เราได้ภาพการแสดงผลดีซิชันทรีที่ดูดีและสามารถตีความเป็นชุดกฎ if-else จากบนลงล่างได้ อีกครั้งที่เห็นว่า tenure ของลูกค้าเป็นตัวแปรสำคัญที่สุดที่ขับเคลื่อนการเลิกใช้ ต้นไม้สามารถสร้างให้มีเลเยอร์มากขึ้น ซึ่งจะให้มุมมองเชิงลึกเพิ่มเติมต่อ ตัวแปรอื่นๆ

แนวทางต่อไปอาจลองปรับพารามิเตอร์ของโมเดลเพิ่มเติม ใช้วิธีแบ่งชุดฝึก/ทดสอบที่แตกต่างกัน ประยุกต์และเปรียบเทียบอัลกอริทึมแมชชีนเลิร์นนิงอื่นๆ และวิเคราะห์คะแนนประเภทต่างๆ เพื่อประเมินประสิทธิภาพของโมเดล

หากสนใจเรียนรู้เชิงลึกเกี่ยวกับการพยากรณ์อัตราการยกเลิกใช้บริการและการประยุกต์วิทยาศาสตร์ข้อมูลด้านการตลาดอื่นๆ คอร์ส Machine Learning for Marketing in Python นี้เป็นจุดเริ่มต้นที่ดี

หัวข้อ
วิทยาการข้อมูล
แมชชีนเลิร์นนิง