Download as pdf or txt
Download as pdf or txt
You are on page 1of 9

8/26/2019 [VNLP Core] [3] Bài toán phân loại văn bản - Phân tích cảm xúc của

xúc của bình luận (text classification) - NLP - Diễn đàn Machine Learning cơ…

Home Blog Facebook Page Facebook Group Interactive Learning Competition

[VNLP Core] [3] Bài toán phân loại văn bản - Phân tích cảm
xúc của bình luận (text classification)
classification nlp-tiengviet sentiment-analysis text

pencil.forever Th09 '18


Th09
Bài toán phân loại văn bản (text classification) được thấy rất nhiều trong các ứng dụng NLP (xử lý ngôn ngữ tự nhiên),
2018
ví dụ bài toán phân loại cảm xúc hay thái độ của người dùng qua bình luận (comment) trên các trang phim, mv ca 1/
nhạc, đánh giá về sản phẩm … Hay như trong ứng dụng chatbot, bài toán phân loại văn bản được sử dụng để phát 24
hiện mục đích của người dùng. Hãy xem một số ví dụ cụ thể dưới đây: Th09
2018
Ví dụ đánh giá phim:

Phim rất thú vị (class: positive)


Xem rất chán (class: negative)

Dựa vào việc phân loại được tự động các bình luận chúng ta có thể đánh giá được tác động của một sản phẩm, dịch
vụ, xu hướng lên khách hàng, cộng đồng là tích cực hay tiêu cực để có những chiến lược kinh doanh phù hợp. Các
công cụ như thế kết hợp với các công cụ thu thập dữ liệu tự động từ nhiều nguồn khác nhau (mạng xã hội, báo điện
tử, diễn đàn…) sẽ tạo lên bộ công cụ điều tra thăm dò cực kỳ giá trị.

Ví dụ trong chatbot:
25d
Tôi muốn đặt hoa (class: flower_order) ngày
Mình huỷ đơn hàng được không (class: order_cancel) trước

Khi biết được mục đích của người dùng, chatbot có thể đưa ra những hành động phù hợp tương ứng. Ví dụ với class
là flower_order thì chatbot có thể trả lời lại: “Bạn muốn đặt loại hoa nào?” Với bài toán phân loại văn bản, chúng ta đã
có thể giải quyết khá nhiều các đoạn hội thoại đơn giản nhưng lại rất quan trọng để thay thế bớt nhiều sức lực cho con
người.

Ở một bài trước mình đã giới thiệu một số hướng giải quyết bài toán phân loại văn bản Bài toán phân loại văn bản.
Trong bài này mình sẽ giới thiệu một hướng tiếp cận cụ thể, với một ví dụ cụ thể cho dữ liệu tiếng Việt. Chúng ta sẽ
cùng nhau xem và giải quyết bài toán phân tích cảm xúc/ thái độ của bình luận phim bằng mô hình deep learning.

1. Chuẩn bị dữ liệu

Dữ liệu bạn có thể thu thập ở bất cứ nguồn nào, ví dụ crawl từ facebook, các trang phim… Miễn là bạn xử lý để tách
được các câu bình luận tiếng Việt. Ví dụ bình luận trên youtube bạn có thể crawl bằng tài khoản google, bình luận
phim có thể crawl không cần tài khoản (Bạn có thể sử dụng urllib, BeautifulSoup của python cũng có thể crawl được.
Một số hàm bạn có thể tham khảo tại đây ).

Ở đây mình đơn giản hoá bằng cách lấy sẵn một số câu bình luận phim, đặt vào 2 files khác nhau (thích, không thích).
Bạn có thể mở rộng bằng cách thêm dữ liệu vào, tạo thêm file số 3, chẳng hạn như neutral.txt (không thích cũng
không chê). Một số mẫu trong file positive.txt :

phim hay quá ae


hay thế
phim hay tuyệt

