85 Views

Average customer adalah konsep masa lalu, karena  bisnis jaman now harus dapat menyegmentasikan basis pelanggan mereka ke dalam kelompok dan menyesuaikan pengalaman untuk setiap segmen pelanggan. Topik ini merupakan salah satu contoh di mana kita akan menggunakan machine learning dan data science yang umumnya digunakan di industri, dan memahami cara melakukannya serta melakukan analisis di dalamnya sangatlah berharga. Mari pelajari bagaimana bisnis jaman now dapat mempersonalisasi pengalaman dengan segmentasi pelanggan.

Teknik segmentasi sebenarnya sudah saya pernah bahasa, sesuai dengan pengalaman yang sudah saya kerjakan ditempat kerja saya sendiri, bisa kalian baca disini, untuk memahami cara teknis kerja tersebut, kalian bisa pelajari teknik merging dan clustering data

Perbedaan yang saya akan bahas disini berupa cara melakukan cleansing data serta melibatkan banyak produk dan bersifat customers-centric.

Tulisan ini lumayan panjang, jadi simak saja baik-baik dan sambil ngopi juga boleh!

Aspek Bisnis dalam Segmentasi Pelanggan

Sebelum kita mendalami kode dan teknis, mari kita pelajari bagaimana bisnis dapat memanfaatkan hasil segmentasi pelanggan.

Sebuah perusahaan mungkin ingin mensegmentasikan pelanggan menurut berbagai faktor sehingga perusahaan dapat memasarkan ke setiap kelompok secara lebih efektif dan tepat. Perusahaan dapat menyegmentasikan pelanggan mereka menurut demografi seperti usia, jenis kelamin, status pernikahan, lokasi, atau kebiasaan membeli.

Dengan mensegmentasi pelanggan, perusahaan bisa

  • Membuat dan mengkomunikasikan pesan pemasaran bertarget yang akan lebih disukai oleh segmen tertentu daripada dengan menargetkan ‘pelanggan rata-rata’ – Average customer  – common customer.
  • Temukan saluran komunikasi terbaik untuk suatu segmen, yang mungkin online atau secara langsung. Misalnya, pelanggan yang lebih muda mungkin lebih cenderung membeli produk jika mereka melihat iklan online melalui, katakanlah, Instagram, dan pelanggan yang lebih tua mungkin melalui selebaran kertas atau platform lama seperti Facebook. Baca artikel tentang perjalanan memulai Airbnb untuk mencari tahu bagaimana mereka menemukan saluran komunikasi terbaik untuk mendorong lebih banyak orang mendaftarkan rumah mereka di platform.
  • Bangun hubungan pelanggan yang lebih kuat. Perasaan yang didapat pelanggan ketika perusahaan menggunakan strategi pemasaran satu ukuran untuk semua membuat mereka menjauh. Hubungan pelanggan yang lebih personal berarti lebih banyak loyalitas kepada perusahaan tertentu

Segmentasi pelanggan tidak hanya mencakup gaya layanan pelanggan atau metode pemasaran yang berbeda – ini bisa sesederhana mengubah teks di situs web. Jika seorang pengguna Airbnb, misalnya, diperkirakan lebih mungkin menjadi pendaftar daripada pemesan (menempatkan propertinya di Airbnb alih-alih bepergian ke tempat lain menggunakan Airbnb), teks di layar beranda (ketika buka browser). Mereka mungkin melihat teks yang berbunyi “Dapatkan uang dengan mencantumkan properti Anda properti di Airbnb “. dan sesuatu yang serupa cocok untuk pengguna yang diprediksi akan menjadi pemesan, bukan pendaftar. Padahal target perusahaan lebih kepada pemesan agar terjadi transaksi

Mencapai rata-rata tidak berarti mencapai mayoritas. Pasar modern mengharuskan perusahaan untuk memberikan pengalaman yang disesuaikan kepada beragam pelanggan.

Cleanising Data

Data tidak selalu (dan biasanya tidak) datang dalam bentuk yang bersih dan siap untuk dianalisis. Sehingga kita akan sedikit usaha ekstra untuk mengubah data menjadi kumpulan data yang dapat disegmentasi pelanggan, dan kemudian mengeksplorasi cara mendapatkan analisis darinya.

