iT邦幫忙

2022 iThome 鐵人賽

DAY 11
0
AI & Data

語言學與NLP系列 第 11

Day 11 機器學習之決策樹(Decision Tree)

  • 分享至 

  • xImage
  •  

恭喜各位,經過前面 10 天的前情提要???之後,我們終於邁入機器學習(machine learning)的第一步----決策樹(Decision Tree)了!!!首先,我們先來了解一下何謂機器學習~

機器學習 (Machine Learning)

機器學習,簡稱 ML 是人工智慧 AI 的一種。是讓機器透過大量的資料來學習並改善其性能。機器學習和 AI 常常同時被提及。然而,二者之含義並不相同。不論其複雜的結構,簡單總結二者的區別就是:雖然所有機器學習都屬於 AI,但並非所有 AI 都是機器學習(可能是深度學習 Deep Learning)。

機器學習主要可分為兩種學習方式,分別為監督式學習(Supervised learning)與非監督式學習(Unsupervised Learning)。

  • 監督式學習:監督式學習的演算法是由已標示完成(labeled dataset),且能預先定義輸出的資料組訓練的。簡單來說,就是有「標準答案」的訓練方式。在此模式下,監督者(工程師、科學家......)會指導並修正、改善演算法,再讓演算法做出結論。經過一次次的修正和調配,讓機器的表現更好。此類模型包含線性(Linear Regression)及邏輯斯迴歸(Logistic Regression)、支援向量機(Support Vector Machine)等演算法。

  • 非監督式學習:顧名思義,與監督式學習相反,此類機器學習沒有以標示完成、有「標準答案」的資料集來做訓練。非監督式機器學習較為獨立,由電腦自行觀察學習輸入的資料集,整理歸納並定義出一套電腦的的流程和模式,人類不會持續提供修正。因為此過程是讓電腦自己去學習,因此很多時候人類無法得知電腦是如何做出這樣的判斷,依據又是什麼,只能透過電腦每一個階段的產出來「推測」其流程,再進行可能相應的改善。

今天要介紹的決策樹屬於一種多元酚類模型,是監督式學習。那廢話不多說,我們來看看該如何做決策樹的訓練吧~
在進行機器學習前,有幾個非常重要的步驟要事先想好或定義好:

  1. 了解自己的資料集
  2. 確認好分類任務的目的
  3. 進行資料預處理(可能包括 word segmentation、清洗資料、特徵提取等等,一切依你的任務目標決定)
  4. 決定評估模型的分數依據(這邊將會使用 F-score 評估模型)
  5. 若想要改善模型表現,可列出所有錯誤分類的案例,分析並做出可能的假設和解釋,
    去思考為什麼這些案例沒有被正確分類
  6. 依據前項分析,做出可能的修正

第一次做相關的訓練時,可以向我底下示範的那樣,將各個步驟進行的方式、流程與目的列出來。

決策樹訓練

  • 資料集大致介紹:今天的示範我將沿用上一篇的 IMDB 資料集做分類。此資料集包含電影名稱、電影描述、類別、導演、主演、上映年份、評分、電影時長、票房、投票數以及 Metascore 評分等資訊。而我在這裡要處理的分類問題是判斷電影的好壞(我將評分大於6設定為好電影),希望透過這樣的分類,找出影響電影評分高低的關鍵因素。

  • 確認分類目的:我的分類目的為找出影響電影評分高低的關鍵因素,判斷電影類別的多寡、電影主要類別、電影描述、投票數、票房以及 Metascore 是否為影響評分(好或壞的電影)的原因。

  • 資料預處理與提取之特徵描述(因為是 NLP 相關任務,故會使用較多的語言特徵):

    1. 首先,刪除我不需要的資料欄位,再將原始資料評分(Rating)這一項轉換為直觀的文字描述並設定為"Comments"欄位(Good movie: 6分以上,和 Bad movie),作為作為我希望模型分類、預測且回傳的指標。

    2. 另外,我將原始資料中的電影類別轉換為相對應的數量。例如 Guardians of the Galaxy 這部電影中包含 Action, Adventure, Sci-Fi 三種類別,則將其轉換為 3,將電影類別多寡作為一項特徵。另一項和 Genre 有關的特徵則是保留 Genre 中的第一項,視為電影主要類別,作為特徵加入決策樹的分類依據。

    3. 電影描述的部分則是分別抽取與家庭相關的關鍵詞(family, parents, daughter, son, children, wife, husband)和低落、害怕、寂寞等常見的負面情緒形容詞(lonely, sad, depressed, fear, hopeless, grief, isolated, lifeless, lost, frustrated, terrible),分別作為不同的語言特徵,用 TRUE 和 FALSE 呈現,即有這些關鍵詞的資料為 TRUE,沒有的就是 FALSE,用以了解與家庭相關或帶有許多負面情緒之電影內容是否也是評分的關鍵。

    4. 投票數、票房以及Metascore這三項數字相關的資料則是探究判斷電影的好壞是否與這些資訊呈現正相關。