https://forum.machinelearningcoban.com/t/vnlp-core-3-bai-toan-phan-loai-van-ban-phan-tich-cam-xuc-cua-binh-luan-text-classification/2371 1/9
8/26/2019 [VNLP Core] [3] Bài toán phân loại văn bản - Phân tích cảm xúc của bình luận (text classification) - NLP - Diễn đàn Machine Learning cơ…

Hay
xem hay thật
phim này xem hay

Một số mẫu trong file negative.txt

phim nhảm
ghét xem phim này
coi tốn thời gian
bảo đảm nhảm nhí
không ra gì

2. Xử lý dữ liệu (tách từ, biểu diễn vector)

Mỗi câu bình luận trước tiên được tách từ thành các từ có ý nghĩa. Ví dụ câu “bảo đảm nhảm nhí” được tách thành

[“bảo_đảm”, “nhảm_nhí”]

def tokenize_sentences(self, sentences):


"""
Tokenize or word segment sentences
:param sentences: input sentences
:return: tokenized sentence
"""
tokens_list = []
for sent in sentences:
tokens = self.tokenizer.tokenize(sent)
tokens_list.append(tokens)
return tokens_list

Mỗi câu sẽ trở thành 1 mảng của các từ, mỗi dữ liệu đầu vào trước tiên được biến thành 1 mảng 2 chiều, chiều thứ
nhất tương ứng với số câu bình luận. Chiều thứ hai tương ứng với số từ trong một câu.

Nếu bạn chưa rõ về tách từ (tokenization, word segmentation) thì hãy xem bài Tách từ tiếng Việt Tiếp theo chúng ta
biến mỗi từ thành một vector, ví dụ từ “bảo_đảm” thành một vector 100 chiều:

[-0.46393627 0.16954394 0.83275014 -1.5028543 -0.01803644 1.2121786


0.5337349 1.0144993 0.14793205 -0.10679752 -0.4278082 1.3274498

0.71588534 0.37957552 0.55647874 -0.37985063 0.61336917 0.79634154
-1.1528205 -1.6517726 -0.29540744 -0.67167693]

Từ đồng nghĩa với từ này là từ “đảm_bảo”, với độ tương đồng khoảng 0.86123. Nếu bạn chưa hiểu rõ về cách sử
dụng word2vec hãy xem lại bài Thực hành biểu diễn từ bằng vector.

def word_embed_sentences(self, sentences, max_length=20):


"""
Helper method to convert word to vector
:param sentences: input sentences in list of strings format
:param max_length: max length of sentence you want to keep, pad more or cut off
:return: embedded sentences as a 3D-array
"""

https://forum.machinelearningcoban.com/t/vnlp-core-3-bai-toan-phan-loai-van-ban-phan-tich-cam-xuc-cua-binh-luan-text-classification/2371 2/9
8/26/2019 [VNLP Core] [3] Bài toán phân loại văn bản - Phân tích cảm xúc của bình luận (text classification) - NLP - Diễn đàn Machine Learning cơ…

