บทความ

ไม่ว่าจะ ข่าวสาร บทสัมภาษณ์ และ Digital Skill บนสื่อ
มีให้คุณได้อ่านบทความดี ๆ มากมายแล้วที่นี่

มาเล่น Sentiment Analysis โดยใช้ Python กัน

มาเล่น Sentiment Analysis โดยใช้ Python กัน



How is it going? Positive, Neutral, or Negative?


เกริ่นก่อน Sentiment Analysis เนี่ย มันคือกระบวนการที่เราสามารถบอกและแยกแยะอารมณ์ที่แสดงออกมาในข้อความหนึ่งๆ ซึ่งในข้อความนั้นๆ อาจจะออกมาเป็นแง่บวก (positive) แง่ลบ (negative) หรือแบบเฉยๆ (neutral) ก็ได้

ปัญหาของเราคือ ถ้าเรามีข้อมูลประมาณด้านล่างนี้ เราจะเอาไปสร้างโมเดล Sentiment Analysis อย่างไร?

ข้อมูล Feedback จากระบบหนึ่ง


เอ๊ะ ที่เราเรียนมาข้อมูลมันจะออกแนวแบ่งเป็น Column ไม่ใช่เหรอ แต่ละ Column คือ 1 Feature ไม่ใช่เหรอ แล้วถ้าเป็นข้อความแบบนี้เราจะทำอย่างไรดีนะ 🤔

มีวิธี Preprocessing อยู่หลายแบบครับ แบบที่ง่ายๆ ที่เราจะมาลองกันในบทความนี้เรียกว่า Bag-of-words model ครับผม ขอเอาตัวอย่างจากใน Wiki มาอธิบายนะครับ ถ้าข้อความเราคือ

John likes to watch movies. Mary likes movies too.

เราจะแปลงให้อยู่ในรูปแบบของ JSON ได้แบบนี้

bag_of_words_1 = {"John": 1, "likes": 2, "to": 1, "watch": 1, "movies": 2, "Mary":1, "too": 1}

สังเกตไหมว่าจริงๆ แล้วมันคือการนับคำนั่นเอง!! 😎 แล้วแต่ละ Key คือคำที่อยู่ในข้อความ และ Value คือจำนวนคำๆ นั้นในข้อความนั่นเอง ถ้ายังไม่คุ้น ลองมาดูในรูปแบบที่เราคุ้นเคยกันดีกว่า

Bag of Words จากข้อความ “John likes to watch movies. Mary likes movies too.”

Key ใน JSON เราสามารถมองเป็นหัว Column ได้เลย ถ้ายังมึนๆ อยู่ ลองดูรูปด้านล่างนี้ครับ น่าจะช่วยให้เข้าใจมากขึ้น 👍

รูป Bag of Words จาก https://slideplayer.com/slide/7073400/


ทีนี้ปัญหาของเราก็จะอยู่ที่ว่าเราจะเลือกคำอะไรบ้างเอามาสร้างโมเดล ซึ่งตรงจุดนี้เป็นจุดที่ยากที่สุดครับ.. วิธีการเลือกคำนี่สามารถเป็นอีกศาสตร์หนึ่งได้เลย ศาสตร์นั้นคือ Natural language processing ครับผม ลองไปศึกษาเพิ่มเติมกันดูเนอะ

กลับมาที่ข้อมูลเราบ้าง เราจะใช้ตัวช่วยนับ CountVectorizer จาก Scikit-Learn ครับ ง่ายมาก! ตามนี้เลย

