返回文章列表

無監督學習產品分群與主成分分析應用

本文探討無監督學習模型中的分群與主成分分析技術,並應用於產品分群案例。文章涵蓋資料預處理、特徵工程、K-means 分群演算法、肘部法、輪廓分數以及 PCA 降維與視覺化等關鍵技術,旨在利用產品描述文字資料進行相似產品分組,並提供實用的 Python 程式碼範例。

機器學習 資料分析

利用無監督學習技術中的分群和主成分分析方法,可以有效地對產品進行分群。首先,對原始資料進行預處理,包括處理缺失值、異常值以及無關欄位。接著,進行特徵工程,提取關鍵特徵,例如產品描述文字,並將其轉換為數值向量表示,例如 TF-IDF 向量。然後,應用 K-means 分群演算法將產品分組,並使用肘部法或輪廓分數等方法確定最佳的簇數。最後,利用主成分分析(PCA)技術降低資料維度,並將分群結果在二維或三維空間中視覺化,以便更直觀地理解產品分群的結構和模式。

# 載入必要的函式庫
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt

# 載入資料集
data = pd.read_csv('online_retail.csv', encoding='latin1')

# 資料預處理
data = data.dropna(subset=['CustomerID'])
data = data[(data['Quantity'] >= 0) & (data['UnitPrice'] >= 0)]
data['Amount'] = data['Quantity'] * data['UnitPrice']
data = data.groupby('CustomerID')['Amount'].sum().reset_index()

# 特徵工程 (簡化範例,使用 TotalAmount 作為單一特徵)
X = data[['Amount']]

# 使用 StandardScaler 進行資料標準化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# K-means 分群
kmeans = KMeans(n_clusters=5, random_state=0)  # 設定簇數為 5
kmeans.fit(X_scaled)

# PCA 降維
pca = PCA(n_components=2)  # 降維至 2 維
X_pca = pca.fit_transform(X_scaled)

# 視覺化分群結果
plt.scatter(X_pca[:, 0], X_pca[:, 1], c=kmeans.labels_)
plt.xlabel('PCA Component 1')
plt.ylabel('PCA Component 2')
plt.title('Customer Segmentation with K-means and PCA')
plt.show()

無監督學習:分群與主成分分析

在機器學習領域中,無監督學習模型能夠在未標註的資料中發現模式。分群是一種用於找出相似物件群組的技術,而主成分分析(PCA)則是一種用於降低資料維度的技術。本章將探討這兩種技術在產品分群中的應用,產品分群利用文字化的產品描述將相似產品分組。

在本章中,我們將:

  • 討論兩種無監督學習技術:分群和主成分分析。
  • 使用 K-means 分群演算法。

將問題分解為特徵

要將問題分解為特徵,需要考慮以下步驟:

  1. 資料準備:載入資料集並檢查資料結構、缺失值和整體特性。預處理資料,可能涉及處理缺失值、資料型別轉換和資料清理。
  2. 特徵工程:選擇相關特徵,從文字中提取特徵,並衍生新的特徵。
  3. 文字資料預處理:對文字進行分詞,移除標點符號和停用詞。使用詞頻-逆檔案頻率(TF-IDF)技術將文字轉換為數值格式。
  4. 應用分群演算法:建立 K-means 分群模型,並使用適當的技術(如肘部法和輪廓分數)確定最佳簇數。
  5. 評估和視覺化分群結果:評估分群效能,並使用 PCA 在降維空間中視覺化結果。

提示策略

本章使用 TAG 模式(任務-行動-指導),如第 2 章所述。我們知道以下要解決的問題:

  • 任務:建立客戶分群模型。
  • 行動:要求提供步驟和使用的技術。
  • 指導:要求逐步學習。

客戶分群

分群可以根據客戶的購買行為、偏好或人口統計資訊對客戶進行分段。透過分析客戶資料(如瀏覽歷史、購買歷史、位置和人口統計資訊),可以應用分群演算法來識別不同的客戶分段。這些資訊可用於個人化行銷活動、推薦相關產品或根據不同客戶群體定製使用者經驗。

資料集

我們將使用電子商務資料集,可以從 UCI 機器學習倉函式庫下載 CSV 檔案:https://archive.ics.uci.edu/dataset/352/online+retail。它包含 2010 年 12 月 1 日至 2011 年 12 月 9 日期間英國註冊的非實體店線上零售商的所有交易資料。