Setiap analisis dimulai dengan data – kumpulan data yang akan kami tangani adalah untuk e-niaga dari pengecer Inggris yang realnya jadi datanya 100% nyata. Masalah yang ditemui di sini mungkin akan muncul di data bisnis lain juga. Bisa kalian download dengan kata kunci Actual transactions from UK retailer – https://www.kaggle.com/carrie1/ecommerce-data. Ada 8 kolom:

  1. InvoiceNo — bulat positif (integer) berisi no invoice, contohnya 536365.
  2. StockCode — string unik berisi item barang (SKU – stok keeping unit)  yang dibeli oleh konsumen, contohnya: 85123A.
  3. Description — deskripsi produk, contohnya: WHITE HANGING HEART T-LIGHT HOLDER.
  4. Quantity —  jumlah item yang dibeli, contohnya : 6.
  5. InvoiceDate — tanggal invoice, contohnya : 12/1/2010 8:26.
  6. UnitPrice — harga per unit dari setiap produk, contohnya : 2.55.
  7. CustomerID —  bulat positif berisi ID Unik pelangggan, contohnya: 17850.
  8. Country — negara asal pelanggan, contohnya: United Kingdom

Data nya cukup besar yaitu format CSV 40 MB dengan jumlah record 541.909 (jumlah yang sangat banyak)

6 Langkah Teknik Segmentasi Pelanggan

Data ini adalah item-customer-centric, yang berarti bahwa setiap baris tidak hanya dibedakan oleh pelanggan dan tidak hanya oleh satu item tetapi oleh beberapa item yang dibeli oleh beberapa pelanggan. Ini membuat pekerjaan kita sedikit lebih sulit.

Tugas kita adalah mencapai data yang customer-centric, di mana setiap baris baru mewakili pelanggan unik yang atributnya tercantum di kolom lain.

Ada beberapa tantangan lain juga; deskripsi adalah satu-satunya indikator produk. Salah satu solusi untuk mengintegrasikan produk apa yang dibeli pelanggan ke dalam data yang berpusat pada pengguna adalah dengan menjadikan setiap produk unik sebagai kolom, dengan nilai dalam kolom mewakili berapa banyak dari setiap produk yang dibeli pengguna. Sayangnya, ini tidak dapat dilakukan baik oleh jumlah dimensi yang sangat tinggi, sesuatu yang algoritma berbasis jarak Euclidean seperti K-Means tidak bisa digunakan karena ada istilah Curse of Dimensionality, dan karena itu benar-benar tidak dapat diinterpretasikan bahkan jika analisisnya selesai , belum lagi betapa sulitnya PCA  untuk pengurangan dimensi.

Untuk mengatasi masalah ini, kita akan mengelompokkan deskripsi produk ke dalam beberapa kelompok (paling banyak, 4 atau 5). Setiap kluster produk ini akan menjadi kolomnya sendiri, dengan nilai selnya menunjukkan nilai total item yang dibeli pelanggan yang sesuai dengan keranjang itu. Ini menurunkan jumlah dimensi dari solusi sebelumnya dan lebih dapat ditafsirkan.

Mari kita siapkan prosesnya Teknik Segmentasi Pelanggan

  1. Muat data dan lakukan pembersihan dasar (menghapus baris identik, dll.).
  2. Vektorisasi deskripsi semua item.
  3. Kelompokkan mereka menjadi maksimal 5 kelompok, dan buat kolom dari mereka berdasarkan berapa banyak uang yang dihabiskan pelanggan di setiap kategori barang.
  4. Tampilkan rekor pembelian pelanggan dalam beberapa kolom (aggregasi). Untuk melakukan ini, buat lima kolom: count, minimum, maximum, mean, dan sum, yang masing-masing mewakili beberapa aspek statistik dari daftar dengan semua harga total pesanan yang telah dibuat oleh pelanggan.
  5. Buat kolom biner yang mewakili apakah pelanggan itu asing atau bukan (dari Inggris atau bukan). Ada 38 negara unik yang terdaftar dalam kumpulan data, dan masing-masing tidak bisa menjadi kolomnya sendiri. Banyak perusahaan hanya mencantumkan pelanggan sebagai orang asing atau bukan, dan karena perusahaan e-niaga ini berbasis di Inggris, semua pelanggan di luar Inggris dianggap asing.
  6. Kelompokkan pelanggan menggunakan K-Means, dan ambil analisis dari pusat cluster.
  7. Gunakan model K-Means untuk membuat analisis.

