📝 tidytextの革新的テキスト分析
tidytextは、テキスト分析にtidy dataの原則を適用した革新的なパッケージです。「1行1トークン」の整然データ形式により、dplyr、ggplot2との完全な統合を実現し、美しいテキスト分析ワークフローを提供します。
🔄 Tidytextテキスト分析パイプライン
🧠 テキスト分析の理論的基盤
📄 非構造化→構造化
自然言語テキストを数値的に表現可能な構造化データに変換
🔤 Token化の重要性
文書を最小意味単位に分割し、統計的分析を可能にする基盤
🧹 ノイズ除去
分析に無関係な要素を除去し、シグナル対ノイズ比を向上
📦 tidytextコアパッケージ
library(tidymodels)
library(tidytext)
library(textrecipes)
library(textdata)
library(tidyverse)
library(janeaustenr)
book_words <- austen_books() %>%
group_by(book) %>%
mutate(linenumber = row_number(),
chapter = cumsum(str_detect(text, regex("^chapter [\\\\divxlc]",
ignore_case = TRUE)))) %>%
ungroup()
glimpse(book_words)
📊 tidytext
テキスト分析の中核パッケージ。1行1トークンの原則でテキストを整然データ化。unnest_tokens()によるトークン化が核となる機能。
unnest_tokens(), get_sentiments(), bind_tf_idf()
🔧 textrecipes
tidymodelsとの連携パッケージ。テキスト前処理をレシピ形式で記述。TF-IDF、n-gram、ストップワード除去を統合ワークフローで実行。
step_tokenize(), step_stopwords(), step_tfidf()
📚 textdata
感情分析辞書とテキストデータセット。AFINN、Bing、NRC辞書による多様な感情分析。初回使用時に自動ダウンロード。
get_sentiments("afinn"), get_sentiments("bing")
🎯 stringr
テキスト操作の基盤パッケージ。正規表現による柔軟な文字列処理。テキスト前処理の前段階で使用される重要なツール。
str_detect(), str_replace(), str_extract()
🔤 テキストのトークン化と前処理
テキスト分析の第一歩は、自然言語テキストを分析可能な形式に変換することです。tidytextの核となるunnest_tokens()関数により、美しい「1行1トークン」形式でテキストを整然データ化します。
📝 基本的なトークン化
tidy_books <- book_words %>%
unnest_tokens(word, text)
data("stop_words")
tidy_books <- tidy_books %>%
anti_join(stop_words)
word_counts <- tidy_books %>%
count(word, sort = TRUE)
print(head(word_counts, 15))
word_counts %>%
slice_head(n = 15) %>%
mutate(word = reorder(word, n)) %>%
ggplot(aes(x = word, y = n, fill = word)) +
geom_col(show.legend = FALSE) +
coord_flip() +
labs(title = "Jane Austen作品の最頻出語",
x = "単語", y = "頻度") +
theme_minimal()
📊 TF-IDF: 単語重要度の数学的理論
📈 Term Frequency (TF)
文書内での単語の相対的な出現頻度。文書の長さで正規化される
📉 Inverse Document Frequency (IDF)
コーパス全体での単語の希少性を示す。希少語ほど高い値
🎯 TF-IDF統合
文書内で重要かつ、コーパス内で特徴的な単語を高く評価
🧮 計算の実践
tidytextのbind_tf_idf()で自動計算。手動計算も可能
🔬 高度なトークン化技術
austen_bigrams <- book_words %>%
unnest_tokens(bigram, text, token = "ngrams", n = 2) %>%
filter(!is.na(bigram))
bigrams_separated <- austen_bigrams %>%
separate(bigram, c("word1", "word2"), sep = " ")
bigrams_filtered <- bigrams_separated %>%
filter(!word1 %in% stop_words$word) %>%
filter(!word2 %in% stop_words$word)
bigram_counts <- bigrams_filtered %>%
count(word1, word2, sort = TRUE)
print(head(bigram_counts, 10))
austen_sentences <- book_words %>%
unnest_tokens(sentence, text, token = "sentences")
austen_paragraphs <- book_words %>%
unnest_tokens(paragraph, text, token = "paragraphs")
🔤 単語トークン化
最も基本的なトークン化。空白や句読点で分割し、1行1単語の整然データを生成。ストップワード除去で分析に有用な単語のみ抽出。
unnest_tokens(word, text), anti_join(stop_words)
🔗 n-gramトークン化
連続するn個の単語を組として扱う。文脈情報を保持し、単語間の関係を分析可能。バイグラム、トライグラムが頻用される。
unnest_tokens(bigram, text, token = "ngrams", n = 2)
📄 文・段落トークン化
より大きな文書単位でのトークン化。文や段落レベルでの分析や感情分析に活用。文書構造を考慮した分析を実現。
unnest_tokens(sentence, text, token = "sentences")
🧹 テキスト清浄化
不要な要素の除去と正規化。空白の除去、大文字小文字統一、特殊文字処理など。分析精度向上のための重要な前処理。
str_remove_all(), str_to_lower(), filter()
😊 感情分析と辞書ベース手法
感情分析は、テキストから感情的な情報を抽出する重要な技術です。tidytextは複数の感情辞書を提供し、美しいワークフローで感情の定量化と可視化を実現します。
🧠 感情分析辞書体系とアルゴリズム
💭 感情分析の理論と手法体系
📚 辞書ベース利点
高速処理、実装簡易、解釈可能性、少ないリソース要求
🤖 機械学習利点
文脈考慮、パターン学習、ドメイン適応、高精度可能
🌊 ハイブリッド利点
両手法の長所統合、堅牢性向上、複雑な感情表現対応
📊 実践的選択
データ量、計算資源、精度要求、解釈必要性を総合評価
📚 辞書ベース感情分析
afinn <- get_sentiments("afinn")
bing <- get_sentiments("bing")
nrc <- get_sentiments("nrc")
austen_sentiment <- tidy_books %>%
inner_join(afinn, by = "word") %>%
group_by(book) %>%
summarise(sentiment_score = sum(value),
sentiment_words = n(),
avg_sentiment = sentiment_score / sentiment_words,
.groups = "drop")
print(austen_sentiment)
austen_sentiment %>%
mutate(book = fct_reorder(book, avg_sentiment)) %>%
ggplot(aes(x = book, y = avg_sentiment, fill = book)) +
geom_col(show.legend = FALSE) +
coord_flip() +
labs(title = "Jane Austen作品の平均感情スコア",
x = "作品", y = "平均感情スコア") +
theme_minimal()
🌈 多次元感情分析
austen_emotions <- tidy_books %>%
inner_join(nrc, by = "word") %>%
count(book, sentiment) %>%
pivot_wider(names_from = sentiment, values_from = n, values_fill = 0)
emotion_radar <- tidy_books %>%
inner_join(nrc, by = "word") %>%
filter(!sentiment %in% c("positive", "negative")) %>%
count(sentiment) %>%
mutate(percentage = n / sum(n) * 100)
emotion_radar %>%
ggplot(aes(x = reorder(sentiment, percentage), y = percentage, fill = sentiment)) +
geom_col(show.legend = FALSE) +
coord_flip() +
labs(title = "Jane Austen作品の感情プロファイル",
x = "感情", y = "割合(%)") +
theme_minimal()
# A tibble: 6 × 4
book sentiment_score sentiment_words avg_sentiment
<fct> <int> <int> <dbl>
1 Sense & Sensibility 2164 4541 0.477
2 Pride & Prejudice 1841 4298 0.428
3 Mansfield Park 1618 4157 0.389
4 Emma 2107 4756 0.443
5 Northanger Abbey 1122 2459 0.456
6 Persuasion 1016 2317 0.439
# 📊 Emma が最も感情的豊かさを示している
📊 AFINN辞書
-5から+5の数値スコアで感情を定量化。シンプルで直感的な感情分析が可能。総合的な感情傾向の把握に最適。
get_sentiments("afinn"), sum(value)
🎯 Bing辞書
positive/negativeのバイナリ分類。シンプルな極性判定に最適。頻度ベースの感情分析で直感的な結果を提供。
get_sentiments("bing"), count(sentiment)
🌈 NRC辞書
10種類の感情カテゴリ(怒り、恐れ、期待など)。多次元感情分析により、感情の細やかなニュアンスを捕捉。
get_sentiments("nrc"), filter(sentiment == "joy")
📈 時系列感情分析
章や段落単位での感情変化の追跡。ストーリーの感情的起伏を可視化し、物語構造の分析を支援。
group_by(chapter), summarise(sentiment_score)
🤖 機械学習によるテキスト分類
textrecipesパッケージにより、テキスト前処理を tidymodels ワークフローに統合できます。TF-IDF変換からハイパーパラメータチューニングまで、美しい一貫したワークフローでテキスト分類を実現します。
📋 textrecipesによる前処理パイプライン
book_classification <- book_words %>%
filter(str_length(text) > 50) %>%
select(book, text) %>%
slice_sample(n = 2000) %>%
mutate(book = factor(book))
set.seed(123)
book_split <- initial_split(book_classification, prop = 0.8, strata = book)
book_train <- training(book_split)
book_test <- testing(book_split)
text_recipe <- recipe(book ~ text, data = book_train) %>%
step_tokenize(text) %>%
step_stopwords(text) %>%
step_tokenfilter(text, max_tokens = 1000) %>%
step_tfidf(text) %>%
step_normalize(all_numeric_predictors())
text_recipe %>%
prep() %>%
bake(new_data = NULL) %>%
glimpse()
🎯 複数モデルの訓練と評価
rf_spec <- rand_forest(trees = 500) %>%
set_engine("ranger") %>%
set_mode("classification")
svm_spec <- svm_linear() %>%
set_engine("LiblineaR") %>%
set_mode("classification")
nb_spec <- naive_Bayes() %>%
set_engine("naivebayes") %>%
set_mode("classification")
text_workflows <- workflow_set(
preproc = list(text = text_recipe),
models = list(rf = rf_spec, svm = svm_spec, nb = nb_spec)
)
book_folds <- vfold_cv(book_train, v = 5, strata = book)
text_results <- text_workflows %>%
workflow_map(
resamples = book_folds,
metrics = metric_set(accuracy, roc_auc, f_meas),
verbose = TRUE
)
text_results %>%
rank_results() %>%
filter(.metric == "accuracy") %>%
select(model, .config, mean, rank)
# A tibble: 3 × 4
model .config mean rank
<chr> <chr> <dbl> <int>
1 svm Preprocessor1_Model1 0.834 1
2 rf Preprocessor1_Model1 0.798 2
3 nb Preprocessor1_Model1 0.756 3
# 🏆 SVM が最高の分類精度を達成!
📝 step_tokenize()
textrecipesの基本関数。テキストを単語に分割し、tidymodelsワークフローに統合。複数のトークン化方式をサポート。
step_tokenize(text, token = "words")
🧹 step_stopwords()
ストップワードの自動除去。多言語対応で、カスタム辞書の追加も可能。テキスト分析の精度向上に重要な前処理。
step_stopwords(text, language = "en", custom_stopwords)
🔢 step_tfidf()
TF-IDF変換による単語重要度の計算。文書内頻度と逆文書頻度を統合し、特徴的な単語を強調した数値化を実現。
step_tfidf(text, norm = "l2", sublinear_tf = TRUE)
⚡ workflow_set()
複数の前処理・モデル組み合わせを効率的に比較。ワークフローセットにより、大規模な実験を統一的に管理・実行可能。
workflow_set(preproc, models), workflow_map()