iT邦幫忙

2022 iThome 鐵人賽

DAY 15
0
AI & Data

語言學與NLP系列 第 15

Day 15 支援向量機 Support Vector Machine 語言特徵相關實作篇

  • 分享至 

  • xImage
  •  

相信經過前兩天的科普(強迫灌輸??)之後,大家對 SVM 都有了相當的認識。不過,昨天的實作主要為了讓大家了解 SVM 切割方式,因此用了很簡單的資料集來做示範。然而,想必大家一定都知道,實際 NLP 任務時不會有那麼簡易的資料,不僅資料預處理很繁雜,提取語料特徵也是一門藝術 XD 因此,這篇要運用相對比較複雜的資料集、提取語言相關之特徵、使用之前提過的 TF 和 TF-IDF 作為其中一項訓練特徵以及偏向語言學的分析來帶大家更進一步認識 SVM。

Dataset + Classification 介紹

本篇使用的資料集為電商平台女裝評論(Women’s E-Commerce Clothing Reviews),資料來源自 Kaggle 平台(https://www.kaggle.com/datasets/nicapotato/womens-ecommerce-clothing-reviews)。因為這是一份真實的商業數據,因此評論進行了匿名處理,並將評論文本中公司和廠商的名字替換為「零售商」。這份資料集中包含10個欄位,分別為:

  1. 服裝 ID:特定產品的ID
  2. 年齡:評論者年齡
  3. 標題:評論標題
  4. 評論文本:評論正文
  5. 評級:客戶對產品的評分,1為最差,5為最佳
  6. 推薦:推薦為1,不推薦為0
  7. 正面反饋計數:記錄發現此評論正面的其他客戶數量
  8. 產品分類:大方向分類
  9. 產品部門:產品部門名稱的分類名稱
  10. 產品類別:產品名稱

而本篇要處理的分類問題是判斷客戶購買的產品是什麼(分為裙子 Dresses 和其他 Others),希望能夠透過評論的文本分類出哪些客戶購買裙裝,哪些不是。

The Purpose of this classification task

本篇分類目的為找出透過評論的文本分類出哪些客戶購買裙裝,哪些不是。判斷的方式是利用每一位顧客的評論文本,將其製作為一份 corpus,分別製作 TF 和 TF-IDF 兩種 SVM 分類器讓機器進行分類與預測。判斷是否能單純利用評論文本的 TF 或 TF-IDF 來預測顧客到底是不是購買裙裝。首先,先設定分類標籤,將購買裙裝的定為Dresses,非裙裝的產品則是 Others,接下來對評論文本進行預處理,包括斷詞、刪除停止詞、移除標點符號等等,將處理好的文本製作成 corpus 並且算出 TF 和 TF-IDF,將這兩份資料分別訓練出兩個 SVM 模型,最後進行預測。

R SVM ---- TF Classifier


# Preprocessing

review = read.csv('Womens Clothing E-Commerce Reviews.csv')

review<-review[!is.na(review$Review.Text), ]
review<-review[!is.na(review$Title), ] # 刪除 NA

labels = c()

for (i in seq_along(review$Class.Name)){
  if (review$Class.Name[i] == "Dresses"){
    labels[i] = 'Dresses'
  }else{
    labels[i] = 'Others'
  }
}

review$Label = labels # 把產品分為裙子 Dresses 和其他 Others,作為分類目標


library(tm)
library(tokenizers)

r <-as.vector(review$Review.Text)
r <-tokenize_words(r)



myStopwords= c(stopwords(), "the", "was", "a", "an", "this", "and", "to", "it", "that", "i")

# 製作 TF 的 dtm corpus

corpus_review = Corpus(VectorSource(r))
dtm_review = DocumentTermMatrix(corpus_review,
                         control = list(weighting = weightTf,# 在這邊設定!!
                                        stopwords = myStopwords,
                                        removePunctuation = T,
                                        removeNumbers = T,
                                        stemming = T))
                                        
# 調整一下 sparsity

dtm_review = removeSparseTerms(dtm_review, 0.8)


# Train SVM classifier with TF

library(caret)

review <- subset(review, select = -c(Clothing.ID, Title, Age, Department.Name, Rating, X, Positive.Feedback.Count, Class.Name))# 刪除不需要的欄位

set.seed(123)


trainIndex <- createDataPartition(review$Label, p=0.8, list=FALSE)

train_set <- as.matrix(dtm_review[trainIndex,])
test_set <- as.matrix(dtm_review[-trainIndex,])
train_labels <- review$Label[trainIndex]
test_labels <- review$Label[-trainIndex]

require(e1071)

svm_model = svm(x = train_set, y = as.factor(train_labels))


# confusion matrix

test_pred = predict(svm_model, test_set)
table(predict=test_pred, real=test_labels)

執行結果為:

svm_tf


# performance metrics + confusion matrix

table_matrix <- confusionMatrix(test_pred, as.factor(test_labels))
table_matrix

table_matrix$byClass["F1"] # 單獨看 F1-score

執行結果為:

svm_tf_c

F1-score
0.8120063

R SVM ---- TF-IDF Classifier


# TF-IDF Classifier

# Preprocessing

review = read.csv('/Womens Clothing E-Commerce Reviews.csv')

review<-review[!is.na(review$Review.Text), ]
review<-review[!is.na(review$Title), ]

labels = c()

for (i in seq_along(review$Class.Name)){
  if (review$Class.Name[i] == "Dresses"){
    labels[i] = 'Dresses'
  }else{
    labels[i] = 'Others'
  }
}

review$Label = labels



library(tm)
library(tokenizers)

r <-as.vector(review$Review.Text)
r <-tokenize_words(r)


# 製作 TF-IDF corpus

myStopwords= c(stopwords(), "the", "was", "a", "an", "this", "and", "to", "it", "that", "i")

corpus_review = Corpus(VectorSource(r))
dtm_review = DocumentTermMatrix(corpus_review,
                         control = list(weighting = weightTfIdf, # 在這裡調喔!!
                                        stopwords = myStopwords,
                                        removePunctuation = T,
                                        removeNumbers = T,
                                        stemming = T))


dtm_review = removeSparseTerms(dtm_review, 0.8)


# Train SVM classifier with TF-IDF

library(caret)

review <- subset(review, select = -c(Clothing.ID, Title, Age, Department.Name, Rating, X, Positive.Feedback.Count, Class.Name))# 刪除不需要的欄位


set.seed(123)


trainIndex <- createDataPartition(review$Label, p=0.8, list=FALSE)

train_set <- as.matrix(dtm_review[trainIndex,])
test_set <- as.matrix(dtm_review[-trainIndex,])
train_labels <- review$Label[trainIndex]
test_labels <- review$Label[-trainIndex]


require(e1071)

svm_model = svm(x = train_set, y = as.factor(train_labels))

table_matrix <- confusionMatrix(test_pred, as.factor(test_labels), mode='prec_recall')
table_matrix

table_matrix$byClass["F1"]

執行結果為:

svm_tfidf

F1-score
0.8123776

比較 TF 和 TF-IDF 模型,以 F1-score 來看的話,是 TF-IDF 的模型表現比較好,不過整體而言其實差異不大,所以也許之後可以不只使用 TF 或 TF-IDF 的方式來做 SVM ,而是可以多調 SVM 裡面不同的參數,看看是否能讓模型的預測更精準。

今天就介紹到這~感謝大家,我們明天見!


上一篇
Day 14 支援向量機 Support Vector Machine 實作篇
下一篇
Day 16 羅吉斯迴歸 Logistic Regression 介紹篇
系列文
語言學與NLP30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言