Langkah 1| Memuat dan Membersihkan Data

Data dapat dimuat dengan perpustakaan pandas, menggunakan pengkodean ISO-8859–1.

import pandas as pd

data = pd.read_csv('data.csv',encoding='ISO-8859-1')
print(data.head(5))

hasil

  InvoiceNo StockCode  ... CustomerID         Country
0    536365    85123A  ...    17850.0  United Kingdom
1    536365     71053  ...    17850.0  United Kingdom
2    536365    84406B  ...    17850.0  United Kingdom
3    536365    84029G  ...    17850.0  United Kingdom
4    536365    84029E  ...    17850.0  United Kingdom

Memanggil perintah len (data) menghasilkan 541909, artinya terdapat 541.909 baris pada data. Peirntah  len(data ['CustomerID'].unique()) menghasilkan 4373, artinya ada 4.373 pelanggan berbeda. Idealnya, data akhir kita memiliki 4.373 baris.

Menulusuri Missing Value – NA

Kita perlu menangani nilai yang hilang – missing value. Dengan memeriksa len(data) - len(data.dropna()) yang mengembalikan jumlah baris yang akan dihapus jika kita menghapus baris yang memiliki nilai na. Ini menghasilkan 135080, yang berarti bahwa antara 1/5 dan 1/4 dari data akan hilang jika kita membuang baris apa pun dengan nilai na.

Setelah kita telusuri ternyata missing value berasal dari CustomerID  dan Description

Jadi, dari manakah sebagian besar missing value ini berasal? Jawabannya: CustomerIDs yang hilang. Kode  data['CustomerID'].isnull().sum(), yang memeriksa berapa banyak nilai yang hilang ada di kolom CustomerID, mengembalikan nilai 135080. Semua baris yang akan dihapus menggunakan data.dropna() memiliki missing value CustomerIDs. Dari informasi diatas didapatkan

  1. len(data)  jumlah data sebanyak 541.909 baris
  2. len(data ['CustomerID'].unique()) jumlah pelanggan unik sebanyak 4.373 baris.
  3. len(data.dropna())  adalah jumlah baris yang mengandung missing value – NA sebanyak 406.829 baris yang berasal dari missing value CustomerIDs 

Untuk keperluan proyek ini, saya akan membuang semua baris yang memiliki nilai na. Namun, ini mungkin tidak bagus dan tidak bijaksana dalam proyek bisnis yang serius karena bias pemilihan

katakanlah bahwa semua pelanggan yang ID-nya termasuk dalam beberapa cluster tambahan atau memberikan informasi berharga yang dibuang karena ID mereka tidak diketahui. Dalam pengaturan bisnis yang lebih formal, mungkin lebih bijaksana untuk mencoba dan menghubungkan ID melalui metode seperti Decision Tree.

data = data.dropna()
len(data)

hasilnya

406829

Jumlah baris semula 541.909 baris berkurang hanya menjadi 406.829 baris saja.

Droping Kolom yang tidak relevan

Kolom InvoiceNo dan StockCode tidak relevan. Kami dapat menghapusnya:

data.drop(['InvoiceNo','StockCode'],axis=1,inplace=True)
data.head()

Teknik Regex untuk menyeragamkan data Description

Selanjutnya, kita akan memvektor kolom Description untuk mengelompokkan produk ke dalam beberapa grup. Untuk menyiapkan data, kita perlu membuat huruf kecil dan menghilangkan tanda baca, misalnya di baris 4 dengan “RED WOOLY HOTTIE WHITE HEART”.

Mari buat fungsi yang membersihkan Description. Ini menggunakan ekspresi reguler – regex untuk menghapus tanda baca dan mengecilkan huruf – lower case.

import re
def clean(description):
    return re.sub(r'[^\w\s]','',description).lower()

Sudah siap! Fungsi .apply Pandas memungkinkan kita menerapkan fungsi ke kolom.

data['Description'] = data['Description'].apply(clean)
data.head()