import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
text = [
'Promptly answer to my request.',
'great turnaround time!',
'Fast response and great service!',
'As usual you took the request and completed in as few steps as possible and well done!',
'Very quick turnaround time and great communication. Thank you!',
'Really quick turnaround. Thanks!!',
'reduce the turn around time and increase/upgrade the interaction ability between the client and the pronto team during the building of the website.',
'Better turn around time for changes and updates. Better copywriting talents for web content rewrite requests.',
'Get back to us faster',
'Be more careful when fixing our site to not break the other coding on other pages',
'All of the information for this listing is already on the website that Pronto built. It is disappointing that this has taken so many tries to get right.',
'slow communication regarding SEO questions, emailing SEO team direct has been slower that going through my account rep- vague and incomplete answers wasting time',
'The time difference and language barrier are my main complaints. Otherwise our website looks great.',
'Process is way too slow. Working with another country seems to really slow things down alot.',
]
label = [
'positive',
'positive',
'positive',
'positive',
'positive',
'positive',
'neutral',
'neutral',
'neutral',
'neutral',
'negative',
'negative',
'negative',
'negative',
]
df = pd.DataFrame(data={
'text': text,
'label': label
})
vectorizer = CountVectorizer(stop_words='english')
X_train = df.text
y_train = df.label
X_train_vectorized = vectorizer.fit_transform(X_train)

เพียงเท่านี้เราจะได้ข้อมูลของเราอยู่ในรูปแบบที่เราต้องการแล้วววว

ข้อมูลข้อความหลังจากที่ทำ Bag of Words


ถ้าเราอยากดูว่า CounterVectorizer เลือกคำอะไรมาให้เราบ้าง เราจะสั่งฟังก์ชั่น get_feature_names ตามนี้กับตัว vectorizer ของเราครับ

คำที่ CountVectorizer เลือกมา


เท่านี้เราก็สามารถนำเข้าโมเดลของเราได้แล้วครับ จัดกันเลย~ ลอง Naive Bayes ละกัน

# import
from sklearn import naive_bayes
# instantiate
clf = naive_bayes.MultinomialNB()
# fit
clf.fit(X_train_vectorized, y_train)

แล้วถ้าเราอยากจะลองทดสอบกับข้อความใหม่ เพื่อดูว่าจะเป็น Positive, Neutral หรือ Negative สิ่งที่เราต้องทำก่อนคือ เราต้องแปลงข้อความใหม่นั้นให้อยู่ใน Bag of Words แบบเดียวกับที่เราเอาเข้าไปสอนโมเดลของเราก่อนครับ ซึ่งวิธีการแปลงเราจะ “ต้อง” เอาตัว vectorizer ที่เราสร้างไว้กับข้อมูลที่ใช้สอนมาใช้ตรงนี้ครับ จุดนี้สำคัญเลย

“เราแปลงข้อมูลที่เราใช้สอนด้วยวิธีไหน เราต้องแปลงข้อมูลที่เราจะใช้ทดสอบด้วยวิธีเดียวกัน”

ทำได้ตามนี้ (ข้อความแรกเป็น Positive ข้อความที่ 2 เป็น Neutral ส่วนข้อความที่ 3 เป็น Negative)

# positive, neutral, negative
X_test = [
'Fast service! Thank you',
'wish it could have been resolved sooner as it was simple',
'Cannot get my website where I want because repeated requests are misunderstood, requests are simply not honored.',
]
X_test_vectorized = vectorizer.transform(X_test)

ตัวแปร X_test_vectorized จะเป็นตัวแปรที่แปลงข้อความ 3 ข้อความนั้นให้อยู่ในรูปแบบของ Bag of Words ให้เรา ต่อจากนี้เราก็เอาไปทดสอบกับโมเดลของเราได้เลย

โค้ดส่วนการสร้างโมเดล Sentiment Analysis


เราเพิ่งจะสร้างโมเดลทำ Sentiment Analysis ไปเรียบร้อยแล้ว 🎉

ผลที่ได้ออกมาก็ดูพอไปวัดไปวาได้ครับ แต่อย่าเพิ่งเชื่อถือมากไปนะ 😂 เราควรปรับโมเดลของเราให้ดีขึ้นเรื่อยๆ ทำให้น่าเชื่อถือมากขึ้น ข้อมูลเพิ่ม เลือกคำให้ดีขึ้น ทำ Cross Validation ทำ ฯลฯ

ขอให้สนุกกับการทำ Sentiment Analysis ครับผม 😙

Kan Ouivirach | Machine Learning

03/05/2019