按照慣例,在介紹完 logistic regression 和基礎的 Python 與 R 的 logistic regression 實作之後,我們就要進入到語言特徵相關的實作了(模擬 NLP 可能會遇到的任務)。
這次一樣使用 SVM 語言特徵相關實作篇使用的 dataset(比較方便 XD),不過訓練方法有些不同。以下幫大家複習一下任務目標和 dataset 內容。
使用的資料集為電商平台女裝評論(Women’s E-Commerce Clothing Reviews),因為這是一份真實的商業數據,因此評論進行了匿名處理,並將評論文本中公司和廠商的名字替換為「零售商」。這份資料集中包含10個欄位,分別為: 1. 服裝 ID:特定產品的ID 2. 年齡:評論者年齡 3. 標題:評論標題 4. 評論文本:評論正文 5. 評級:客戶對產品的評分,1為最差,5為最佳 6. 推薦:推薦為1,不推薦為0 7. 正面反饋計數:記錄發現此評論正面的其他客戶數量。 8. 產品分類:大方向分類。 9. 產品部門:產品部門名稱的分類名稱。 10. 產品類別:產品名稱。
而我在這裡要處理的分類問題是判斷客戶購買的產品是什麼(分為裙子 Dresses 和其他 Others),希望能夠透過評論的文本分類出哪些客戶購買裙裝,哪些不是。
此次分類目的為找出透過評論的文本分類出哪些客戶購買裙裝,哪些不是。訓練 Logistic Regression 模型來進行分類判斷。此模型是使用 unigram + bigram_trigram 的方式訓練,並進行 10-fold cross-validation。首先,先設定分類標籤,將購買裙裝的定為Dresses,非裙裝的產品則是Others,接下來對評論文本進行預處理,包括斷詞、刪除停止詞、移除標點符號等等,將處理好的文本製作成unigram + bigram_trigram 的形式,訓練出模型,最後進行預測。
# unigram+bigram+trigram with 10-fold cross-validation
# Preprocessing
library(text2vec)
library(data.table)
library(magrittr)
library(tm)
review = read.csv('Womens Clothing E-Commerce Reviews.csv')
review<-review[!is.na(review$Review.Text), ]
review<-review[!is.na(review$Title), ]
label = c()
for (i in seq_along(review$Class.Name)){
if (review$Class.Name[i] == "Dresses"){
label <- c(label, 1)
}else{
label <- c(label, 0)
}
}
label = factor(label, levels=c(1,0), labels = c('Dresses', 'Others'))
review$Label = label
review <- subset(review, select = -c(Clothing.ID, Title, Age, Department.Name, Rating, Positive.Feedback.Count, Recommended.IND, Class.Name))
myStopwords= c(stopwords(), "the", "was", "a", "an", "this", "and", "to", "it", "that", "i")
review$Review.Text <- removePunctuation(review$Review.Text )
review$Review.Text <- removeWords(review$Review.Text, myStopwords)
review$Review.Text <- removeNumbers(review$Review.Text)
# Train a model with unigram+bigram+trigram with 10-fold cross-validation
library(caret)
set.seed(123)
trainIndex <- createDataPartition(review$Label, p=0.8, list=FALSE)
train_set <- review[trainIndex,]
test_set <- review[-trainIndex,] # 分 training & test set
it_train = itoken(train_set$Review.Text,
preprocessor = tolower,
tokenizer = word_tokenizer,
ids = train_set$X,
progressbar = FALSE) # 對 Review 這個欄位進行大小寫轉換和斷詞
stop_words = c("the", "was", "a", "an", "this", "and", "to", "it", "that", "i") # 去除停用詞
vocab = create_vocabulary(it_train, stopwords = stop_words) # 列出 review 中的所有單字
vocab = create_vocabulary(it_train, ngram = c(1L, 3L)) # 列出 unigram 和 trigram
vocab = prune_vocabulary(vocab, term_count_min = 10,
doc_proportion_max = 0.5)
trigram_vectorizer = vocab_vectorizer(vocab)
dtm_train = create_dtm(it_train, trigram_vectorizer)
# 訓練 logistic regression
library(glmnet)
NFOLDS = 10 # 交叉驗證
glmnet_classifier = cv.glmnet(x = dtm_train, y = train_set$Label,
family = 'binomial',
alpha = 1,
type.measure = "auc",
nfolds = NFOLDS,
thresh = 1e-3,
maxit = 1e3)
it_test = word_tokenizer(tolower(test_set$Review.Text))
it_test = itoken(it_test, ids = test_set$X, progressbar = FALSE)
dtm_test = create_dtm(it_test, trigram_vectorizer)
preds = predict(glmnet_classifier, dtm_test, type = 'response')[,1]
glmnet:::auc(test_set$Label, preds)
執行結果為:
[1] 0.9689055
# 製作 confusion matrix & Performance metrics
glmnet_classifier_pred = ifelse(predict(glmnet_classifier, dtm_test, type = 'response')>0.5, "Others", "Dresses")
table = table(actual = test_set$Label, predicted = glmnet_classifier_pred)
result = confusionMatrix(table, positive = "Others")
result
執行結果為:
今天就到這~謝謝大家!我們明天見