資料集包含以下欄位:

  • InvoiceNo:每個交易唯一分配的 6 位整數
  • StockCode:每個不同產品唯一分配的 5 位整數
  • Description:每個產品名稱的文字描述
  • Quantity:每個交易中每個產品(專案)的數量
  • InvoiceDate:每個交易生成的日期和時間
  • UnitPrice:每個單位產品的價格(英鎊)
  • CustomerID:每個客戶唯一分配的 5 位整數
  • Country:每個客戶所在國家/地區的名稱

將 AI 助手新增到無監督學習模型開發過程

讓我們利用 ChatGPT 為無監督學習模型開發過程新增 AI 助手。首先,我們向 ChatGPT 輪廓我們的任務。讓我們看看如何使用 TAG 模式:

  • 任務:我們的任務是建立一個分群模型。
# 載入必要的函式庫
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt

# 載入資料集
data = pd.read_csv('online_retail.csv')

# 檢視資料集的前幾行
print(data.head())

#### 內容解密:
這段程式碼首先載入了必要的 Python 函式庫包括 `pandas` 用於資料處理、`TfidfVectorizer` 用於將文字轉換為 TF-IDF 特徵、`KMeans` 用於執行 K-means 分群、`PCA` 用於降維以及 `matplotlib.pyplot` 用於視覺化然後它載入了電子商務資料集並查看了資料集的前幾行以瞭解其結構

載入與理解客戶細分聚類別模型的資料集

在進行客戶細分聚類別分析時,第一步是載入並理解所使用的資料集。以下將介紹如何使用Python在Jupyter Notebook中完成這項任務。

載入資料集

首先,需要從GitHub倉函式庫中載入名為data.csv的資料集。該資料集包含了客戶交易的詳細資訊,包括發票號、商品程式碼、描述、數量、發票日期、單價、客戶ID以及國家等欄位。

# 匯入必要的函式庫
import pandas as pd

# GitHub上原始CSV檔案的URL
data_url = "https://raw.githubusercontent.com/yourusername/yourrepository/master/data.csv"

# 使用latin1編碼讀取資料集到pandas DataFrame
df = pd.read_csv(data_url, encoding='latin1')

# 顯示DataFrame的形狀(行數,列數)
print("DataFrame的形狀:", df.shape)

# 顯示DataFrame的前幾行
print("DataFrame的前幾行:")
print(df.head())

內容解密:

  1. 匯入函式庫:使用import pandas as pd匯入pandas函式庫,這是Python中用於資料操作和分析的主要工具。
  2. 定義資料URL:將data_url變數設定為GitHub上data.csv檔案的原始URL。
  3. 讀取資料:使用pd.read_csv函式讀取CSV檔案到DataFrame df中,並指定encoding='latin1'以正確處理字元編碼。
  4. 顯示DataFrame資訊:透過df.shapedf.head()分別顯示DataFrame的行列數和前幾行的內容,以便初步瞭解資料。

檢查資料

接下來,需要檢查資料的欄位名稱、資料型別以及是否存在缺失值。

# 顯示欄位名稱和資料型別
print("欄位名稱和資料型別:")
print(df.dtypes)

# 檢查每個欄位的缺失值數量
print("\n每個欄位的缺失值數量:")
print(df.isnull().sum())

內容解密:

  1. 欄位名稱和資料型別:使用df.dtypes檢視每個欄位的資料型別,有助於瞭解資料的儲存格式。
  2. 檢查缺失值:透過df.isnull().sum()計算每個欄位的缺失值數量,這對於後續的資料預處理非常重要。
內容解密:
  1. 計算總結統計:使用df.describe(include='all')計算所有欄位的總結統計,包括數值和非數值欄位。
  2. 轉置總結統計:透過summary_stats.transpose()將總結統計轉置,使其更易於閱讀。
  3. 顯示總結統計:最後,列印預出轉置後的總結統計結果。

後續步驟

完成上述步驟後,將對資料集有初步的瞭解。接下來,需要進行資料預處理,以便將資料用於客戶細分聚類別模型。具體的預處理步驟將在下一小節中介紹。

資料載入與理解流程

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title 無監督學習產品分群與主成分分析應用

package "無監督學習分群" {
    package "資料預處理" {
        component [缺失值處理] as missing
        component [異常值處理] as outlier
        component [TF-IDF 向量化] as tfidf
    }

    package "分群演算法" {
        component [K-means] as kmeans
        component [肘部法] as elbow
        component [輪廓分數] as silhouette
    }

    package "降維視覺化" {
        component [PCA 降維] as pca
        component [2D/3D 視覺化] as viz
        component [分群解讀] as interpret
    }
}