Kalian bisa lihat, bahwa function tersebut bekerja dengan baik! Teks siap untuk vektorisasi. Dua hal terakhir – kita perlu mengatur ulang indeks dan dengan cepat membuat kolom baru. Karena kita tadi menghapus semua nilai na, akan ada beberapa nilai indeks yang tidak beraturan (tidak urut lagi), kita perlu reset index

 data = data.reset_index().drop('index',axis=1)

Total Nominal yang dibeli oleh konsumen

Di masa depan, kita perlu mengetahui jumlah total uang yang dibelanjakan untuk sebuah produk – ungkapan ulang, biaya unit dikalikan jumlah item.

data['Total'] = data['UnitPrice'] * data['Quantity']

Langkah 2| Lakukan vektorisasi Description

Mengingat sifat kolom Description ini, mungkin yang terbaik adalah menggunakan kumpulan kata-kata daripada TD-IDF, yang lebih cocok untuk teks panjang dengan kata-kata yang lebih berlebihan. Tampaknya setiap kata dalam kolom Description adalah semacam kata kunci, jadi memvektorkannya hanya dengan sekumpulan kata / hitungan adalah cara terbaik.

(TF-IDF) mengukur pentingnya frase kata kunci dengan membandingkannya dengan frekuensi istilah dalam sekumpulan besar dokumen.

from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer(stop_words='english')

Ini membuat objek CountVectorizer dengan kata-kata stopwords bahasa Inggris (kata-kata and, of, a, dll. Yang tidak banyak mengandung arti – ini kebetulan saja, saya menggunakan dataset yang mengandung bahasa inggris, kalau ntar ada yang bahasa indonesia, kalian bisa cari kata kunci stopwords bahasa indonesia). Kemudian dapat menyesuaikan vectorizer pada data dan mengubahnya menggunakan .fit_transform.

<406829x2093 sparse matrix of type '<class 'numpy.int64'>'
   with 1640936 stored elements in Compressed Sparse Row format>

Seperti yang diharapkan, sebagian besar matriksnya bersifat sparse dan cukup besar. NumPy memiliki trik cerdas untuk menjaga array ini dalam format terkompresi sehingga waktu pengoperasian lebih cepat.

Langkah 3| Kelompokkan Produk & Buat Fitur

Sebenarnya pengelompokan produk itu sederhana hanya dengan menggunakan library sklearn’s KMeans. Mari kita coba saja menggunakan 5 cluster

from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=5,random_state=0)
kmeans.fit(descriptions)

Sabar saja karena banyak waktu untuk menyesuaikan model KMean (~ 5 menit) karena ada begitu banyak contoh teks untuk dijalankan. Atau kalian bisa mencoba Kmeans ini atau pakai pypy3

Kita dapat menetapkan setiap item yang dibeli label apa pun yang didapatnya melalui KMeans ke dalam kolom baru, Produk, dengan kode ini:

data['Product'] = kmeans.labels_
data.head()

Membuat data yang customer-centric sebenarnya sedikit lebih sulit. Untuk memulai, mari kita buat DataFrame baru, bernama customers. Saat ini, kolom satu-satunya adalah nilai unik untuk CustomerID.

customers = pd.DataFrame({'CustomerID':data['CustomerID'].unique()})
customers.head()

setiap baris adalah pelanggan baru, diwakili oleh unik CustomerID

Selanjutnya, kita perlu membuat 5 kolom (karena kita menggunakan 5 cluster), satu untuk setiap kategori produk. Untuk saat ini, saya akan menetapkannya sama dengan 0 sebagai nilai initial

customers['Product0'] = 0
customers['Product1'] = 0
customers['Product2'] = 0
customers['Product3'] = 0
customers['Product4'] = 0
customers.head()

Dari sini, Saya akan looping satu-persatu untuk mengisi data. Meskipun mungkin membutuhkan waktu lama, ini adalah proses yang mudah.

Untuk setiap baris dalam data, saya akan menambahkan berapa pun jumlah uang yang dibelanjakan untuk produk tersebut ke kategori produk apa pun di baris yang memiliki CustomerID yang cocok.

Oiya saya menggunakan library TQDM untuk melihat progress bar nya (kalian tidak perlu install koq, jika menggunakan anaconda)

Butuh waktu agak lama yaitu sekitar 10 menit

