[VNLP Core] [1] Bài toán tách từ tiếng Việt - Tokenization, Word Segmentation

nlp-tiengviet
word-segmentation
tokenization

#1

Bài toán tách từ là bài toán quan trọng đối với tiếng Việt. Khác với tiếng Anh, một từ tiếng Việt có thể được tạo bởi nhiều hơn một âm. Ví dụ từ (word) “cá_nhân” được tạo lên bởi 2 âm (syllable) là “cá” và “nhân”. Trong khi hai từ đơn “cá” và từ đơn “nhân” lại có thể mang ý nghĩa khác. Do vậy, tách từ tiếng Việt là bước quan trọng chúng ta cần thực hiện trước khi đưa dữ liệu vào các bước tiếp theo, ví dụ như word embedding.

Trong bài này mình xin giới thiệu 2 thuật toán chúng ta có thể sử dụng để giải quyết bài toán này.

  1. Sử dụng bộ từ điển. Ví dụ: Thuật toán so khớp từ dài nhất (longest matching) Thuật toán này khá đơn giản, đối với 1 đoạn text đầu vào “Thuế thu nhập cá nhân” thì chúng ta thực hiện như sau (giải thuật đơn giản hoá): current_syllable_id = 0 while current_syllable_id and not done { check if “word word+1 word+2” is in tri-gram-dictionary => {take word_word1_word2; current_syllable_id += 3} else if “word word+1” is in bi-gram-dictionary => {take word_word1; current_syllable_id += 2} else => {take word only; current_syllable_id += 1} } Bắt đầu từ trái sang phải, với vị trí từ hiện tại chúng ta kiểm tra xem từ đó và 2 từ tiếp theo có thể ghép thành 1 từ có nghĩa hay không bằng cách kiểm tra trong từ điển tri-gram. Nếu không thể tạo ra được từ có nghĩa từ 3 từ thì ta tiếp tục kiểm tra xem từ hiện tại và từ tiếp theo có thể ghép được thành một từ có nghĩa hay không bằng cách kiểm tra trong từ điển bi-gram. Cuối cùng nếu không thể ghép được thì ta coi đó là từ đơn. Chỉ số current_syllable_id sẽ dịch 1, 2, hay 3 đơn vị tuỳ theo số từ ta ghép được. Xem thêm tại: https://github.com/deepai-solutions/core_nlp/blob/master/tokenization/dict_models.py

Ngoài thuật toán so khớp từ dài nhất còn có thuật toán so khớp từ cực đại. Idea và thuật toán so khớp cực đại khá tương tự nhưng thay vì xét từng từ thì ta xét cả câu để tránh bị sai như trong câu: “Học sinh học sinh vật học” sẽ thành “Học_sinh học_sinh vật học” (theo Longest Matching).

  1. Sử dụng học máy. Ví dụ: Thuật toán Conditional Random Field (CRF) Phương pháp chung là chúng ta đưa bài toán về dạng classification và sử dụng các thuật toán classification khác nhau để học. Thuật toán CRF sử dụng xác suất có điều kiện và thống kê để mô hình hoá đầu vào là các features và đầu ra là class id. Thuật toán này khá phù hợp với các bài toán classification trong nlp như tokenization (word segmentation), POS tagging, NER. Chi tiết sâu hơn về CRF xin được giới thiệu ở một bài khác. Bài này mình muốn tập chung vào cách tạo dữ liệu, training và test mô hình.

HTML format: Pháp_lệnh thuế_thu_nhập đối_với người có thu_nhập cao ra_đời và được áp_dụng trong bối_cảnh đầu_tư trực_tiếp nước_ngoài ( FDI ) vào VN đã hình_thành một nhóm người có thu_nhập cao hơn mức bình_thường của người dân trong nước và sắc_thuế này chính là để khắc_phục sự bất_hợp_lý đó . CLEANT format: Pháp_lệnh thuế_thu_nhập đối_với người có thu_nhập cao ra_đời và được áp_dụng trong bối_cảnh đầu_tư trực_tiếp nước_ngoài ( FDI ) vào VN đã hình_thành một nhóm người có thu_nhập cao hơn mức bình_thường của người dân trong nước và sắc_thuế này chính là để khắc_phục sự bất_hợp_lý đó .

  • Dữ liệu chúng ta cần chuẩn bị ở dạng sau:
X = [[{'bias': 1.0, 'lower': 'hello'}, {'bias': 1.0, 'lower': 'world'}],
     [{'bias': 1.0, 'lower': 'world'}, {'bias': 1.0, 'lower': 'hello'}]]
y = [['B', 'I'], ['B', 'I']]

