TF-IDF と単語頻度分析
bind_tf_idf() を使って、文書間での単語の重要度をスコア化します。
「TF-IDF と単語頻度分析」はCoddyKit上の無料R Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはR Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 R Academyコースには全4レッスンが含まれています。
TF-IDFとは
TF-IDF(Term Frequency–Inverse Document Frequency)は、コーパス内の特定の文書において、ある単語がどれだけ特徴的かを測定します。TF-IDFスコアが高い単語は、その文書では頻出する一方で、すべての文書全体ではまれです。そのため、文書の主要なトピックを示す有力な指標になります。
# TF-IDF formula
# TF(w, d) = count of w in document d / total words in d
# IDF(w) = log(N / number of docs containing w)
# TF-IDF(w, d) = TF(w, d) * IDF(w)
# Manual example
N <- 4 # total documents
docs_with_word <- 1 # 'neural' appears in only 1 doc
tf <- 5 / 100 # word appears 5 times in 100-word doc
idf <- log(N / docs_with_word)
tfidf <- tf * idf
cat('TF: ', round(tf, 4), '\n')
cat('IDF: ', round(idf, 4), '\n')
cat('TF-IDF: ', round(tfidf, 4), '\n')トークン数の準備
TF-IDFを計算する前に、document(文書識別子)、word(トークン)、n(出現数)の列を持つデータフレームを用意する必要があります。unnest_tokens()に続けてcount(document, word)を使用します。
library(tidytext)
library(dplyr)
# Simulate a 4-document corpus on tech topics
docs <- tibble::tibble(
document = c(rep('ML', 3), rep('Stats', 3), rep('DB', 3), rep('Web', 3)),
text = c(
'machine learning neural networks training',
'deep learning models gradient descent',
'reinforcement learning reward policy agent',
'probability distributions hypothesis testing',
'bayesian inference regression analysis variance',
'statistics sampling confidence intervals normal',
'database sql joins indexes queries transactions',
'relational tables primary keys foreign constraints',
'nosql document store mongodb redis cassandra',
'html css javascript frontend react components',
'dom events browser api fetch requests',
'responsive design flexbox grid layout'
)
)
word_counts <- docs |>
unnest_tokens(word, text) |>
count(document, word, sort = TRUE)
cat('Document-word pairs:', nrow(word_counts), '\n')
print(head(word_counts, 8))bind_tf_idf: TF-IDFの計算
bind_tf_idf(word, document, n)は、tidy形式のカウントデータフレームを受け取り、tf(用語頻度)、idf(逆文書頻度)、tf_idf(それらの積)という3つの列を追加します。IDFは、データフレームに含まれる文書から計算されます。
library(tidytext)
library(dplyr)
docs <- tibble::tibble(
document = c(rep('ML', 2), rep('Stats', 2), rep('DB', 2)),
text = c(
'machine learning neural gradient',
'deep networks training epochs',
'probability distributions variance covariance',
'bayesian inference prior posterior',
'sql database tables joins indexes',
'queries transactions foreign primary'
)
)
tfidf <- docs |>
unnest_tokens(word, text) |>
count(document, word) |>
bind_tf_idf(word, document, n)
cat('Columns added:', names(tfidf), '\n')
print(head(arrange(tfidf, desc(tf_idf)), 8))arrange(desc(tf_idf)): 上位の用語
tf_idfの降順で並べ替えると、各文書を最もよく特徴付ける単語を確認できます。すべての文書に含まれるIDFが0の単語は、頻度に関係なくTF-IDFも0になります。そのため、文書を識別することはできません。
library(tidytext)
library(dplyr)
docs <- tibble::tibble(
document = c(rep('Python', 3), rep('R', 3), rep('Julia', 3)),
text = c(
'python pandas numpy scipy programming',
'machine learning scikit tensorflow keras',
'jupyter notebooks scripts debugging modules',
'ggplot2 dplyr tidyverse statistics vectors',
'shiny rmarkdown knitr cran bioconductor',
'linear models factors dataframes packages',
'julia multiple dispatch type system macros',
'package ecosystem flux diffeq parallel',
'scientific computing performance benchmarks'
)
)
top_terms <- docs |>
unnest_tokens(word, text) |>
count(document, word) |>
bind_tf_idf(word, document, n) |>
arrange(desc(tf_idf))
cat('Top distinctive terms per language:\n')
print(head(top_terms[, c('document', 'word', 'tf_idf')], 9))文書ごとの上位TF-IDF用語
group_by(document) |> slice_max(tf_idf, n = 5)を使うと、文書ごとに特徴の強い上位N個の用語を抽出できます。これはコーパスの強力な要約方法であり、各文書に特徴的な語彙が明確に現れます。
library(tidytext)
library(dplyr)
docs <- tibble::tibble(
document = c(rep('Cooking', 3), rep('Finance', 3), rep('Sports', 3)),
text = c(
'recipe ingredients oven bake flour butter',
'cooking temperature boil simmer saute',
'kitchen knife chopping herbs spices garnish',
'investment portfolio returns dividends stocks bonds',
'market equity risk hedge fund derivatives',
'inflation interest rate treasury balance sheet',
'goal tackle pass dribble goalkeeper penalty',
'tournament league championship trophy season',
'athlete training stamina sprint endurance'
)
)
top5 <- docs |>
unnest_tokens(word, text) |>
count(document, word) |>
bind_tf_idf(word, document, n) |>
group_by(document) |>
slice_max(tf_idf, n = 3) |>
ungroup()
print(top5[, c('document', 'word', 'tf_idf')])文書ごとのTF-IDFの可視化
文書ごとにファセット分けしたTF-IDFスコアの棒グラフを使うと、各文書に特徴的な語彙を一目で確認できます。facet_wrap(~document, scales = 'free_y')を使用すると、各パネルでそれぞれの上位用語を独立して表示できます。
library(tidytext)
library(dplyr)
library(ggplot2)
docs <- tibble::tibble(
document = c(rep('AI', 3), rep('DB', 3), rep('Web', 3)),
text = c(
'neural networks gradient backpropagation',
'deep learning transformer attention bert',
'reinforcement policy reward exploration',
'sql database indexes joins transactions',
'relational schema normalization queries',
'nosql mongodb redis cassandra document',
'html css javascript react dom',
'frontend api fetch async components',
'responsive flexbox grid webpack bundle'
)
)
plot_data <- docs |>
unnest_tokens(word, text) |>
count(document, word) |>
bind_tf_idf(word, document, n) |>
group_by(document) |>
slice_max(tf_idf, n = 4) |>
ungroup()
ggplot(plot_data, aes(reorder(word, tf_idf), tf_idf, fill = document)) +
geom_col(show.legend = FALSE) +
facet_wrap(~document, scales = 'free_y') +
coord_flip() +
labs(x = NULL, y = 'TF-IDF', title = 'Top TF-IDF Terms per Topic') +
theme_minimal()IDF: すべての文書に現れる単語
すべての文書に現れる単語は、IDF = log(N/N) = 0となるため、TF-IDFも0になります。これにより、ストップワードのリストを用意しなくても、コーパス全体に共通する単語の重みが自動的に下がります。ただし、非常に小さなコーパスでは、ストップワードの除去も有効です。
library(tidytext)
library(dplyr)
docs <- tibble::tibble(
document = c('A', 'B', 'C'),
text = c(
'data analysis statistics regression probability',
'data engineering pipelines etl transformation',
'data visualisation ggplot2 charts dashboards'
)
)
tfidf <- docs |>
unnest_tokens(word, text) |>
count(document, word) |>
bind_tf_idf(word, document, n)
# 'data' appears in all 3 docs: tf_idf should be 0
data_rows <- filter(tfidf, word == 'data')
cat('TF-IDF for "data" across documents:\n')
print(data_rows[, c('document', 'word', 'idf', 'tf_idf')])2つの文書の比較
TF-IDFを使うと文書を簡単に比較できます。一方の文書でTF-IDFが高く、もう一方では低いか0である用語を探すことで、各文書を特徴付ける要素を理解できます。TF-IDFのテーブルをwordで内部結合し、スコアを比較します。
library(tidytext)
library(dplyr)
docs <- tibble::tibble(
document = c(rep('Doc1', 3), rep('Doc2', 3)),
text = c(
'bayesian statistics prior posterior mcmc',
'markov chain monte carlo sampling',
'probability distributions conjugate inference',
'convolutional neural network image classification',
'pooling activation relu softmax batch',
'convolution filter feature map stride padding'
)
)
tfidf <- docs |>
unnest_tokens(word, text) |>
count(document, word) |>
bind_tf_idf(word, document, n)
# Top 3 unique terms per document
tfidf |>
group_by(document) |>
slice_max(tf_idf, n = 3) |>
select(document, word, tf_idf) |>
print()ジェーン・オースティンの小説でTF-IDFを使う
janeaustenrパッケージには、オースティンの6作品の全文が収録されています。これはTF-IDFの古典的なベンチマークであり、各小説に特徴的な語彙を特定できます。たとえば、"wentworth"という単語はPersuasionにほぼ固有です。
library(tidytext)
library(dplyr)
# Requires janeaustenr package
# library(janeaustenr)
# austen_books() returns: book, text
# Simulated mini-Austen corpus
mini_austen <- tibble::tibble(
book = c(rep('Sense', 3), rep('Pride', 3), rep('Emma', 3)),
text = c(
'elinor marianne dashwood willoughby colonel',
'edward ferrars barton cottage sister sense',
'brandon feelings attachment sensibility heart',
'darcy bennet bingley netherfield wickham',
'jane lizzy lydia longbourn pemberley',
'pride prejudice proposal marriage happiness',
'emma woodhouse knightley harriet weston',
'highbury match social governess niece',
'frank jane fairfax box hill picnic'
)
)
top <- mini_austen |>
unnest_tokens(word, text) |>
count(book, word) |>
bind_tf_idf(word, book, n) |>
group_by(book) |>
slice_max(tf_idf, n = 3) |>
select(book, word, tf_idf)
print(top)特徴量エンジニアリングのためのTF-IDF
TF-IDFスコアは、機械学習の分類器の特徴量として利用できます。cast_dtm()またはcast_sparse()を使って、tidy形式のTF-IDF出力を文書ターム行列に変換し、glmnet、xgboostなどの分類器に渡します。
library(tidytext)
library(dplyr)
docs <- tibble::tibble(
document = c(rep('Positive', 4), rep('Negative', 4)),
text = c(
'excellent product love recommend quality',
'amazing fast delivery five star perfect',
'great value money satisfied happy return',
'wonderful experience purchase outstanding best',
'terrible waste money broken arrived damaged',
'horrible quality slow delivery disappointed awful',
'poor value cheap plastic flimsy broken',
'worst experience refund needed useless junk'
)
)
# TF-IDF as features
tfidf_wide <- docs |>
unnest_tokens(word, text) |>
count(document, word) |>
bind_tf_idf(word, document, n) |>
cast_dtm(document, word, tf_idf)
cat('DTM dimensions:', dim(tfidf_wide), '\n')
cat('(rows=documents, cols=unique words)\n')限界と代替手法
TF-IDFには、単語を独立したものとして扱い、語順や文脈を無視すること、まれなスペルミスの影響を受けやすいことなどの限界があります。現代的な代替手法には、単語埋め込み(word2vec、GloVe)や文脈埋め込み(BERT)がありますが、TF-IDFは文書検索や分類のベースラインとして今でも優れています。
# TF-IDF strengths and weaknesses summary
criteria <- data.frame(
Criterion = c('Speed', 'Interpretability', 'Context', 'Word order',
'Rare words', 'Scalability'),
TF_IDF = c('Fast', 'High', 'None', 'Ignored',
'High IDF (inflated)', 'Excellent'),
BERT = c('Slow', 'Low', 'Rich', 'Captured',
'Handled', 'Moderate')
)
print(criteria, row.names = FALSE)確認問題
コーパス内のすべての文書にある単語が出現しています。この単語のTF-IDFスコアはいくつになりますか。
まとめ: TF-IDF分析
主なポイント:
- TF-IDF = 用語頻度 × 逆文書頻度であり、スコアが高いほど特徴的な単語です
- 手順は、
unnest_tokens()→count(document, word)→bind_tf_idf(word, document, n)です bind_tf_idf()はtf、idf、tf_idfの列を追加しますarrange(desc(tf_idf))/slice_max(tf_idf, n = 5)で文書ごとの上位用語を確認できます- すべての文書に含まれる単語は、IDF = 0、TF-IDF = 0になります
cast_dtm(document, word, tf_idf)で、機械学習用の文書ターム行列に変換できます- TF-IDFの結果には、ファセット分けした棒グラフが標準的な可視化方法です
library(tidytext)
library(dplyr)
# Minimal TF-IDF pipeline
tibble::tibble(
doc = c('A', 'A', 'B', 'B'),
text = c('neural networks deep', 'learning training', 'sql database query', 'joins indexes')
) |>
unnest_tokens(word, text) |>
count(doc, word) |>
bind_tf_idf(word, doc, n) |>
arrange(desc(tf_idf)) |>
print()AI チューターと学ぶ R — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 43
- レッスン
- 159
よくある質問
「TF-IDF と単語頻度分析」レッスンは無料ですか?
はい。「TF-IDF と単語頻度分析」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、R Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 R Academyコースには全4レッスンが含まれています。
「TF-IDF と単語頻度分析」で何を学びますか?
bind_tf_idf() を使って、文書間での単語の重要度をスコア化します。 ブラウザで直接実行するハンズオンコードでR Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
R Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのR Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「TF-IDF と単語頻度分析」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このR Academyレッスンでコードを書いて実行できますか?
はい。すべてのR Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- トークン化とストップワードの除去
- TF-IDF と単語頻度分析
- R での感情分析
- LDA によるトピックモデリング