from tqdm import tqdm
for index in tqdm(range(len(data))):
    customerID = data.loc[index,'CustomerID']
    product_category = data.loc[index,'Product']
    product_price = data.loc[index,'Total']
    customers_table_index = customers[customers['CustomerID']==customerID].index[0]
    customers.loc[customers_table_index, 'Product'+str(product_category)] += product_price

tampilkan proses

100%|██████████| 406829/406829 [11:14<00:00, 603.18it/s]

Dengan menampilkan customers, kita dapat melihat bahwa jumlah yang dibelanjakan setiap pelanggan di salah satu dari lima kluster produk.

      CustomerID  Product0  Product1  Product2  Product3  Product4
0        17850.0      0.00    495.60   4124.57    668.46      0.00
1        13047.0     41.32     25.35   2481.77    129.26    401.40
2        12583.0    185.64   1410.44   5251.06      0.00    340.20
3        13748.0     47.76      0.00    836.25     34.30     29.94
4        15100.0      0.00      0.00      0.00      0.00    635.10
5        15291.0      0.00    428.91   3711.54    409.26     46.80
6        14688.0    120.61   1831.21   2995.51     33.00    127.05
7        17809.0    182.64     58.05   4241.24      0.00    145.69
8        15311.0    127.02  25217.70  29908.77   1961.95   2203.90

Langkah 4 | Membuat Deskripsi Histori Pembelian

Selanjutnya, tugas kita adalah membuat lima kolom: count, maximum, minimum, average, dan sum, yang merupakan lima indikator numerik dari riwayat pembelian pelanggan. Perhatikan bahwa kita perlu melakukan ini karena alternatifnya, yaitu menyandikan riwayat pembelian setiap pelanggan berdasarkan tanggal

Saya akan menggunakan metode serupa seperti sebelumnya. Cara yaitu mengatur 5 kolom menjadi 0 dan mengisinya secara berulang.

customers['PurchaseCount'] = 0
customers['PurchaseMin'] = 0
customers['PurchaseMax'] = 0
customers['PurchaseMean'] = 0
customers['PurchaseSum'] = 0
customers.head()

Mari kita telusuri logika tentang apa yang ingin kita lakukan di sini. Untuk setiap pelanggan unik, saya ingin mengakses semua (total) pembelian yang telah mereka lakukan. Dari sana, jika riwayat disimpan dalam larik NumPy atau Series Pandas, atribut seperti count, maximum, minimum, average, dan sum.

from tqdm import tqdm
for index in tqdm(range(len(customers))):
    customerID = customers.loc[index,'CustomerID']
    history = data[data['CustomerID']==customerID]['Total']
    customers.loc[index,'PurchaseCount'] = history.count()
    customers.loc[index,'PurchaseMin'] = history.min()
    customers.loc[index,'PurchaseMax'] = history.max()
    customers.loc[index,'PurchaseMean'] = history.mean()
    customers.loc[index,'PurchaseSum'] = history.sum()

tampilan proses

100%|██████████| 4372/4372 [00:41<00:00, 104.36it/s]

Dengan menampilkan customers, kita dapat mengubah data menjadi bentuk yang berfokus pada pengguna- user-centric, lengkap dengan kategori produk dan statistik riwayat pembelian.

Kita hampir sampai! Satu fitur lagi dan kita siap untuk mulai mengelompokkan pelanggan.

Langkah 5 | Membuat fitur biner ‘foreign’

Kita ingin tahu apakah pelanggan berasal dari Inggris atau bukan. Ini cukup sederhana – kita akan menggunakan metode set-and-input saja.

customers['Foreign'] = 0

Secara default, Foreign akan menjadi 0, karena mayoritas penjualan berasal dari Inggris Ray – UK -United Kingdom

for index in tqdm(range(len(customers))):
    customerID = customers.loc[index,'CustomerID']
    customerCountry = data[data['CustomerID']==customerID] .reset_index().loc[0,'Country']
    if customerCountry == 'United Kingdom':
        customers.loc[index,'Foreign'] = 1

Dengan menampilkan customers, kita telah berhasil mengonversi data yang berpusat pada pengguna / produk – customer centric menjadi data yang murni direquest oleh pelanggan sambil mempertahankan informasi penting lainnya.