embed_sentences = []
for sent in sentences:
embed_sent = []
for word in sent:
if (self.sym_dict is not None) and (word.lower() in self.sym_dict):
replace_word = self.sym_dict[word.lower()]
embed_sent.append(self.word2vec[replace_word])
elif word.lower() in self.word2vec:
embed_sent.append(self.word2vec[word.lower()])
else:
embed_sent.append(np.zeros(shape=(self.word_dim,), dtype=float))
if len(embed_sent) > max_length:
embed_sent = embed_sent[:max_length]
elif len(embed_sent) < max_length:
embed_sent = np.concatenate((embed_sent, np.zeros(shape=(max_length - len(embed_
self.word_dim), dtype=f
axis=0)
embed_sentences.append(embed_sent)
return embed_sentences

Như vậy mỗi từ sẽ biến thành 1 vector 100 chiều, mỗi câu sẽ thành 1 ma trận max_length x 100 với max_length = 20
là số từ tối đa trong 1 câu mà ta chọn. Nếu câu dài hơn ta sẽ cắt đi, nếu câu ngắn hơn ta sẽ thêm vào vector 0. Dữ liệu
features X gồm n câu (sentences) sẽ được biểu diễn thành 1 tensor 3 chiều n x max_length x d; với n = số mẫu (hay
số câu bình luận), max_length = chiều dài 1 câu (nhớ chọn là 1 số cố định), d = số chiều không gian vector biểu diễn 1
từ.

3. Tạo mô hình deep learning

Khi đã đưa được mỗi từ (word) thành một vector, mỗi câu thành một ma trận, dữ liệu đầu vào trở thành 1 tensor 3
chiều, thì chúng ta có thể sử dụng các mô hình deeplearning để classify.

Với dữ liệu ma trận chúng ta có thể nghĩ tới Convolution Neural Network nhưng với ma trận mà chiều của không gian
từ đã mang ý nghĩa của chính nó thì ta không cần quét bộ lọc (filter qua) mà chỉ cần quét đặc trưng theo chiều chuỗi
các từ nên người ta hay dùng Conv1D cho text classification.

Dữ liệu văn bản là dữ liệu ở dạng chuỗi nên chúng ta nghĩ tới phương án sử dụng mạng Recurrrent Neural Network (ví
dụ: Long Short-Term Memory). Để phân loại chuỗi của các từ ta thấy rằng cần xét cả câu và Bi-LSTM giúp tránh ảnh
hưởng bởi sự mất cân bằng giữa các từ cuối câu so với đầu câu.

Tóm lại, về mô hình deeplearning trong trường hợp này chúng ta có thể nghĩ ngay tới Conv1D, LSTM, Bi-LSTM để làm
ví dụ và thử nghiệm đầu tiên. Chi tiết về các mô hình các bạn có thể xem ở các bài khác trong diễn đàn, hoặc các
nguồn khác vì đây là các mô hình được sử dụng rất rộng rãi hiện nay.

Để đơn giản, chúng ta sử dụng thư viện Keras, bạn chỉ cần chọn các hyper-parameters như số layer, số neuron trên 1
layer, kỹ thuật Dropout, hay chọn thuật toán tối ưu…

Với Keras, chúng ta có thể dễ dàng lưu và load model để sử dụng lại nhiều lần.

def load_model(self):
"""
Load model from file
:return: None
"""
self.model = self.build_model((self.max_length, self.word_dim))
self.model.load_weights(self.model_path)

https://forum.machinelearningcoban.com/t/vnlp-core-3-bai-toan-phan-loai-van-ban-phan-tich-cam-xuc-cua-binh-luan-text-classification/2371 3/9
8/26/2019 [VNLP Core] [3] Bài toán phân loại văn bản - Phân tích cảm xúc của bình luận (text classification) - NLP - Diễn đàn Machine Learning cơ…

def build_model(self, input_dim):


"""
Build model structure
:param input_dim: input dimension max_length x word_dim
:return: Keras model
"""
model = Sequential()

model.add(LSTM(64, return_sequences=True, input_shape=input_dim))


model.add(Dropout(0.2))
model.add(LSTM(32))
model.add(Dense(self.n_class, activation="softmax"))

model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adadelta(),
metrics=['accuracy'])
return model

Xem thêm cách chuẩn bị dữ liệu, tạo mô hình tại

deepai-solutions/core_nlp/blob/master/text_classification/short_text_classifiers.py

import numpy as np
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, LSTM, Bidirectional

class BaseTextClassifier(object):
def train(self, X, y):
"""
Training using data X, y
:param X: input feature array
:param y: label array
:return:
"""
pass

def predict(self, X):


"""
Predict for input X
:param X: input feature array

This file has been truncated. show original

4. Training và test Bước training và predict khá đơn giản khi chúng ta đã đưa dữ liệu về dạng ma trận số hay
tensor, chỉ cần sử dụng hàm fit hay predict theo API của thư viện Keras. Chúng ta cũng dễ dàng lưu các tham số
đã tối ưu bằng hàm save_weights(path)

def train(self, X, y):


"""
Training with data X, y
https://forum.machinelearningcoban.com/t/vnlp-core-3-bai-toan-phan-loai-van-ban-phan-tich-cam-xuc-cua-binh-luan-text-classification/2371 4/9
8/26/2019 [VNLP Core] [3] Bài toán phân loại văn bản - Phân tích cảm xúc của bình luận (text classification) - NLP - Diễn đàn Machine Learning cơ…

:param X: 3D features array, number of samples x max length x word dimension


:param y: 2D labels array, number of samples x number of class
:return:
"""
self.model = self.build_model(input_dim=(X.shape[1], X.shape[2]))
self.model.fit(X, y, batch_size=self.batch_size, epochs=self.n_epochs)
self.model.save_weights(self.model_path)

def predict(self, X):


"""
Predict for 3D feature array
:param X: 3D feature array, converted from string to matrix
:return: label array y as 2D-array
"""
if self.model is None:
self.load_model()
y = self.model.predict(X)
return y

Lưu ý:

Bạn hãy crawl dữ liệu và test thử xem có cần bổ sung thêm dữ liệu training hay không?
Kiểm tra phần tách từ xem có cần training lại cho phù hợp với domain (ví dụ ở đây thì domain là bình luận phim)
hay không? Như phần xử lý viết tắt chẳng hạn.
Tương tự hãy kiểm tra word2vec xem có ổn không vì pre-trained model hiện tại là training cho dữ liệu khác. Đặc
biệt với những từ (word) quan trọng. Mình đã sử dụng 1 trick nhỏ trong source code mà chưa đề cập đó là từ
đồng nghĩa cho một số từ không có trong word2vec training sẵn hoặc mang ý nghĩa không đúng. Hãy xem kỹ
source code để hiểu trick này.
Bạn có thể thay mô hình deeplearning đơn giản nếu bạn sử dụng Keras, chỉ cần extend lại class
KerasTextClassifier và override lại hàm build_model(self, input_dim)

Có gì chưa rõ ràng mong các bạn comment bên dưới, mình sẽ sửa hoặc trả lời.

Chi tiết về các đoạn code và cách chạy thử nghiệm ví dụ phân tích cảm xúc / thái độ của bình luận được mô tả ở link
dưới đây:

Source code:

deepai-solutions/core_nlp/blob/master/demo.py

from tokenization.crf_tokenizer import CrfTokenizer


from word_embedding.word2vec_gensim import Word2Vec
from text_classification.short_text_classifiers import BiDirectionalLSTMClassifier, load_s

# Please give the correct paths


# Load word2vec model from file. If you want to train your own model, please go to README
word2vec_model = Word2Vec.load('models/pretrained_word2vec.bin')

# Load tokenizer model for word segmentation. If you want to train you own model,
# please go to README or check crf_tokenizer.py
tokenizer = CrfTokenizer(config_root_path='tokenization/',
model_path='models/pretrained_tokenizer.crfsuite')
sym_dict = load_synonym_dict('data/sentiment/synonym.txt')
keras_text_classifier = BiDirectionalLSTMClassifier(tokenizer=tokenizer, word2vec=word2vec

https://forum.machinelearningcoban.com/t/vnlp-core-3-bai-toan-phan-loai-van-ban-phan-tich-cam-xuc-cua-binh-luan-text-classification/2371 5/9
8/26/2019 [VNLP Core] [3] Bài toán phân loại văn bản - Phân tích cảm xúc của bình luận (text classification) - NLP - Diễn đàn Machine Learning cơ…

model_path='models/sentiment_model.h5'
max_length=10, n_epochs=10,
sym_dict=sym_dict)
# Load and prepare data
X, y = keras_text_classifier.load_data(['data/sentiment/samples/positive.txt',
'data/sentiment/samples/negative.txt'],

This file has been truncated. show original

Tìm giải pháp cho bài toán sentiments classification


[Hỏi] Xây dựng tập dữ liệu training cho n-gram language model phục vụ bài toán tách từ

Naebolo Th09 '18

Cám ơn bài viết hay của bạn. Khi mình chạy thử đoạn này thì bị lỗi ở phần

tokenizer = CrfTokenizer(config_root_path=’…/tokenization/’,
model_path=’…/models/pretrained_tokenizer.crfsuite’)

Lỗi ở hàm:

self.bi_grams = load_n_grams(config_root_path + bi_grams_path)

Mã lỗi

UnicodeDecodeError: ‘charmap’ codec can’t decode byte 0x81 in position 252: character maps to

pencil.forever Th09 '18

Naebolo:

Bạn xem file demo.py nhé! Mình sử dụng python 3. Bạn xem thêm file requirements.txt nhé.
https://github.com/deepai-solutions/core_nlp/blob/master/requirements.txt

pencil.forever Th09 '18

Mình đã search lỗi này, có thể do OS của bạn không mặc định đọc utf8. Bạn có thể thử chỗ open file, thêm vào
encoding=“utf8”:

with open(file_path, encoding="utf8") as fr:

Mình đã sửa trong nhánh master trên github, bạn có thể pull về chạy thử lại. Nếu lỗi tương tự bạn viết issue trên github
hoặc phản hồi lại đây nhé (mình sẽ sửa những chỗ bị lỗi)

https://forum.machinelearningcoban.com/t/vnlp-core-3-bai-toan-phan-loai-van-ban-phan-tich-cam-xuc-cua-binh-luan-text-classification/2371 6/9
8/26/2019 [VNLP Core] [3] Bài toán phân loại văn bản - Phân tích cảm xúc của bình luận (text classification) - NLP - Diễn đàn Machine Learning cơ…

manhdoi123 Th10 '18

cảm ơn bài viết của anh. Em chạy thử code demo.py thì bị lỗi raise KeyError("word '%s' not in vocabulary" %
word)

KeyError: "word 'xuất_sắc' not in vocabulary"

ở trong file

gensim\models\keyedvectors.py line 274 in word_vec

pencil.forever Th10 '18

manhdoi123:

xuất_sắc

Có lẽ dữ liệu của bạn có lỗi mã hoá tiếng việt ở từ “xuất_sắc”. Còn thông báo lỗi thì cho thấy từ “xuất_sắc”
không tồn tại trong bộ từ vựng của model word_vec. Nếu bạn ko fix được lỗi có thể copy cả đoạn lỗi bắn ra, xem ở file
nào trong project của mình. Còn nếu chỉ thông tin lỗi như này thì mình chỉ kết luận được như vậy. Cảm ơn bạn đã
phản hồi.

andrew Th11 '18

pencil.forever:

Mỗi câu sẽ trở thành 1 mảng của các từ, mỗi dữ liệu đầu vào trước tiên được biến thành 1 mảng 2 chiều, chiều
thứ nhất tương ứng với số câu bình luận. Chiều thứ hai tương ứng với số từ trong một câu.

E chưa rõ đoạn này lắm ạ. E đang hiểu nó như sau: Input là “Tôi thích bộ phim này lắm. Nhân vật chính rất tuyệt” Như
vậy nó sẽ thành 2 chiều, mỗi chiều là 1 câu, sau đó mỗi câu lại có các từ phải k ạ? [[Tôi, thích, bộ_phim này],
[Nhân_vật_chính, tuyệt]]. Nếu vậy có cách nào để phân biệt các câu ạ? EM cảm ơn a

pencil.forever Th11 '18

Bạn có thể coi 2 câu là 1 text đầu vào (dấu chấm coi như 1 từ) thì có thể cho model học luôn. Hoặc sử dụng thuật toán
khác để tách 1 đoạn dài thành nhiều câu đơn, sau đó cho input từng câu rồi dùng voting (hoặc attention) để đưa ra
output

Xin hướng dẫn học về NLP

Hua_Dan Th11 '18

Mình đang mắc chỗ cài đặt thuật toán phân loại theo từ điển. ban có gợi ý nào giúp mình được không ạ? Xin chân
thành cảm ơn bạn.

Thanh_Ho_Quang Th11 '18

https://forum.machinelearningcoban.com/t/vnlp-core-3-bai-toan-phan-loai-van-ban-phan-tich-cam-xuc-cua-binh-luan-text-classification/2371 7/9
8/26/2019 [VNLP Core] [3] Bài toán phân loại văn bản - Phân tích cảm xúc của bình luận (text classification) - NLP - Diễn đàn Machine Learning cơ…

Bạn có thể nói rõ về vấn đề bạn gặp, mình đang làm đề tài liên quan và có tham khảo bài này. Nếu có gì giải đáp được
mình sẽ giúp

hoho303 Th02 6

Các bác cho em hỏi làm sao để phân loại các bình luận không liên quan đến phim, ví dụ như bình luận “chào mọi
người” chẳng hạn nó sẽ phân ra class irrelevant ạ

nguyenvanhieu.vn Th02 11

Bạn có thể tạo thêm 1 nhãn riêng “irrelevant” như vậy. Hoặc build một model sàng lọc trước khi cho vào model chính.

hoho303 Th02 11

Em có một vấn đề là nếu nhãn của em càng nhiều thì độ chính xác sẽ càng giảm đi ạ ?

Cách tạo Word2Vec cho competition

pencil.forever Th02 21

Bạn nêu chi tiết hơn về chỗ đang vướng được không ạ?

pencil.forever Th02 21

Như vậy dữ liệu của bạn bị nhiễu (noise) hay bị mất cân bằng (imbalance) chăng? Nếu nhiễu thì bạn có thể dùng re-
filtering (dùng model để lọc lại các mẫu bị sai có confidence thấp). Nếu mất cân bằng thì bạn có thể dùng các phương
pháp để sampling dữ liệu.

hoho303 Th02 21

Dạ em định xây 1 cái dataset cho chatbot ấy ạ. Chia text ra thành từng nhãn để có response tương ứng

pencil.forever Th02 22

Vậy thì bạn tham khảo một số mô hình của các chatbot framework nổi tiếng hiện nay. Nhưng trước hết mình nghĩ bạn
nên đi từng bước một.

1. Xây dựng bộ dữ liệu phân loại intent (ý định của người hỏi, ví dụ: intent mua hàng, intent hỏi giá…)
2. Trích xuất các entity (các thuộc tính, ví dụ: số lượng hàng, mã mặt hàng…)
3. Đưa ra các action tương ứng với intent, entity (cái này có thể dùng rule tạo thành cây quyết định). Ví dụ: intent
hỏi giá => trả lời giá Chatbot không phải là bài toán đơn giản nên mình mô hàng sơ lược như vậy để dễ hình
dung bước đầu tiếp cận.

Tran_Loc Th04 2

https://forum.machinelearningcoban.com/t/vnlp-core-3-bai-toan-phan-loai-van-ban-phan-tich-cam-xuc-cua-binh-luan-text-classification/2371 8/9
8/26/2019 [VNLP Core] [3] Bài toán phân loại văn bản - Phân tích cảm xúc của bình luận (text classification) - NLP - Diễn đàn Machine Learning cơ…

A cho em hỏi có em muốn phân loại bình luận dưa trên các khía cạnh nhằm mục đích thống kê. Ví dụ điện thoại
Iphone chẳng hạn có bình luận như sau: Pin nhanh hết, nhưng màn hình mượt. Vậy mình sẽ có 2 khía cạnh là Pin và
màn hình. 1 cái negative 1 cái là positive. E muốn phân loại và thống kê những cái nào là positive cái nào là negative.
A có hướng giải quyết nào ko giúp e với. E cảm ơn a

So_So Th06 28

mình cũng đang bị lỗi giống bạn không biết bạn đã sửa được lỗi đó chưa?

dot97 Th07 1

mình nghĩ phân tách thành các câu rồi phân loại từng câu. Sau hợp chúng lại nếu cùng nhãn. ko thì để phân tách vậy

https://forum.machinelearningcoban.com/t/vnlp-core-3-bai-toan-phan-loai-van-ban-phan-tich-cam-xuc-cua-binh-luan-text-classification/2371 9/9

You might also like