Trong kỷ nguyên dữ liệu lớn, khả năng trích xuất thông tin có giá trị từ dữ liệu văn bản phi cấu trúc là một kỹ năng vô cùng quan trọng đối với các nhà khoa học dữ liệu. Dù là phân tích phản hồi của khách hàng, nghiên cứu tin tức hay khám phá các chủ đề trong tài liệu khoa học, phân tích văn bản cung cấp cái nhìn sâu sắc giúp định hình các quyết định kinh doanh và nghiên cứu. Bài viết này sẽ giới thiệu bạn đến với `quanteda`, một gói phần mềm mạnh mẽ và hiệu quả trong R, được thiết kế đặc biệt cho việc phân tích văn bản. Đây là phần đầu tiên trong chuỗi bài viết, tập trung vào các khái niệm cơ bản và các bước tiền xử lý chính.
Các Gói Phần Mềm Cần Thiết
1library(quanteda)
2library(quanteda.textstats)
3library(quanteda.textplots)
4library(readr)
5library(dplyr)
6library(ggplot2)
7library(stringr)
8library(DT)
9library(tidytext)Nắm Vững Kiến Thức Cơ Bản Về Phân Tích Văn Bản
Phân tích văn bản là quá trình biến đổi dữ liệu văn bản thành dữ liệu có cấu trúc phù hợp để phân tích. Một quy trình làm việc điển hình bao gồm các bước sau:
* **Thu thập và tải văn bản**: Nhập dữ liệu văn bản từ nhiều nguồn khác nhau.
* **Tiền xử lý**: Làm sạch và chuẩn hóa văn bản.
* **Token hóa**: Chia văn bản thành các đơn vị có ý nghĩa (từ, câu, N-grams).
* **Tạo ma trận tài liệu-đặc trưng (DFM)**: Biểu diễn văn bản dưới dạng số.
* **Phân tích**: Trích xuất thông tin chi tiết thông qua các phương pháp thống kê và tính toán.
Tạo Corpus: Chuẩn Bị Dữ Liệu Để Phân Tích
Corpus là một tập hợp văn bản có cấu trúc. Gói `quanteda` cung cấp hàm `corpus()` để tạo đối tượng corpus từ nhiều nguồn dữ liệu khác nhau.
Ví Dụ 1: Corpus Đơn Giản Từ Vector Ký Tự
1# Tạo một corpus đơn giản từ vector ký tự
2texts <- c(
3 "The quick brown fox jumps over the lazy dog.",
4 "Natural language processing is fascinating and powerful.",
5 "Text analytics enables data-driven decision making.",
6 "Machine learning algorithms can analyze text at scale.",
7 "Data science combines statistics, programming, and domain knowledge."
8)
9# Tạo corpus
10corp <- corpus(texts)
11# Kiểm tra corpus
12summary(corp)Corpus bao gồm 5 tài liệu, hiển thị 5 tài liệu:
Text Types Tokens Sentences
text1 10 10 1
text2 8 8 1
text3 7 7 1
text4 9 9 1
text5 10 11 1
Ví Dụ 2: Corpus Từ Khung Dữ Liệu
Trong thực tế, dữ liệu văn bản thường đi kèm với siêu dữ liệu liên quan (ví dụ: tác giả, ngày, danh mục). `quanteda` xử lý vấn đề này rất tốt:
1# Tạo một khung dữ liệu với văn bản và siêu dữ liệu
2text_df <- data.frame(
3 text = c(
4 "Customer service was excellent and responsive.",
5 "Product quality is poor. Very disappointed.",
6 "Shipping was fast. Happy with my purchase.",
7 "Price is too high for the quality received.",
8 "Great value for money. Would recommend!"
9 ),
10 rating = c(5, 2, 4, 2, 5),
11 product_category = c("Electronics", "Clothing", "Electronics", "Clothing", "Electronics"),
12 review_date = as.Date(c("2025-01-15", "2025-02-20", "2025-03-10", "2025-04-05", "2025-05-12")),
13 stringsAsFactors = FALSE
14)
15datatable(text_df)1# Tạo corpus từ khung dữ liệu
2reviews_corp <- corpus(text_df, text_field = "text")
3# Kiểm tra corpus với siêu dữ liệu
4summary(reviews_corp)Corpus bao gồm 5 tài liệu, hiển thị 5 tài liệu:
Text Types Tokens Sentences rating product_category review_date
text1 7 7 1 5 Electronics 2025-01-15
text2 7 8 2 2 Clothing 2025-02-20
text3 8 9 2 4 Electronics 2025-03-10
text4 9 9 1 2 Clothing 2025-04-05
text5 8 8 2 5 Electronics 2025-05-12
1# Truy cập các biến tài liệu (siêu dữ liệu) (các cột không được khai báo là "text_field")
2docvars(reviews_corp)rating product_category review_date
1 5 Electronics 2025-01-15
2 2 Clothing 2025-02-20
3 4 Electronics 2025-03-10
4 2 Clothing 2025-04-05
5 5 Electronics 2025-05-12
1# Tạo tập con của corpus theo siêu dữ liệu
2high_rated <- corpus_subset(reviews_corp, rating >= 4)
3summary(high_rated)Corpus bao gồm 3 tài liệu, hiển thị 3 tài liệu:
Text Types Tokens Sentences rating product_category review_date
text1 7 7 1 5 Electronics 2025-01-15
text3 8 9 2 4 Electronics 2025-03-10
text5 8 8 2 5 Electronics 2025-05-12
Token Hóa: Chia Văn Bản Thành Các Đơn Vị
Token hóa là quá trình chia văn bản thành các đơn vị riêng lẻ (tokens), thường là các từ. Hàm `tokens()` cung cấp nhiều khả năng token hóa.
Token Hóa Cơ Bản
1# Token hóa corpus đánh giá
2toks <- tokens(reviews_corp)
3# Xem các tokens từ tất cả tài liệu
4print(toks)Tokens bao gồm 5 tài liệu và 3 biến tài liệu.
text1 :
[1] "Customer" "service" "was" "excellent" "and"
[6] "responsive" "."
text2 :
[1] "Product" "quality" "is" "poor" "."
[6] "Very" "disappointed" "."
text3 :
[1] "Shipping" "was" "fast" "." "Happy" "with" "my"
[8] "purchase" "."
text4 :
[1] "Price" "is" "too" "high" "for" "the" "quality"
[8] "received" "."
text5 :
[1] "Great" "value" "for" "money" "." "Would"
[7] "recommend" "!"
Các Tùy Chọn Token Hóa Nâng Cao
`quanteda` cung cấp nhiều quyền kiểm soát đối với quá trình token hóa:
1# Tạo văn bản mẫu với các yếu tố khác nhau
2sample_text <- "Dr. Smith's email is
3[email protected]
4.
5 He earned $100,000 in 2024! Visit https://example.com
6 for more info. #DataScience #AI"
7sample_corp <- corpus(sample_text)
8# Các phương pháp token hóa khác nhau
9tokens_default <- tokens(sample_corp)
10tokens_no_punct <- tokens(sample_corp, remove_punct = TRUE)
11tokens_no_numbers <- tokens(sample_corp, remove_numbers = TRUE)
12tokens_no_symbols <- tokens(sample_corp, remove_symbols = TRUE)
13tokens_lowercase <- tokens(sample_corp, remove_punct = TRUE) %>% tokens_tolower()
14# So sánh kết quả
15print(tokens_default)Tokens bao gồm 1 tài liệu.
text1 :
[1] "Dr" "." "Smith's"
[4] "email" "is" "
[email protected]
"
[7] "." "He" "earned"
[10] "$" "100,000" "in"
[ ... và 10 đơn vị khác ]
1print(tokens_no_punct)Tokens bao gồm 1 tài liệu.
text1 :
[1] "Dr" "Smith's" "email"
[4] "is" "
[email protected]
" "He"
[7] "earned" "$" "100,000"
[10] "in" "2024" "Visit"
[ ... và 6 đơn vị khác ]
1print(tokens_no_numbers)Tokens bao gồm 1 tài liệu.
text1 :
[1] "Dr" "." "Smith's"
[4] "email" "is" "
[email protected]
"
[7] "." "He" "earned"
[10] "$" "in" "!"
[ ... và 8 đơn vị khác ]
1print(tokens_no_symbols)Tokens bao gồm 1 tài liệu.
text1 :
[1] "Dr" "." "Smith's"
[4] "email" "is" "
[email protected]
"
[7] "." "He" "earned"
[10] "100,000" "in" "2024"
[ ... và 9 đơn vị khác ]
1print(tokens_lowercase)Tokens bao gồm 1 tài liệu.
text1 :
[1] "dr" "smith's" "email"
[4] "is" "
[email protected]
" "he"
[7] "earned" "$" "100,000"
[10] "in" "2024" "visit"
[ ... và 6 đơn vị khác ]
Loại Bỏ Từ Dừng
Từ dừng là những từ thông dụng (ví dụ: "the", "is", "at") mà thường không mang ý nghĩa đáng kể. Việc loại bỏ chúng giúp giảm nhiễu và cải thiện hiệu quả tổng thể.
1# Xem 20 từ dừng tiếng Anh tích hợp sẵn đầu tiên
2head(stopwords("english"), 20)[1] "i" "me" "my" "myself" "we"
[6] "our" "ours" "ourselves" "you" "your"
[11] "yours" "yourself" "yourselves" "he" "him"
[16] "his" "himself" "she" "her" "hers"
1# Số lượng từ dừng tiếng Anh
2length(stopwords("english"))[1] 175
1# Loại bỏ từ dừng khỏi tokens
2toks_no_stop <- tokens(reviews_corp,
3 remove_punct = TRUE,
4 remove_numbers = TRUE) %>%
5 tokens_tolower() %>%
6 tokens_remove(stopwords("english"))
7# So sánh có và không có từ dừng
8print(tokens(reviews_corp, remove_punct = TRUE)[1])Tokens bao gồm 1 tài liệu và 3 biến tài liệu.
text1 :
[1] "Customer" "service" "was" "excellent" "and"
[6] "responsive"
1print(toks_no_stop[1])Tokens bao gồm 1 tài liệu và 3 biến tài liệu.
text1 :
[1] "customer" "service" "excellent" "responsive"
1# Đếm số lượng tokens trước và sau
2print(ntoken(tokens(reviews_corp, remove_punct = TRUE)))text1 text2 text3 text4 text5
6 6 7 8 6
1print(ntoken(toks_no_stop))text1 text2 text3 text4 text5
4 4 4 4 4
Gọt Từ
Gọt từ (stemming) là kỹ thuật giảm các từ về dạng gốc bằng cách loại bỏ các hậu tố (ví dụ: "running" → "run").
1# Văn bản ví dụ minh họa các biến thể của từ
2stem_text <- c(
3 "The running runners ran faster than expected.",
4 "Computing computers computed complex calculations.",
5 "The analyst analyzed analytical data using analysis techniques."
6)
7stem_corp <- corpus(stem_text)
8# Token hóa
9stem_toks <- tokens(stem_corp, remove_punct = TRUE) %>% tokens_tolower()
10# Áp dụng gọt từ
11stem_toks_stemmed <- tokens_wordstem(stem_toks)
12# So sánh bản gốc và bản đã gọt từ
13print(stem_toks[1])Tokens bao gồm 1 tài liệu.
text1 :
[1] "the" "running" "runners" "ran" "faster" "than" "expected"
1print(stem_toks_stemmed[1])Tokens bao gồm 1 tài liệu.
[1] "the" "run" "runner" "ran" "faster" "than" "expect"
Ma Trận Tài Liệu-Đặc Trưng (DFM): Biểu Diễn Số
Ma trận tài liệu-đặc trưng (DFM) là một biểu diễn số của văn bản, trong đó các hàng đại diện cho tài liệu, các cột đại diện cho đặc trưng (thường là từ), và các giá trị trong ô cho biết tần suất đặc trưng trong mỗi tài liệu. Cấu trúc này cho phép phân tích thống kê và các ứng dụng máy học.
1# Tạo DFM từ corpus đánh giá của chúng ta
2reviews_dfm <- reviews_corp %>%
3 tokens(remove_punct = TRUE, remove_numbers = TRUE) %>%
4 tokens_tolower() %>%
5 tokens_remove(stopwords("english")) %>%
6 dfm()
7# Kiểm tra DFM
8print(reviews_dfm)Ma trận tài liệu-đặc trưng của: 5 tài liệu, 19 đặc trưng (78.95% thưa) và 3 biến tài liệu.
features
docs customer service excellent responsive product quality poor disappointed
text1 1 1 1 1 0 0 0 0
text2 0 0 0 0 1 1 1 1
text3 0 0 0 0 0 0 0 0
text4 0 0 0 0 0 1 0 0
text5 0 0 0 0 0 0 0 0
features
docs shipping fast
text1 0 0
text2 0 0
text3 1 1
text4 0 0
text5 0 0
[ đạt max_nfeat ... 9 đặc trưng khác ]
1# Xem kích thước DFM
2print(dim(reviews_dfm))[1] 5 19
Thống Kê Đặc Trưng: Hiểu Tần Suất Từ
Phân tích tần suất đặc trưng tiết lộ các thuật ngữ quan trọng nhất trong corpus.
1# Tính toán tần suất đặc trưng
2feat_freq <- textstat_frequency(reviews_dfm)
3# Xem các đặc trưng hàng đầu
4head(feat_freq, 15)feature frequency rank docfreq group
1 quality 2 1 2 all
2 customer 1 2 1 all
3 service 1 2 1 all
4 excellent 1 2 1 all
5 responsive 1 2 1 all
6 product 1 2 1 all
7 poor 1 2 1 all
8 disappointed 1 2 1 all
9 shipping 1 2 1 all
10 fast 1 2 1 all
11 happy 1 2 1 all
12 purchase 1 2 1 all
13 price 1 2 1 all
14 high 1 2 1 all
15 received 1 2 1 all
1# Trực quan hóa các đặc trưng hàng đầu
2feat_freq %>%
3 head(15) %>%
4 ggplot(aes(x = reorder(feature, frequency), y = frequency)) +
5 geom_col(fill = "steelblue") +
6 coord_flip() +
7 labs(title = "15 Thuật Ngữ Phổ Biến Nhất",
8 x = "Thuật Ngữ",
9 y = "Tần Suất") +
10 theme_minimal()Phân Tích Đặc Trưng Dựa Trên Nhóm
Phân tích các đặc trưng theo nhóm (ví dụ: đánh giá cao so với đánh giá thấp) tiết lộ từ vựng đặc trưng:
1# Nhóm DFM theo danh mục xếp hạng
2reviews_dfm_grouped <- reviews_corp %>%
3 tokens(remove_punct = TRUE, remove_numbers = TRUE) %>%
4 tokens_tolower() %>%
5 tokens_remove(stopwords("english")) %>%
6 dfm() %>%
7 dfm_group(groups = rating)
8# Tính toán tần suất theo nhóm
9freq_by_rating <- textstat_frequency(reviews_dfm_grouped, groups = rating)
10# Xem các đặc trưng hàng đầu cho mỗi xếp hạng
11print(freq_by_rating %>% filter(group == 5) %>% head(10))feature frequency rank docfreq group
12 customer 1 1 1 5
13 service 1 1 1 5
14 excellent 1 1 1 5
15 responsive 1 1 1 5
16 great 1 1 1 5
17 value 1 1 1 5
18 money 1 1 1 5
19 recommend 1 1 1 5
1print(freq_by_rating %>% filter(group == 2) %>% head(10))feature frequency rank docfreq group
1 quality 2 1 1 2
2 product 1 2 1 2
3 poor 1 2 1 2
4 disappointed 1 2 1 2
5 price 1 2 1 2
6 high 1 2 1 2
7 received 1 2 1 2
1# Trực quan hóa so sánh
2freq_by_rating %>%
3 filter(group %in% c(2, 5)) %>%
4 group_by(group) %>%
5 slice_max(frequency, n = 8) %>%
6 ungroup() %>%
7 mutate(feature = reorder_within(feature, frequency, group)) %>%
8 ggplot(aes(x = feature, y = frequency, fill = factor(group))) +
9 geom_col(show.legend = FALSE) +
10 facet_wrap(~ group, scales = "free_y", labeller = labeller(group = c("2" = "Đánh Giá 2 Sao", "5" = "Đánh Giá 5 Sao"))) +
11 scale_x_reordered() +
12 coord_flip() +
13 labs(title = "Các Thuật Ngữ Hàng Đầu Theo Xếp Hạng Đánh Giá",
14 x = "Thuật Ngữ",
15 y = "Tần Suất") +
16 theme_minimal()Đám Mây Từ: Khám Phá Trực Quan
Đám mây từ cung cấp hình ảnh trực quan trực quan về tần suất thuật ngữ:
1# Tạo đám mây từ
2set.seed(123)
3textplot_wordcloud(reviews_dfm,
4 min_count = 1,
5 max_words = 50,
6 rotation = 0.25,
7 color = RColorBrewer::brewer.pal(8, "Dark2"))N-grams: Các Biểu Thức Nhiều Từ
N-grams là các chuỗi N tokens liên tiếp. Bigrams (2-grams) và trigrams (3-grams) nắm bắt các biểu thức và cụm từ nhiều từ mà các từ đơn lẻ bỏ qua.
1# Tạo văn bản mẫu để phân tích N-gram
2ngram_text <- c(
3 "Machine learning and artificial intelligence are transforming data science.",
4 "Natural language processing enables text analytics at scale.",
5 "Deep learning models achieve state of the art results.",
6 "Data science requires domain knowledge and technical skills.",
7 "Text mining extracts insights from unstructured data."
8)
9ngram_corp <- corpus(ngram_text)
10# Tạo bigrams
11bigrams <- ngram_corp %>%
12 tokens(remove_punct = TRUE) %>%
13 tokens_tolower() %>%
14 tokens_ngrams(n = 2) %>%
15 dfm()
16# Tính toán tần suất bigram
17bigram_freq <- textstat_frequency(bigrams)
18head(bigram_freq, 15)feature frequency rank docfreq group
1 data_science 2 1 2 all
2 machine_learning 1 2 1 all
3 learning_and 1 2 1 all
4 and_artificial 1 2 1 all
5 artificial_intelligence 1 2 1 all
6 intelligence_are 1 2 1 all
7 are_transforming 1 2 1 all
8 transforming_data 1 2 1 all
9 natural_language 1 2 1 all
10 language_processing 1 2 1 all
11 processing_enables 1 2 1 all
12 enables_text 1 2 1 all
13 text_analytics 1 2 1 all
14 analytics_at 1 2 1 all
15 at_scale 1 2 1 all
1# Trực quan hóa các bigrams hàng đầu
2bigram_freq %>%
3 head(10) %>%
4 ggplot(aes(x = reorder(feature, frequency), y = frequency)) +
5 geom_col(fill = "indianred") +
6 coord_flip() +
7 labs(title = "10 Bigrams Hàng Đầu",
8 x = "Bigram",
9 y = "Tần Suất") +
10 theme_minimal()1# Tạo trigrams
2trigrams <- ngram_corp %>%
3 tokens(remove_punct = TRUE) %>%
4 tokens_tolower() %>%
5 tokens_ngrams(n = 3) %>%
6 dfm()
7# Tính toán tần suất trigram
8trigram_freq <- textstat_frequency(trigrams)
9# Trực quan hóa các bigrams hàng đầu
10trigram_freq %>%
11 head(10) %>%
12 ggplot(aes(x = reorder(feature, frequency), y = frequency)) +
13 geom_col(fill = "steelblue") +
14 coord_flip() +
15 labs(title = "10 Trigrams Hàng Đầu",
16 x = "Trigram",
17 y = "Tần Suất") +
18 theme_minimal()Ví Dụ Thực Tế: Phân Tích Phản Hồi Khách Hàng
Hãy thử áp dụng các kỹ thuật này vào một kịch bản thực tế hơn.
1# Tạo một tập dữ liệu phản hồi khách hàng thực tế
2set.seed(456)
3feedback_df <- data.frame(
4 text = c(
5 "Absolutely love this product! Best purchase I've made all year. Quality is outstanding.",
6 "Terrible experience. Product broke after one week. Customer service was unhelpful.",
7 "Good value for the price. Works as expected. Would buy again.",
8 "Shipping took forever. Product is okay but not worth the wait.",
9 "Amazing quality and fast delivery. Highly recommend to everyone!",
10 "Product description was misleading. Not what I expected at all.",
11 "Decent product but customer support needs improvement. Long wait times.",
12 "Exceeded my expectations! Great features and easy to use.",
13 "Poor quality control. Received damaged item. Return process was difficult.",
14 "Perfect! Exactly what I needed. Five stars all around.",
15 "Overpriced for what you get. Better alternatives available elsewhere.",
16 "Good product but instructions were confusing. Setup took hours.",
17 "Love it! Works perfectly and looks great too.",
18 "Not satisfied. Product feels cheap and flimsy.",
19 "Best customer service ever! They resolved my issue immediately.",
20 "Average product. Nothing special but gets the job done.",
21 "Fantastic! Will definitely purchase from this company again.",
22 "Disappointed with the quality. Expected much better.",
23 "Great features but battery life is poor.",
24 "Excellent value. Highly recommend for budget shoppers."
25 ),
26 rating = c(5, 1, 4, 2, 5, 1, 3, 5, 1, 5, 2, 3, 5, 2, 5, 3, 5, 2, 3, 4),
27 category = sample(c("Electronics", "Home & Kitchen", "Clothing"), 20, replace = TRUE),
28 helpful_votes = sample(0:50, 20, replace = TRUE),
29 stringsAsFactors = FALSE
30)
31# Tạo corpus
32feedback_corp <- corpus(feedback_df, text_field = "text")
33# Hoàn thành quy trình tiền xử lý
34feedback_dfm <- feedback_corp %>%
35 tokens(remove_punct = TRUE,
36 remove_numbers = TRUE,
37 remove_symbols = TRUE) %>%
38 tokens_tolower() %>%
39 tokens_remove(stopwords("english")) %>%
40 tokens_wordstem() %>%
41 dfm()
42# Phân tích các thuật ngữ liên quan đến cảm xúc tổng thể
43sentiment_terms <- c("love", "best", "great", "excel", "amaz", "perfect",
44 "terribl", "poor", "worst", "disappoint", "bad")
45sentiment_dfm <- dfm_select(feedback_dfm, pattern = sentiment_terms)
46# Tính toán tần suất thuật ngữ cảm xúc
47sentiment_freq <- textstat_frequency(sentiment_dfm)
48# Trực quan hóa các thuật ngữ cảm xúc
49ggplot(sentiment_freq, aes(x = reorder(feature, frequency), y = frequency)) +
50 geom_col(aes(fill = feature), show.legend = FALSE) +
51 coord_flip() +
52 labs(title = "Tần Suất Các Thuật Ngữ Liên Quan Đến Cảm Xúc",
53 subtitle = "Phân Tích Phản Hồi Khách Hàng",
54 x = "Thuật Ngữ (Đã Gọt Từ)",
55 y = "Tần Suất") +
56 theme_minimal() +
57 scale_fill_manual(values = c(
58 "love" = "darkgreen", "best" = "darkgreen", "great" = "darkgreen",
59 "excel" = "darkgreen", "amaz" = "darkgreen", "perfect" = "darkgreen",
60 "terribl" = "darkred", "poor" = "darkred", "worst" = "darkred",
61 "disappoint" = "darkred", "bad" = "darkred"
62 ))1# So sánh các đánh giá cao và thấp
2# Tạo biến danh mục xếp hạng
3rating_category <- ifelse(docvars(feedback_corp, "rating") >= 4, "High Rating", "Low Rating")
4feedback_grouped <- feedback_corp %>%
5 tokens(remove_punct = TRUE, remove_numbers = TRUE) %>%
6 tokens_tolower() %>%
7 tokens_remove(stopwords("english")) %>%
8 dfm() %>%
9 dfm_group(groups = rating_category)
10# Tính toán độ đặc trưng của từ
11keyness_stats <- textstat_keyness(feedback_grouped, target = "High Rating")
12# Trực quan hóa độ đặc trưng của từ
13textplot_keyness(keyness_stats, n = 10, color = c("darkgreen", "darkred")) +
14 labs(title = "Các Thuật Ngữ Đặc Trưng: Đánh Giá Cao so với Đánh Giá Thấp") +
15 theme_minimal()Phân Tích Độ Tương Đồng Tài Liệu
Hiểu độ tương đồng của tài liệu là rất quan trọng cho các tác vụ như phát hiện trùng lặp, phân cụm tài liệu và hệ thống đề xuất:
1# Sử dụng DFM đã tiền xử lý để đo lường độ tương đồng tốt hơn
2feedback_dfm_clean <- feedback_corp %>%
3 tokens(remove_punct = TRUE, remove_numbers = TRUE) %>%
4 tokens_tolower() %>%
5 tokens_remove(stopwords("english")) %>%
6 tokens_wordstem() %>%
7 dfm()
8# Tính toán độ tương đồng tài liệu bằng độ tương đồng cosin
9doc_similarity <- textstat_simil(feedback_dfm_clean,
10 method = "cosine",
11 margin = "documents")
12# Tìm các tài liệu tương đồng nhất với đánh giá đầu tiên (một đánh giá tích cực)
13similarity_df <- as.data.frame(as.matrix(doc_similarity))
14similarity_to_doc1 <- sort(as.numeric(similarity_df[1, ]), decreasing = TRUE)[2:6] # Bỏ qua tài liệu đầu tiên (chính nó)
15# Tài liệu đánh giá đầu tiên
16as.character(feedback_corp)[1]text1
"Absolutely love this product! Best purchase I've made all year. Quality is outstanding."
1# 3 tài liệu tương đồng hàng đầu
2for(i in 2:4) {
3 doc_idx <- order(as.numeric(similarity_df[1, ]), decreasing = TRUE)[i]
4 cat("\nDocument", doc_idx, "(Similarity:", round(similarity_df[1, doc_idx], 3), "):\n")
5 cat(as.character(feedback_corp)[doc_idx], "\n")
6}Document 6 (Similarity: 0.167 ):
Product description was misleading. Not what I expected at all.
Document 17 (Similarity: 0.167 ):
Fantastic! Will definitely purchase from this company again.
Document 13 (Similarity: 0.149 ):
Love it! Works perfectly and looks great too.
Cần lưu ý rằng độ tương đồng cosin đơn thuần có thể không đủ vì tài liệu tương đồng hàng đầu không khớp với cảm xúc của tài liệu gốc.
Độ Tương Đồng Có Nhận Thức Về Cảm Xúc
Để cải thiện việc đánh giá độ tương đồng, chúng ta có thể kết hợp điểm cảm xúc. Hãy thêm điểm cảm xúc như một đặc trưng.
1# Định nghĩa từ điển cảm xúc tích cực và tiêu cực
2positive_words <- c("love", "best", "great", "excellent", "amazing", "perfect",
3 "fantastic", "outstanding", "happy", "wonderful", "superb")
4negative_words <- c("terrible", "poor", "worst", "disappointing", "bad", "awful",
5 "horrible", "useless", "disappointed", "misleading", "cheap")
6# Tạo tokens
7feedback_toks <- feedback_corp %>%
8 tokens(remove_punct = TRUE, remove_numbers = TRUE) %>%
9 tokens_tolower() %>%
10 tokens_remove(stopwords("english"))
11# Tính toán điểm cảm xúc cho mỗi tài liệu
12sentiment_scores <- sapply(feedback_toks, function(doc_tokens) {
13 pos_count <- sum(doc_tokens %in% positive_words)
14 neg_count <- sum(doc_tokens %in% negative_words)
15 # Điểm cảm xúc ròng
16 (pos_count - neg_count) / length(doc_tokens)
17})
18# Tạo DFM với các đặc trưng cảm xúc
19feedback_dfm_sentiment <- feedback_toks %>%
20 tokens_wordstem() %>%
21 dfm()
22# Thêm điểm cảm xúc như một đặc trưng có trọng số
23# Tạo một đặc trưng cảm xúc bằng cách nhân đôi điểm cảm xúc
24sentiment_feature_matrix <- matrix(sentiment_scores * 10, # Tăng tỷ lệ để dễ thấy
25 nrow = ndoc(feedback_dfm_sentiment),
26 ncol = 1,
27 dimnames = list(docnames(feedback_dfm_sentiment),
28 "SENTIMENT_SCORE"))
29# Kết hợp với DFM gốc
30feedback_dfm_with_sentiment <- cbind(feedback_dfm_sentiment, sentiment_feature_matrix)
31# Tính toán độ tương đồng với cảm xúc
32doc_similarity_sentiment <- textstat_simil(feedback_dfm_with_sentiment,
33 method = "cosine",
34 margin = "documents")
35# So sánh kết quả
36similarity_df_sentiment <- as.data.frame(as.matrix(doc_similarity_sentiment))
37# Độ tương đồng tiêu chuẩn so với độ tương đồng có nhận thức về cảm xúc
38# Tài liệu đầu tiên
39cat(as.character(feedback_corp)[1], "\n")Absolutely love this product! Best purchase I've made all year. Quality is outstanding.
1# Độ tương đồng có nhận thức về cảm xúc
2for(i in 2:4) {
3 doc_idx <- order(as.numeric(similarity_df_sentiment[1, ]), decreasing = TRUE)[i]
4 cat("\nDocument", doc_idx, "(Similarity:", round(similarity_df_sentiment[1, doc_idx], 3), "):\n")
5 cat(as.character(feedback_corp)[doc_idx], "\n")
6 cat("Rating:", docvars(feedback_corp, "rating")[doc_idx],
7 "| Sentiment:", round(sentiment_scores[doc_idx], 3), "\n")
8}Document 13 (Similarity: 0.697 ):
Love it! Works perfectly and looks great too.
Rating: 5 | Sentiment: 0.4
Document 17 (Similarity: 0.65 ):
Fantastic! Will definitely purchase from this company again.
Rating: 5 | Sentiment: 0.25
Document 5 (Similarity: 0.427 ):
Amazing quality and fast delivery. Highly recommend to everyone!
Rating: 5 | Sentiment: 0.143
Phân Tích Đồng Xuất Hiện Đặc Trưng
Hiểu những từ nào thường xuất hiện cùng nhau có thể giúp tiết lộ các mối quan hệ ngữ nghĩa.
1# Tạo ma trận đồng xuất hiện đặc trưng (FCM)
2fcm <- feedback_corp %>%
3 tokens(remove_punct = TRUE) %>%
4 tokens_tolower() %>%
5 tokens_remove(stopwords("english")) %>%
6 fcm()
7# Xem các đồng xuất hiện hàng đầu
8feat_cooc <- fcm[1:20, 1:20]
9# Trực quan hóa mạng lưới ngữ nghĩa
10set.seed(123)
11textplot_network(fcm,
12 min_freq = 2,
13 edge_alpha = 0.5,
14 edge_size = 2,
15 vertex_labelsize = 3) +
16 labs(title = "Mạng Lưới Ngữ Nghĩa Phản Hồi Khách Hàng")Thao Tác Và Chuyển Đổi DFM
`quanteda` cung cấp các hàm mạnh mẽ để thao tác DFM:
1# Cắt tỉa DFM để loại bỏ các đặc trưng hiếm và rất phổ biến
2feedback_dfm_trimmed <- dfm_trim(feedback_dfm,
3 min_termfreq = 2, # Loại bỏ các thuật ngữ xuất hiện < 2 lần
4 max_docfreq = 0.8, # Loại bỏ các thuật ngữ xuất hiện trong > 80% tài liệu
5 docfreq_type = "prop")
6# Kích thước DFM gốc
7print(dim(feedback_dfm))[1] 20 95
1# Kích thước DFM đã cắt tỉa
2print(dim(feedback_dfm_trimmed))[1] 20 22
1# Trọng số DFM sử dụng TF-IDF
2feedback_tfidf <- dfm_tfidf(feedback_dfm_trimmed)
3# Các đặc trưng hàng đầu theo TF-IDF
4tfidf_freq <- textstat_frequency(feedback_tfidf, force = T)
5print(head(tfidf_freq, 15))feature frequency rank docfreq group
1 product 3.183520 1 8 all
2 qualiti 2.795880 2 4 all
3 expect 2.795880 2 4 all
4 custom 2.471726 4 3 all
5 great 2.471726 4 3 all
6 love 2.000000 6 2 all
7 best 2.000000 6 2 all
8 purchas 2.000000 6 2 all
9 servic 2.000000 6 2 all
10 good 2.000000 6 2 all
11 valu 2.000000 6 2 all
12 work 2.000000 6 2 all
13 took 2.000000 6 2 all
14 wait 2.000000 6 2 all
15 high 2.000000 6 2 all
1# Chọn các đặc trưng cụ thể
2service_terms <- c("service", "support", "help", "response", "customer")
3service_dfm <- dfm_select(feedback_dfm, pattern = service_terms)
4# Tần suất các thuật ngữ liên quan đến dịch vụ
5print(colSums(service_dfm))support
1
1# Loại bỏ các đặc trưng cụ thể
2filtered_dfm <- dfm_remove(feedback_dfm, pattern = c("product", "item"))
3# Số lượng đặc trưng gốc
4nfeat(feedback_dfm)[1] 95
1# Số lượng đặc trưng đã lọc
2nfeat(filtered_dfm)[1] 93
✨ Giá trị đắt giá
Phần 1 của chuỗi bài viết này đã trang bị cho bạn những công cụ cần thiết để bắt đầu hành trình phân tích văn bản trong R với gói `quanteda`. Bạn đã học cách:
* Xây dựng `corpus` từ nhiều nguồn dữ liệu.
* Thực hiện các bước tiền xử lý văn bản thiết yếu như token hóa, loại bỏ từ dừng và gọt từ.
* Tạo và thao tác ma trận tài liệu-đặc trưng (DFM) để biến văn bản thành dữ liệu số.
* Khám phá tần suất từ, phân tích theo nhóm và trực quan hóa dữ liệu văn bản bằng đám mây từ.
* Áp dụng N-grams để nắm bắt các biểu thức nhiều từ.
* Thực hiện phân tích độ tương đồng tài liệu cơ bản và nâng cao có nhận thức về cảm xúc.
* Khám phá ma trận đồng xuất hiện đặc trưng (FCM) để hiểu mối quan hệ giữa các từ.
* Thực hiện các thao tác DFM nâng cao như cắt tỉa và trọng số TF-IDF.
Những kỹ năng này là nền tảng cho bất kỳ dự án khoa học dữ liệu văn bản nào, mở ra cánh cửa cho những phân tích phức tạp hơn.
Câu hỏi tư duy hoặc bài tập ứng dụng
1. Dựa trên kiến thức về tiền xử lý văn bản, hãy thảo luận khi nào việc loại bỏ các từ dừng hoặc áp dụng gọt từ có thể không phù hợp cho một tác vụ phân tích cụ thể (ví dụ: phân tích văn phong, phân tích cảm xúc dựa trên ngữ cảnh).
2. Hãy thử tìm một tập dữ liệu văn bản công khai (ví dụ: bình luận phim, tiêu đề tin tức) và áp dụng quy trình tiền xử lý đầy đủ mà bạn đã học. Sau đó, tạo biểu đồ 15 từ phổ biến nhất và 10 bigram phổ biến nhất.