X là dữ liệu features, chúng ta chuẩn bị ở dạng dictionary. Mỗi âm (syllable) được tính và tạo ra một dữ liệu đặc trưng dạng json. Ví dụ: với câu “Hello World” sẽ có 2 syllables là “Hello” và “World”. Syllable là “Hello” sẽ tạo ra 1 dict là {‘bias’: 1.0, ‘lower’: ‘hello’}. Một số các feature chúng ta có thể tính là: ‘bias’, ‘lower’, ‘isupper’, ‘istitle’, ‘isdigit’. Lưu ý: feature của một từ còn được tính cho các từ phía trước phía sau. Ví dụ: ‘+1:lower’: ‘world’ là 1 feature của “Hello”. Tương ứng với mỗi syllable (ví dụ “Hello”) là một nhãn, chẳng hạn ‘B’ hay ‘I’ (bạn có thể thay là ‘0’ hoặc ‘1’)

        trainer = pycrfsuite.Trainer(verbose=False)

        for xseq, yseq in zip(X, y):
            trainer.append(xseq, yseq)

        trainer.set_params({
            'c1': 1.0,
            'c2': 1e-3,
            'max_iterations': 60,
            'feature.possible_transitions': True
        })

        trainer.train(self.model_path)

Khi đã có model, chúng ta có thể sử dụng lại bằng cách load model từ file:

        print("Loading model from file {}".format(self.model_path))
        self.tagger = pycrfsuite.Tagger()
        self.tagger.open(self.model_path)
        prediction = self.tagger.tag(test_features)

Để hiểu hơn về cách sử dụng crf cho bài toán tokenization, hãy tham khảo tại:

Mở rộng:

  • Bạn có thể sử dụng pre-trained model cho bài toán tách từ
  • Bạn có thể download dữ liệu hoặc tạo dữ liệu để training lại model tốt hơn
  • Bạn có thể sử dụng code cho bài toán tách từ để áp dụng cho bài toán POS-tagging, NER hoặc bài toán trích xuất đặc điểm của đối tượng. Ví dụ: “Tôi muốn mua iPhone 6 màu hồng” có thể cung cấp thông tin về tên sản phẩm là “iPhone 6”, màu sắc là “hồng”.

Định hướng: Cùng học và chia sẻ kiến thức cũng như source code để xây dựng cộng đồng xử lý ngôn ngữ tiếng Việt lớn mạnh hơn. Tham khảo thêm tại: https://github.com/deepai-solutions/core_nlp Nếu bạn có bất cứ chỗ nào không rõ xin vui lòng để lại comment, mình sẽ giải thích hoặc viết thêm vào bài này.