Langkah 6 | Membuat Cluster

Saatnya membuat kluster dengan data secara resmi! Kita memiliki 4.372 pelanggan unik yang dapat kita buat kluster.

Namun sebelum kita mulai membuat cluster, penting untuk bertanya – berapa banyak cluster yang harus kita miliki? Metode yang umum adalah metode elbow, yang memplot kesalahan dan mencoba menemukan ‘elbow’ dalam data di mana peningkatan kesalahan versus peningkatan dalam kluster menurun secara signifikan. Saya selalu menemukan metode itu sangat subjektif – sebagai gantinya, kita akan menggunakan skor siluet, yang menghitung seberapa cocok sejumlah cluster tertentu dengan data. Kemudian, saya akan memilih jumlah cluster yang memiliki skor siluet terendah, namun wajar saja (100 cluster mungkin memiliki skor siluet terendah, tetapi saya tidak dapat memilih banyak cluster).

Selain itu, kita perlu mengukur data. Karena K Means berbasis jarak, kita perlu menskalakan data. Ini berarti meletakkan semuanya dalam skala dari -1 hingga 1 – disebut dengan normalisasi

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaled_customers = scaler.fit_transform(customers)

Sayangnya diatas masih dalam bentuk array numpy, Kita dapat mengubahnya menjadi DataFrame melalui kode berikut

scaled_customers = pd.DataFrame(scaled_customers, columns=customers.columns)
scaled_customers

Sekarang, kita dapat membuat 6 model K-Means, di mana masing-masing memiliki kelompok 2, 3, 4, 5, 6, atau 7. Kita menyimpan skor siluet ke daftar kolom score

from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
cluster_nums = [2,3,4,5,6,7]
scores = []
for cluster_num in cluster_nums:
    kmeans = KMeans(n_clusters = cluster_num,random_state=0)
    kmeans.fit(scaled_customers)
    clusters = kmeans.predict(scaled_customers)
    silhouette = silhouette_score(scaled_customers, clusters)
    scores.append(silhouette)

Setelah memplotnya, ternyata 5 cluster memiliki skor siluet tertinggi.

Kluster 2 dan 3 tampaknya memiliki skor siluet yang sama tinggi. Tapi saya akan menggunakan jumlah cluster 3 saja.

kmeans = KMeans(3)
kmeans.fit(scaled_customers)

Langkah 7 | Analisis

Mari kita lihat tiga pusat cluster – center. Cara aksesnya sebagai berikut

kmeans.cluster_centers_

array([[ 2.56188209e-04, -1.88159948e-02, -1.71282366e-02,
        -3.03679217e-02, -2.63061468e-02, -2.27507589e-02,
        -1.00864293e-02,  2.03527112e-02, -2.11499378e-02,
        -2.32509353e-03, -3.00544685e-02,  2.50466157e-03],
       [-1.14259631e-02,  1.37398260e+01,  1.25174061e+01,
         2.21658653e+01,  1.91765762e+01,  1.65974784e+01,
         7.46533542e+00, -5.77754576e-01,  1.19314711e+00,
         1.76567791e+00,  2.19365583e+01, -1.93067615e+00],
       [-5.24724782e-01, -1.62977342e-01, -1.78406253e-01,
        -2.34790636e-01, -1.29716217e-01, -1.50279233e-01,
        -3.87417609e-01, -4.26763521e+01,  4.25697229e+01,
        -2.23679645e-01, -2.30824555e-01,  3.26856915e-01]])

Mari kita ubah ini menjadi heatmap- ini akan lebih mudah dibaca.

plt.figure(figsize=(50,3.5))
sns.heatmap(scaler.inverse_transform(kmeans.cluster_centers_)[:,0:11],
            annot=True,
            yticklabels=['Cluster 1','Cluster 2','Cluster 3'],
            xticklabels=scaled_customers.columns.drop('CustomerID'))
plt.xticks(rotation=15)

Cluster kedua paling banyak customer yang beli dari luar UK – Foreign, Sedangkan untuk Cluster ketiga PurchaseMean mempunyai nilai tertinggi yaitu 1.7e5 atau sebanyak 170000 kali. Silahkan kalian intepretasikan sendiri saja

Leave a Reply

Your email address will not be published. Required fields are marked *

89 − = 84