missing --> outlier : 資料清洗
outlier --> tfidf : 欄位篩選
tfidf --> kmeans : 文字向量
kmeans --> elbow : 分群執行
elbow --> silhouette : 簇數選擇
silhouette --> pca : 品質評估
pca --> viz : 維度壓縮
viz --> interpret : 結果呈現

note right of tfidf
  特徵工程:
  - TF-IDF 文字向量
  - 資料標準化
  - 產品描述提取
end note

note right of silhouette
  評估方法:
  - 肘部法則
  - 輪廓分數
  - 群內/群間距離
end note

@enduml

此圖示展示了從載入資料集到進行客戶細分聚類別分析的整個流程。

無監督學習:客戶分群與主成分分析(PCA)

資料預處理

在檢視資料後,我們發現CustomerID欄位存在缺失值。為了使用這些資料進行客戶分群聚類別模型的訓練,我們需要移除這些缺失值。此外,QuantityUnitPrice等數值欄位也包含一些負值,這些同樣需要被移除。我們將捨棄一些對客戶分群聚類別模型無用的欄位,包括StockCodeInvoiceDateDescriptionCountry

預處理步驟實作

# 步驟 4:資料預處理
# 1. 移除CustomerID欄位中的缺失值
df_cleaned = df.dropna(subset=['CustomerID'])

# 2. 移除Quantity和UnitPrice欄位中的負值
df_cleaned = df_cleaned[(df_cleaned['Quantity'] >= 0) & (df_cleaned['UnitPrice'] >= 0)]

# 3. 移除未使用的欄位:'StockCode', 'InvoiceDate', 'Description', 'Country'
columns_to_drop = ['StockCode', 'InvoiceDate', 'Description', 'Country']
df_cleaned = df_cleaned.drop(columns=columns_to_drop)

# 顯示清理後的DataFrame形狀
print("清理後的DataFrame形狀:", df_cleaned.shape)

# 顯示清理後的DataFrame前幾行
print("\n清理後的DataFrame前幾行:")
print(df_cleaned.head())

程式碼解說:

  1. 使用dropna()函式移除CustomerID欄位中缺失值對應的列,以確保客戶ID的有效性。
  2. 使用布林索引過濾掉QuantityUnitPrice欄位中為負值的列,僅保留非負值的交易記錄。
  3. 使用drop()函式移除無用的欄位,如StockCodeInvoiceDateDescriptionCountry

特徵工程

為了幫助客戶分群聚類別模型的訓練,我們需要進行特徵工程,建立新的特徵。首先,透過將QuantityUnitPrice欄位相乘來建立一個名為Amount的新欄位。然後,根據CustomerIDAmount進行匯總,建立一個名為TotalAmount的欄位。同時,計算每個客戶的交易次數,建立一個名為TotalTransactions的欄位。用於客戶分群的資料集將包含兩個欄位:TotalAmountTotalTransactions

特徵工程實作

# 步驟 5:特徵工程
# 1. 建立Amount欄位:將Quantity和UnitPrice欄位相乘
df_cleaned['Amount'] = df_cleaned['Quantity'] * df_cleaned['UnitPrice']

# 2. 建立TotalAmount欄位:根據CustomerID匯總Amount
df_total_amount = df_cleaned.groupby('CustomerID')['Amount'].sum().reset_index()
df_total_amount.rename(columns={'Amount': 'TotalAmount'}, inplace=True)

# 3. 建立TotalTransactions欄位:計算每個CustomerID的發票數量
df_total_transactions = df_cleaned.groupby('CustomerID')['InvoiceNo'].nunique().reset_index()
df_total_transactions.rename(columns={'InvoiceNo': 'TotalTransactions'}, inplace=True)

# 4. 建立客戶分群資料集:合併TotalAmount和TotalTransactions
df_segmentation = pd.merge(df_total_amount, df_total_transactions, on='CustomerID')

# 顯示客戶分群DataFrame的前幾行
print("客戶分群DataFrame:")
print(df_segmentation.head())

程式碼解說:

  1. 透過將QuantityUnitPrice欄位相乘來建立新的Amount欄位,以計算每筆交易的總金額。
  2. 使用groupby()sum()函式根據CustomerID匯總所有交易的Amount,計算每個客戶的總消費金額(TotalAmount)。
  3. 使用groupby()nunique()函式計算每個客戶的唯一發票數量,以代表客戶的交易次數(TotalTransactions)。
  4. 將包含TotalAmount和TotalTransactions的DataFrame合併,建立最終的客戶分群資料集。

重點分析與未來趨勢