[VNLP Core] [2] Thực hành training và sử dụng biểu diễn từ trong không gian - word embedding
[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)
[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ừ
Cách xử lý các thuộc tính dạng chữ
Cách tạo Word2Vec cho competition
Tách các từ trong một đoạn âm thanh
#2

Thanks bạn, Ngoài 2 cách bạn đề cập ở trên để thành lập các cụm từ, từ trong corpus thì mình xin phép được chia sẻ 1 phương pháp tiếp cận khác là dựa vào tập dữ liệu. Đây là phương pháp của nhóm tác giả Mikolov sử dụng để pre training các cụm từ sử dụng trong word2vec (Các bạn có thể đọc thêm trong bài “Distributed Representations of Words and Phrases and their Compositionality” ). Về phương pháp có thể mô tả: Các cụm từ 2 từ (ví dụ cá_nhân) sẽ được tính dựa trên tỉ lệ giữa số lần chúng xuất hiện chung (cá_nhân) với tích các từ riêng biệt đi chung với nhau (từ cá và từ nhân), tương tự tính cho cụm gồm 3 từ Hồng Lâu Mộng (Hồng_Lâu vs Mộng) hay 4 từ. (hình bên dưới). Tỉ lệ này sẽ được so sánh với 1 ngưỡng. Giá trị ngưỡng giảm dần đối với các cụm từ với số từ tăng dần (cụm 2, 3, 4 từ) image

Ví dụ tác giả đề xuất ngưỡng là 200 cho cụm 3 từ, và 100 cho cụm 2 từ. “Theta” là hệ số được thiết lập để tránh việc có nhiều cụm từ được tạo thành từ các từ riêng lẻ rất hiếm khi xảy ra. Với tác giả thì họ sử dụng theta bằng 5. Đây là cách tiếp cận phụ thuộc vào tập dữ liệu. Vì thế muốn chính xác thì phải tinh chỉnh lại các hệ số để phù hợp với tập dữ liệu của cá nhân. Về implement thì họ thực hiện trên ngôn ngữ C. Đây là phần source word2vec C được 1 “thánh” comment giải thích rõ ràng (https://github.com/chrisjmccormick/word2vec_commented)

Mình có “chuyển” qua code python trong git (chưa biết chèn code vào bài viết nên mọi người chịu khó click vào git): https://github.com/vanleantking/glove/blob/master/corpus/read_data_tf.py

Corpus mình xây dựng thì hiện tai là một tập gồm list các list (ví dụ [[hom, nay, troi, mua, to lam], [khong, muon, lam, gi…]…]) p/s: Đây là code lúc mình “nhập môn” python, nên nếu có sai sót gì mong mọi người chỉ giáo. p/s: Hỏi ngu xíu là làm cách nào để chèn code vào nhỉ ;(


#3

Hay quá anh, cách này nhìn đơn giản mà có điều chắc chọn ngưỡng cực lắm, với em nghĩ corpus cũng phải lớn :sweat_smile:

Mà em thắc mắc xíu, do \text{count}(w_iw_j) \le \text{count}(w_i) \times \text{count}(w_j) nên score sẽ nhỏ hơn bằng 1 sao mình so với ngưỡng 200, 100 được anh? Với đoạn nào trong paper để ngưỡng đó vậy ạ do em mở paper lên xem thì không thấy? Em cảm ơn ạ.

P/s anh có thể chép code vào, rồi nhấn biểu tượng </> trên toolbar hay bao đoạn code của anh bằng:

    ```python
    # Code
    ```

#4

Thanks bạn :smile:, Trong bài báo không có nhắc đến, nhưng trong lúc hiện thực, họ sẽ lấy score * corpus_size nữa nhé (bạn có thể xem trong link git gốc ở trên). Đúng là chọn ngưỡng hơi cực.


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

Chèn code thì bạn dùng theo format của markdown nhé!

```python code block here ```

Bắt đầu bằng dấy ```python và kết thúc bằng 3 dấu ```

Tham khảo thêm: https://help.github.com/articles/creating-and-highlighting-code-blocks/


#6

Anh @pencil.forever có thể cho em hỏi, trong thư mục git core_nlp anh có 2 file tri_grams.txtbi_grams.txt. Em muốn hỏi nếu trong dự án của nhóm em sử dụng lại nội dung 2 file này thì có được không ạ? Với nếu trích dẫn, nhóm em nên trích dẫn nội dung của anh như thế nào ạ?

Chi tiết dự án của nhóm em: Nhóm em đang làm luận văn cử nhân về chủ đề: hỗ trợ người dùng nhận biết tin tức giả bằng tiếng Việt.

Nhóm em xin cảm ơn anh rất nhiều ạ!!!


#7

Bất cứ file nào của mình đặt trên github đều cho free sử dụng. Bạn có thể đặt trích dẫn là github chung chung là được. Ngoài ra các bạn có thể tham khảo ở nguồn khác để có bộ từ chuẩn hơn: http://www.informatik.uni-leipzig.de/~duc/Dict/


#8

Em cảm ơn anh @pencil.forever rất nhiều ạ


#9

Cho hỏi, khi chạy nó báo lỗi ModuleNotFoundError: No module named ‘tokenization’. Vậy tokenization mình phải cài, nhưng tìm trên mạng kg thấy, chỉ thấy ntlk.tokenization. Cho hỏi tìm module đó ở đâu. CÁM ƠN NHIỀU


#10

Cái tokenization là thư mục trong core-nlp đó anh


#11

Cho hỏi ngu thêm một phát. Vậy mình phải chép hết tất cả các file trong thư mục tokenizationphải không?


#12

Nếu anh @huuhanh thử nghiệm thì nên lấy hết git của anh pencil về.

Còn nếu anh đang làm dự án thì trong thư mục tokenization có một vài file anh có thể tái sử dụng, thì anh lấy riêng về, trong phần import anh sẽ viết lại, ví dụ như:

from tokenization.utils import xyz

đổi thành

from <thư_mục_mới>.utils import xyz


#13

cho e hỏi chút! a đã viết về bài CRF chưa ạ?


#14

Anh ấy hiện tại đang tập trung làm cái này:

“Chào các bạn, Hiện tại nhóm chúng tôi bao gồm các bạn KSTN-K52-BKHN và những thành viên tâm huyết của diễn đàn MLCB đang tập trung xây dựng một nền tảng giúp tổ chức các cuộc thi machine learning cho sinh viên và kỹ sư Việt Nam…”

Xong cái nền tảng thì sẽ viết tiếp em à.


#15

Cảm ơn bạn.

Chỉ riêng vụ share bộ dataset của VLSP là đã quý lắm rồi. Bộ đó dc soạn sạch đẹp ghê luôn!