15 มีนาคม 2561

Published 3/15/2561 by with 1 comment

ทำ Sentiment Analysis ภาษาไทยโดยใช้ NLTK

หลังจากที่บทความ ทำ Sentiment Analysis ภาษาไทยใน Python ถูกเผยแพร่ออกไปเป็นระยะเวลาเกือบ 1 ปี ได้มีผู้สนใจจำนวนมากและติดกับปัญหาที่ใช้เวลา train ที่นานมาก (บางท่านบอกว่า train เป็นวันก็ยังไม่เสร็จ แค่บางท่าน ไม่กี่นาทีก็เสร็จ) ผมเลยเขียนบทความนี้ขึ้นมาใหม่ โดยใช้โค้ดตัวใหม่ที่ train ได้รวดเร็วยิ่งขึ้นกว่าเดิม

ก่อนเริ่มทำ Sentiment Analysis ให้ทำการติดตั้ง NLTK และ PyThaiNLP ก่อน ด้วยคำสั่ง pip install nltk pythainlp

Sentiment Analysis คืออะไร ?

Sentiment Analysis หรือชื่อในภาษาไทย "การวิเคราะห์ความรู้สึก" เป็นการวิเคราะห์อารมณ์และความรู้สึกจากข้อความ เพื่อบ่งบอกความรู้สึกของผู้คนที่มีต่อบางสิ่งบางอย่าง เช่น ความรู้สึกดี (Positive) หรือ ความรู้สึกที่ไม่ดี (Negative)

การทำงานของ Sentiment Analysis

อย่างแรกนำข้อความมาแบ่งคำ (ใช้ PyThaiNLP) แล้วหาความสัมพันธ์ระหว่าง "คำ" และ "เอกสาร" ที่มีอยู่ ในรูปแบบของเวกเตอร์ ต่อมาสร้างโมเดล Sentiment Analysis ด้วยอัลกอริทึม Naive Bayes (ใช้ NLTK) แล้วนำข้อความที่ต้องการ มาแบ่งคำแล้วใช้โมเดล Sentiment Analysis ที่สร้างแล้วส่งค่าออกมา

หลักการทำงานอัลกอริทึม Naive Bayes อ่านได้ที่ http://dataminingtrend.com/2014/naive-bayes/

ก่อนลงมือโค้ด ให้ทำการเตรียมไฟล์ pos.txt และ neg.txt ซึ่ง pos.txt เก็บข้อความที่เป็น positive และ neg.txt เก็บข้อความที่เป็น negative โดยเก็บประโยคละบรรทัด

ตัวอย่างเช่น
pos.txt 
เขาเป็นคนดี ช่วยแมวที่กำลังจะตกจากอาคารสูง น่าชื่นชมนะเขาเป็นคนกล้าแสดงออก
neg.txt
เขาชอบโดดงาน
เขาทำงานบกพร่อง

มาลงมือโค้ดกันเลย
ให้ import โมดูลเข้ามา
import nltk, re,codecs
from pythainlp.tokenize import word_tokenize
แล้วต่อมาสร้างตัวแปร
features = []
สำหรับใช้เก็บ features จากทั้งหมด
สร้างฟังก์ชัน get_words_in_reviews สำหรับใช้แยก word ออกจาก (words, sentiment) ให้เป็น list
def get_words_in_reviews(all_reviews):
  all_words = []
  for (words, sentiment) in all_reviews:
    all_words.extend(words)
  return all_words

แล้วสร้างฟังก์ชัน get_word_features
def get_word_features(list_of_words):
  list_of_words = nltk.FreqDist(list_of_words)
  word_features = list_of_words.keys()
  return word_features

ใช้สำหรับคืนค่าคำโดยไม่ให้ซ้ำกัน
แล้วสร้างฟังก์ชัน extract_features สำหรับดึง features
def extract_features(document):
  document_words = set(document)
  features = {}
  for word in features:
    features['contains(%s)' % word] = (word in document_words)
  return features
แล้วสร้างฟังก์ชันสำหรับทำงาน ตัวอย่างเช่น ฟังก์ชัน train กันเลย
def train():
  #สำหรับเปิดไฟล์ที่เป็น positive และ negative
  pos_reviews_file = codecs.open('pos.txt', 'r', "utf-8")
  neg_reviews_file = codecs.open('neg.txt', 'r', "utf-8")
  pos_reviews = []
  for each_review in pos_reviews_file:
    each_review = ' '.join(word_tokenize(each_review)) # ตัดคำ
    if each_review.endswith('\n'):
      each_review = each_review[:-1]
    if not each_review == '':
      pos_reviews.append([each_review,'pos']) # แท็ก pos

  #เก็บ negative ให้เป็น list -----------------------------------------
  neg_reviews = []
  for each_review in neg_reviews_file:
    each_review = ' '.join(word_tokenize(each_review))
    if each_review.endswith('\n'):
      each_review = each_review[:-1]
    if not each_review == '':
      neg_reviews.append([each_review,'neg']) # แท็ก neg
  all_reviews = []
  for (review, sentiment) in pos_reviews + neg_reviews:
    reviews_filtered = [w.lower() for w in word_tokenize(review)]
  all_reviews.append((reviews_filtered, sentiment))
  global features
  features = get_word_features(get_words_in_reviews(all_reviews))
  training_set = nltk.classify.apply_features(extract_features, all_reviews)
  classifier = nltk.NaiveBayesClassifier.train(training_set) # ทำการ train
  return classifier

แล้วมาลองเรียกใช้งานกันเลย
classifier = train()
read_in = input('Enter >>> ')
while read_in != 'exit':
  print ('\n' + classifier.classify(extract_features(word_tokenize(read_in))))
  read_in = input('Enter >>> ')


โค้ดฉบับเต็ม
ข้อควรรู้
  • ข้อมูลทั้ง positive และ negative ควรมีขนาดเท่ากัน
  • หากต้องการทำ text classification ให้สร้างไฟล์ข้อมูล และ เพิ่ม tag โดยดูตามตัวอย่างโค้ด

1 ความคิดเห็น:

  1. พอใส่ข้อความแล้วenterเข้าไปมันเกิดerorครับ เช่น Enter >>> www output เป็น NameError: name 'www' is not defined

    ตอบลบ

แสดงความคิดเห็นได้ครับ :)