透過資料預處理和特徵工程,我們成功地準備了用於客戶分群的資料集。這種方法不僅能夠幫助企業更好地瞭解其客戶群體,還可以為精準行銷提供有力的資料支援。未來,可以考慮結合更多的特徵,例如客戶的人口統計資訊或行為資料,以進一步提高客戶分群的準確性。隨著機器學習技術的不斷進步,客戶分群的應用將更加廣泛和深入。

客戶分群分析中的離群值處理與資料標準化

在進行客戶分群分析時,資料的品質與預處理步驟對於最終的分群結果具有決定性的影響。本章節將探討如何檢查與移除離群值,以及如何透過資料標準化來提升分群分析的準確性。

建立客戶分群特徵

首先,我們需要建立用於客戶分群的特徵。在此案例中,我們關注兩個主要的特徵:客戶的總消費金額(TotalAmount)與總交易次數(TotalTransactions)。這兩個特徵能夠有效地反映客戶的消費行為與忠誠度。

# 建立客戶分群特徵
df_segmentation = df_total_amount.merge(df_total_transactions, on='CustomerID')

內容解密:

  1. df_total_amountdf_total_transactions 分別代表客戶的總消費金額與總交易次數,這些是透過對原始資料進行分組與匯總計算得到的。
  2. merge 函式用於根據 CustomerID 將兩個資料集合併為一個新的 DataFrame df_segmentation

檢查離群值

在進行分群分析之前,檢查資料中的離群值是非常重要的步驟。離群值可能會對分群結果產生不利影響,因此需要仔細檢查並適當處理。

# 刪除 CustomerID 列
df_segmentation.drop('CustomerID', axis=1, inplace=True)

# 使用箱型圖檢查離群值
import matplotlib.pyplot as plt
plt.figure(figsize=(8, 5))
plt.boxplot([df_segmentation['TotalAmount'], df_segmentation['TotalTransactions']], labels=['TotalAmount', 'TotalTransactions'])
plt.title('TotalAmount 與 TotalTransactions 的箱型圖')
plt.ylabel('數值')
plt.show()

內容解密:

  1. drop 函式用於刪除 CustomerID 列,因為該列不參與分群分析。
  2. 箱型圖是一種有效的視覺化工具,用於識別資料中的離群值。箱型圖中的「箱子」代表了資料的四分位距(IQR),而「鬍鬚」以外的點則被視為潛在的離群值。
  3. 透過視覺化檢查,可以直觀地判斷是否存在離群值,並根據具體情況決定如何處理這些離群值。

移除離群值

一旦發現離群值,就需要決定是否移除或以其他方式處理這些資料。在本案例中,我們選擇使用 IQR 方法來檢測並移除離群值。

# 計算 TotalAmount 列的 IQR
Q1 = df_segmentation['TotalAmount'].quantile(0.25)
Q3 = df_segmentation['TotalAmount'].quantile(0.75)
IQR = Q3 - Q1

# 定義離群值檢測的上下限
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

# 移除 TotalAmount 列中的離群值
df_segmentation = df_segmentation[(df_segmentation['TotalAmount'] >= lower_bound) & (df_segmentation['TotalAmount'] <= upper_bound)]

# 輸出移除離群值後的 DataFrame 大小
print("移除離群值後的 DataFrame 大小:", df_segmentation.shape)

內容解密:

  1. IQR 方法是一種常見的離群值檢測方法,透過計算第一四分位數(Q1)與第三四分位數(Q3)之間的差值來定義資料的正常範圍。
  2. 將超出 Q1 - 1.5*IQRQ3 + 1.5*IQR 範圍的資料視為離群值,並將其移除。
  3. 移除離群值後,DataFrame 的大小會發生變化,這可以透過比較 shape 屬性的變化來觀察。

資料標準化

在進行分群分析時,資料標準化是至關重要的步驟。標準化可以確保不同特徵在相同的尺度上,避免某些特徵因尺度差異而主導分群結果。

# 使用 StandardScaler 進行資料標準化
from sklearn.preprocessing import StandardScaler

# 初始化 StandardScaler
scaler = StandardScaler()

# 對 TotalAmount 與 TotalTransactions 進行標準化
df_scaled = scaler.fit_transform(df_segmentation)

# 將標準化後的陣列轉換回 DataFrame

內容解密:

  1. StandardScaler 是 scikit-learn 提供的一種標準化工具,可以將資料轉換為均值為 0、標準差為 1 的分佈。
  2. 標準化的過程包括了對原始資料進行擬合(fit)與轉換(transform),確保所有特徵在相同的尺度上。
  3. 將標準化後的結果轉換回 DataFrame,以便於後續的分群分析。