Trích chọn thuộc tính trong đoạn văn bản với TF-IDF
1. Giới thiệu sơ lược về Vector Space Model (VSM) VSM là một mô hình đại số tuyến tính biểu diễn dạng văn bản thành dạng một vector, các phần tử trong vector có thể biểu diễn mức độ quan trọng của một từ (TF-IDF) hoặc dạng có mặt hoặc vắng mặt của một từ (Bag of Words) trong đoạn văn bản. Tập hợp ...
1. Giới thiệu sơ lược về Vector Space Model (VSM)
VSM là một mô hình đại số tuyến tính biểu diễn dạng văn bản thành dạng một vector, các phần tử trong vector có thể biểu diễn mức độ quan trọng của một từ (TF-IDF) hoặc dạng có mặt hoặc vắng mặt của một từ (Bag of Words) trong đoạn văn bản. Tập hợp các đoạn văn bản được biểu diễn thành dạng vector được gọi là không gian vector, và nó đại diện cho các thuộc tính đã được trích chọn từ đoạn văn bản
2. Tổng quát về TF-IDF
Trong khai phá dữ liệu văn bản (text mining), thuật ngữ TF-IDF (term frequency - inverse document frequency) là một phương thức thống kê được biết đến rộng rãi nhất để xác định độ quan trọng của một từ trong đoạn văn bản trong một tập nhiều đoạn văn bản khác nhau. Nó thường được sử dụng như một trọng số trong việc khai phá dữ liệu văn bản. TF-IDF chuyển đổi dạng biểu diễn văn bản thành dạng không gian vector (VSM), hoặc thành những vector thưa thớt.
-
TF (Term Frequency): là tần suất xuất hiện của một từ trong một đoạn văn bản. Với những đoạn văn bản có độ dài khác nhau, sẽ có những từ xuất hiện nhiều ở những đoạn văn bản dài thay vì những đoạn văn bản ngắn. Vì thế, tần suất này thường được chia cho độ dài của đoạn văn bản như một phương thức chuẩn hóa (normalization). TF được tính bởi công thức: tf(t)=f(t,d)Ttf(t) = frac{f(t,d)}{T}tf(t)=Tf(t,d) (với ttt là một từ trong đoạn văn bản; f(t,d)f(t,d)f(t,d) là tần suất xuất hiện của ttt trong đoạn văn bản ddd; TTT là tổng số từ trong đoạn văn bản đó).
-
IDF (Inverse Document Frequency): tính toán độ quan trọng của một từ. Khi tính toán TF, mỗi từ đều quan trọng như nhau, nhưng có một số từ trong tiếng Anh như "is", "of", "that",... xuất hiện khá nhiều nhưng lại rất ít quan trọng. Vì vậy, chúng ta cần một phương thức bù trừ những từ xuất hiện nhiều lần và tăng độ quan trọng của những từ ít xuất hiện những có ý nghĩa đặc biệt cho một số đoạn văn bản hơn bằng cách tính IDF: idf(t)=logN∣t∈D:t∈d∣idf(t)= log{frac{N}{|{t in D : t in d}|}}idf(t)=log∣t∈D:t∈d∣N (trong đó NNN là tổng số đoạn văn bản; tập |{t in D : t in d}| là số văn bản chứa từ ttt).
-
TF-IDF được tính bởi: tf_idf(t)=tf(t)×idf(t)tf\_idf(t) = tf(t) imes idf(t)tf_idf(t)=tf(t)×idf(t)
3. Ví dụ về sử dụng TF-IDF
Trong ví dụ này, chúng ta sẽ thực hiện tính toán TF-IDF trên dữ liệu là kịch bản (lời thoại) trong một series phim nổi tiếng của Mỹ - "How I met your mother?". Tập dữ liệu có thể tải về tại đây.
Việc tính toán TF-IDF được thực hiện thông qua thư viện scikit-learn trên Python.
Dữ liệu là một file csv và được thể hiện như ở hình dưới (dòng đầu tiên là dòng chứa header)
SentenceId,EpisodeId,Season,Episode,Sentence 1,1,1,1,Pilot 2,1,1,1,Scene One 3,1,1,1,[Title: The Year 2030] 4,1,1,1,"Narrator: Kids, I'm going to tell you an incredible story. The story of how I met your mother" 5,1,1,1,Son: Are we being punished for something? 6,1,1,1,Narrator: No
Đầu tiên, chúng thực hiện tiền xử lý dữ liệu, đọc file và chuyển nó về dạng một list chứa các đoạn văn bản
from collections import defaultdict import csv episodes = defaultdict(list) with open("data/import/sentences.csv", "r") as sentences_file: reader = csv.reader(sentences_file, delimiter=',') reader.next() for row in reader: episodes[row[1]].append(row[4]) for episode_id, text in episodes.iteritems(): episodes[episode_id] = "".join(text) corpus = [] for id, episode in sorted(episodes.iteritems(), key=lambda t: int(t[0])): corpus.append(episode)
Biến corpus lúc này chứa 208 bản ghi (1 bản ghi mỗi tập) chứa toàn bộ câu thoại của tập đó. Tiếp theo chúng ta sẽ mô hình hóa tập dữ liệu này về dạng biểu diễn TF-IDF với đoạn code sau:
from sklearn.feature_extraction.text import TfidfVectorizer tf = TfidfVectorizer(analyzer='word', ngram_range=(1,3), min_df = 0, stop_words = 'english')
Với tham số ngram_range, chúng ta sẽ tạo ra được những cụm từ chứa 2 đến 3 từ cùng với những từ đơn có trong tập dữ liệu. Ví dụ với câu "Python is cool" sẽ sinh ra được các từ và cụm từ "Python", "is", "cool", "Python is", "Python is cool" , "is cool".
Sinh mô hình TF-IDF từ tập trên với đoạn code sau:
tfidf_matrix = tf.fit_transform(corpus) feature_names = tf.get_feature_names() >>> len(feature_names) 498254 >>> feature_names[50:70] [u'00 does sound', u'00 don', u'00 don buy', u'00 dressed', u'00 dressed blond', u'00 drunkenly', u'00 drunkenly slurred', u'00 fair', u'00 fair tonight', u'00 fall', u'00 fall foliage', u'00 far', u'00 far impossible', u'00 fart', u'00 fart sure', u'00 friends', u'00 friends singing', u'00 getting', u'00 getting guys', u'00 god']
Từ đó, chúng ta có gần 500.000 cụm từ, và vì thế ma trận TF-IDF của chúng ta sẽ là ma trận 208×498254 208 imes498254208×498254 - mỗi một hàng biểu diễn một tập phim, mỗi một cột biểu diễn một cụm từ:
>>> tfidf_matrix <208x498254 sparse matrix of type '<type 'numpy.float64'>' with 740396 stored elements in Compressed Sparse Row format>
Lấy ra tập các từ và TF-IDF của nó trong tập một của bộ phim:
dense = tfidf_matrix.todense() episode = dense[0].tolist()[0] phrase_scores = [pair for pair in zip(range(0, len(episode)), episode) if pair[1] > 0] >>> len(phrase_scores) 4823
Chúng ta lọc ra những từ mà không xuất hiện trong tập một của bộ phim, kết quả là chỉ còn gần 5000 từ trên toàn bộ tập từ sinh ra được từ kịch bản của bộ phim. Cũng có thể thấy ở đây là dạng biểu diễn dense matrix không hiệu quả bằng sparse matrix khi mà sẽ có quá nhiều giá trị bằng 0 trong ma trận.
Tiếp theo, chúng ta sắp xếp theo thứ tự giảm dần của TF-IDF
>>> sorted(phrase_scores, key=lambda t: t[1] * -1)[:5] [(419207, 0.2625177493269755), (312591, 0.19571419072701732), (267538, 0.15551468983363487), (490429, 0.15227880637176266), (356632, 0.1304175242341549)]
Giá trị đầu tiên của mỗi tuple chính là index của cụm từ trong biến feature_names cho phép chúng ta lấy lại dạng văn bản của cụm từ.
>>> feature_names[419207] u'ted' >>> feature_names[312591] u'olives' >>> feature_names[356632] u'robin'
Cùng xem kết quả của việc tính toán:
sorted_phrase_scores = sorted(phrase_scores, key=lambda t: t[1] * -1) for phrase, score in [(feature_names[word_id], score) for (word_id, score) in sorted_phrase_scores][:20]: print('{0: <20} {1}'.format(phrase, score)) ted 0.262517749327 olives 0.195714190727 marshall 0.155514689834 yasmine 0.152278806372 robin 0.130417524234 barney 0.124411751867 lily 0.122924977859 signal 0.103793246466 goanna 0.0981379875009 scene 0.0953423604123 cut 0.0917336653574 narrator 0.0864622981985 flashback 0.078295921554 flashback date 0.0702825260177 ranjit 0.0693927691559 flashback date robin 0.0585687716814 ted yasmine 0.0585687716814 carl 0.0582101172888 eye patch 0.0543650529797 lebanese 0.0543650529797
Chúng ta có thể thấy, phần lớn tên nhân vật xuất hiện ở đầu, đây là những giá trị không hữu ích bởi vì chúng không mang lại ý nghĩa của đoạn văn bản (trong text mining nói chung, vấn đề này được xử lý bằng các phương pháp stopword filtering, NER, POS tagging). Nhưng với từ "olives" chính là từ quan trọng có liên quan đến giả thuyết quả olive mà nhân vật chính đã đề cập đến ở tập đầu mà không đề cập đến ở những tập sau của bộ phim (như trong câu lệnh dưới), tuy là tên nhân vật nhưng "yasmine" cũng chỉ xuất hiện ở những tập đầu mà không còn được nhắc đến ở những tập sau nữa. Như vậy, những từ như "olives" hoặc "yasmine" sẽ là quan trọng trong những đoạn văn bản mà nó được đề cập đến và ít quan trọng so với những đoạn văn bản khác.
$ grep -rni --color "olives" data.csv 173:172,1,1,1,Robin: Do you want these? (Holding up remaining olives from her plate) I hate olives. 175:174,1,1,1,Marshall: She hates olives! Awesome! 178:177,1,1,1,"Ted: The olive theory is based on my friends, Marshall and Lily. He hates olives, she loves them. In a weird way that's what makes them such a great couple. A Perfect balance (eats olive)." 179:178,1,1,1,"Robin: You know, I've had a jar of olives just sitting in my fridge forever." 277:276,1,1,1,Ted: I was just hoping to get those olives... that you said I could have. 278:277,1,1,1,Robin: Would you like those olives with some Gin and Vermouth? 285:284,1,1,1,"Barney: You hate olives? Lily loves them, you can't stand them." 286:285,1,1,1,"Marshall: Yeah, hate olives." 287:286,1,1,1,"Barney: Two weeks ago, Spanish bar on 79th Street, dish of olives-you had some. What up?" 291:290,1,1,1,"Marshall: On our first date, I ordered a Greek salad; Lily asked if she could have my olives. I said, ""Sure... I hate olives.""" 292:291,1,1,1,Barney: But you like olives! 293:292,1,1,1,"Marshall: Well, I was eighteen, okay? I was a virgin. Been waiting for my whole life for a pretty girl to want my olives." 309:308,1,1,1,"Barney: Come on man, you said your stomach's been hurting, right? You know what that is! Hunger. You're hungry for experience. Hungry for something new. Hungry for olives. But you're too scared to do anything about it." 310:309,1,1,1,"Marshall: Yeah, I'm scared, okay? But when I think about spending the rest of my life with Lily... committing forever, no other women (Lily appears behind Marshall in the open window) doesn't scare me at all. I'm marrying that girl. (Lily pops her head in from the window. Marshall turns around) Lily. Lily, I like olives." 318:317,1,1,1,Robin: Hold on. (Gets up) Wait a minute. (Hands him Olives) Promised you these. 319:318,1,1,1,Ted: Olives. Thanks. I love you. What's wrong with me?
4. Lời kết
Như vậy, qua bài viết chúng ta cũng có thể hiểu được việc mô hình hóa một đoạn văn bản sang dạng không gian vector VSM có thể thực hiện bằng cách tính toán TF-IDF. Đây chỉ là một trong những cách biểu diễn ngữ nghĩa mức thấp của văn bản, thường dùng cho việc trích chọn dữ liệu để có thể mô hình hóa văn bản ở những bài toán mức cao hơn như POS tagging, NER,...
Tham khảo
TF-IDF Machine Learning :: Text feature extraction (tf-idf) Sklearn TfidfVectorizer Sklearn TfidfTransformer