library(tm)
library(tokenizers)

movie = read.csv("IMDB-Movie-Data.csv") # 讀取資料

movie<-movie[!is.na(movie$Metascore), ]
movie <- movie[!is.na(movie$Revenue..Millions.), ] # 刪除 NA


result <-c()
for(i in seq_along(movie$Rating)){
  
  if ((movie$Rating[i] >= '6.0')){
  result[i]= "Good movie"
  }else{
     result[i]= "Bad movie"
    }
  }
movie$Comments = result # 第一項特徵

g_type1 <- gsub("\\,\\w+", "", movie$Genre)
g_type2 <- gsub("\\-\\w+", "", g_type1)
g_type3 <- gsub("\\s", "", g_type2)
movie$Genre_type = g_type3 # 提取電影類別

g_clean<-sapply(strsplit(movie$Genre, ","), length)
movie$Genre = g_clean # 根據提取的電影類別轉換為類別數量,放進 Genre 這個欄位,即第二項特徵


# 第三項特徵
d1<-grepl('family|parents|daughter|son|children|wife|husband', movie$Description)
movie$Description_family = d1 # family 相關特徵

d2<-grepl('lonely|sad|depressed|fear|hopeless|grief|isolated|lifeless|lost|frustrated|terrible', movie$Description)
movie$Description_ng = d2 # negative sentiment 特徵



head(movie, 10) # 看看整理完的資料


執行結果為:

1

2


# Features + Model Training

set.seed(53) # 隨意設定種子數量
shuffle_index <- sample(1:nrow(movie)) 
movie <- movie[shuffle_index, ] # 打散資料

movie <- subset(movie, select = -c(Rank, Title, Actors, Director, Year, Runtime..Minutes., Rating, Description)) # 刪除不需要放進去訓練的欄位

movie$Genre <- as.character(movie$Genre)
movie$Description_family <- as.factor(movie$Description_family)
movie$Description_ng <- as.factor(movie$Description_ng)
movie$Comments <- as.factor(movie$Comments)
movie$Genre_type <- as.factor(movie$Genre_type) # 把要放進去訓練的「非」數字特徵換成 factor 讓電腦理解


library(caret) 

set.seed(111)

# 將資料分成 訓練集和測試集 8:2,百分之 80 的資料拿來訓練模型,百分之 20 的資料拿來測試模型的表現

trainIndex <- createDataPartition(movie$Comments, p=0.8, list=FALSE) # 以 Comments 這欄作為標準答案
    
train_set <- movie[trainIndex,]
test_set <- movie[-trainIndex,]

prop.table(table(train_set$Comments)) 
prop.table(table(test_set$Comments)) # 分別看看 train set & test set 資料分割的情況

執行結果為:
Bad movie Good movie
0.1773472 0.8226528

Bad movie Good movie
0.1736527 0.8263473 (train set & test set 都成功分割成大約 8:2 了)


library(rpart)
library(rpart.plot) # 引用 decision tree package


trained_model <- rpart(Comments~., data = train_set, method = 'class') # 以 Comments 為標準做分類

rpart.plot(trained_model, extra= 104)  # 畫出決策樹在做分類時的流程

執行結果為:

tree

可以看到最上方,也就根部(它是一棵倒著的樹xd)就是所有特徵中對決策樹分類時來說最重要的特徵。接著依次分類。


# Result + F score

predict_labels <- predict(trained_model, test_set, type = 'class')
table_matrix <- confusionMatrix(predict_labels, test_set$Comments, mode='prec_recall')
table_matrix

執行結果為:

result

可以看到雖然此模型的準確率(Accuracy)很高,但是 F-score 卻很低。可以推測模型可能亂猜居多,因為資料不平衡(Good Movie 在整份資料的佔比大於 Bad Movie 太多,導致模型只要猜 Good Movie,正確率就會很高。)

最後,我們列出分類錯誤的資料,方便分析、改進吧!


test_set[which(predict_labels != test_set$Comments), ] 

今天就先到這裡,明天再做更多模型表現分析的介紹與 Random Forest 吧!


上一篇
Day 10 一篇搞懂 R 語言的迴圈 Loop
下一篇
Day 12 模型表現判斷、分析與 Random Forest
系列文
語言學與NLP30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言