BERTopic: 高性能トピックモデリングの概要

近年、大量のテキストデータから有益な情報を抽出するために、トピックモデルが注目されています。トピックモデルは、文書集合に潜在するテーマ(トピック)を発見するための強力なツールであり、自然言語処理、情報検索、テキストマイニングなど、様々な分野で応用されています。
しかし、従来のトピックモデルには、単語の文脈を考慮できない、計算コストが高い、動的なトピックの変化に対応できないといった課題がありました。そこで登場したのが、「BERTopic」です。
BERTopicは、Transformerベースの言語モデルとクラスベースのTF-IDFを組み合わせることで、これらの課題を克服し、高精度かつ柔軟なトピックモデリングを実現します。本記事では、BERTopicの基本的な概念、技術的な詳細、実装方法、応用例について解説します。
はじめに
近年、テキストデータから潜在的なテーマを発見するトピックモデルは、テキストに隠された物語や共通の話題を明らかにする強力なツールとして注目されています。従来のトピックモデル、例えばLatent Dirichlet Allocation(LDA)やNon-Negative Matrix Factorization(NMF)は、文書を単語の集合(bag-of-words)として扱い、文書内の単語のセマンティックな関係性を無視していました。
このような背景の中、BERTopicは、Transformerベースの言語モデルを用いて文書をベクトル化し、クラスタリングとクラスベースのTF-IDFを組み合わせることで、より高精度で一貫性のあるトピック表現を可能にしました。
BERTopicは、従来のトピックモデルが抱える課題を克服し、エンジニアリングにとって以下のようなメリットをもたらします。
- 情報整理: 大量のテキストデータから重要なトピックを抽出し、情報を効率的に整理できます。
- トレンド把握: トピックの経時的な変化を分析することで、トレンドを把握し、迅速な意思決定を支援します。
- 顧客理解: 顧客のレビューやフィードバックからトピックを抽出し、顧客のニーズや不満を理解することで、製品やサービスの改善に役立てます。
BERTopicは、高精度かつ柔軟なトピック分析を通じて、テキストデータの価値を最大限に引き出すことを可能にする、強力なツールです。
BERTopicの概要
BERTopicは、クラスタリング技術とクラスベースのTF-IDFを利用して、一貫性のあるトピック表現を生成するトピックモデルです。BERTopicは、従来のトピックモデルとは異なり、以下の3つの主要なステップで構成されています。
- 文書埋め込み(Document embeddings)
- 文書クラスタリング(Document clustering)
- トピック表現(Topic Representation)

文書埋め込み
最初のステップでは、Sentence-BERT(SBERT)フレームワークを使用して、文書をベクトル空間内の表現に変換します。SBERTは、Transformerベースの事前学習済み言語モデルを利用して、文や段落を密なベクトル表現に変換する手法であり、様々な文埋め込みタスクで最先端の性能を発揮します。
BERTopicでは、同じトピックを含む文書は意味的に類似していると仮定します。SBERTを用いることで、文書の意味的な情報を捉え、類似した文書をベクトル空間上で近い位置に配置することが可能になります。
重要な点として、これらの埋め込みは、意味的に類似した文書をクラスタリングするために使用され、トピックの生成には直接使用されません。意味的類似性に基づいてファインチューニングされた言語モデルであれば、他の埋め込み手法も使用できます。したがって、新しい、より優れた言語モデルが開発されるにつれて、BERTopicのクラスタリングの品質は向上すると考えられます。
文書クラスタリング
次に、埋め込みの次元を削減してから、意味的に類似する文書のクラスタを作成し、それぞれのクラスタが個別のトピックを表すようにします。
データが高次元になるにつれて、最近傍のデータ点までの距離が最遠のデータ点までの距離に近づくことが示されています。その結果、高次元空間では、空間的局所性の概念が不明確になり、距離尺度がほとんど変わらなくなります。
このような次元の呪いを克服するために、UMAP(Uniform Manifold Approximation and Projection)を使用して、埋め込みの次元を削減します。UMAPは、高次元データのローカルおよびグローバルな特徴をより多く保持することが示されています。また、埋め込みの次元に計算上の制限がないため、異なる次元空間を持つ言語モデルで使用できます。
次元削減された埋め込みは、HDBSCAN(Hierarchical Density-Based Spatial Clustering of Applications with Noise)アルゴリズムを用いてクラスタリングされます。HDBSCANは、DBSCANを階層的なクラスタリングアルゴリズムに変換することで、密度の異なるクラスタを検出する手法です。HDBSCANは、ソフトクラスタリングアプローチを使用してクラスタをモデル化し、ノイズを外れ値としてモデル化できます。これにより、無関係な文書がクラスタに割り当てられるのを防ぎ、トピック表現を改善することが期待されます。
トピック表現
各クラスタには1つのトピックが割り当てられ、トピック表現は各クラスタ内の文書に基づいてモデル化されます。各トピックについて、そのクラスタ-単語分布に基づいて、あるトピックが別のトピックとどのように異なるかを知りたいと考えます。この目的のために、TF-IDFを修正して、用語のトピックに対する重要度を表現できるようにします。
従来のTF-IDF手順は、term frequency(単語頻度)とinverse document frequency(逆文書頻度)の2つの統計量を組み合わせたものです。
- 単語頻度(term frequency): 文書dにおける用語tの頻度をモデル化します。
- 逆文書頻度(inverse document frequency): 用語が文書に提供する情報の量を測定し、コーパスN内の文書数に用語tを含む文書の総数を割った値の対数をとることによって計算されます。
この手順を文書のクラスタに一般化します。まず、クラスタ内のすべての文書を連結することにより、クラスタ内のすべての文書を単一の文書として扱います。次に、文書をクラスタに変換することにより、この表現を考慮するようにTF-IDFを調整します。
このために、inverse document frequency(逆文書頻度)をinverse class frequency(逆クラス頻度)に置き換えて、用語がクラスに提供する情報の量を測定します。これは、クラスあたりの単語の平均数Aを、すべてのクラスにおける用語tの頻度で割った値の対数をとることによって計算されます。正の値のみを出力するために、対数内の除算に1を加えます。
したがって、このクラスベースのTF-IDF手順は、個々の文書ではなく、クラスタ内の単語の重要度をモデル化します。これにより、文書の各クラスタに対してトピック-単語分布を生成できます。
最後に、最も一般的でないトピックのc-TF-IDF表現を最も類似したトピックと反復的にマージすることにより、トピックの数をユーザー指定の値に減らすことができます。
技術的なメリットと課題
- メリット
- 柔軟性:SBERT、Doc2Vecなどの様々な言語モデルに対応可能であり、GPUがない環境でも利用できます。
- 精度:従来のモデルよりも高いトピック一貫性(coherence)と多様性(diversity)を実現します。
- 動的トピックモデリング:時間の経過に伴うトピックの変化を分析できます。
- 課題
- 計算コスト:特にGPUがない環境では、文書埋め込みに時間がかかる可能性があります。
- 文書の多重トピック性:1つの文書が複数のトピックを持つ場合に、その情報を十分に捉えられない可能性があります。
- 課題解決へのアプローチ:
- 高速化:MiniLMなどの軽量な言語モデルを使用することで、計算コストを削減します。
- 多重トピック性:HDBSCANの確率行列を代理指標として使用し、文書内のトピック分布を推定します。

BERTopicを試してみる
BERTopicには、Pythonで利用できるパッケージがあるので、まずはpipを利用してインストールします。
# PyPIからインストール
$ pip install bertopic
# GitHubからインストール(今回はこっちを使用)
$ pip install git+https://github.com/MaartenGr/BERTopic
# 以降のお試して LiteLLM も利用しています。
$ pip install litellm
次に、使用するデータセットを準備します。今回は、テキスト分類などで使用されるオープンデータである 20 Newsgroups を使用します。
from sklearn.datasets import fetch_20newsgroups docs = fetch_20newsgroups(subset='all', remove=('headers', 'footers', 'quotes'))['data'] print(docs[0])
I am sure some bashers of Pens fans are pretty confused about the lack
of any kind of posts about the recent Pens massacre of the Devils. Actually,
I am bit puzzled too and a bit relieved. However, I am going to put an end
to non-PIttsburghers' relief with a bit of praise for the Pens. Man, they
are killing those Devils worse than I thought. Jagr just showed you why
he is much better than his regular season stats. He is also a lot
fo fun to watch in the playoffs. Bowman should let JAgr have a lot of
fun in the next couple of games since the Pens are going to beat the pulp out of Jersey anyway. I was very disappointed not to see the Islanders lose the final
regular season game. PENS RULE!!!
BERTopicの基本的な使い方(学習方法)は、次のようになります。各パラメータについては、コード中のコメントを参考にしていただくか、公式のドキュメントを参照してください。
from bertopic import BERTopic topic_model = BERTopic( language="english", # ドキュメントで使用される主な言語。デフォルトのsentence-transformersモデルは"all-MiniLM-L6-v2"。 top_n_words=10, # トピックごとに抽出する単語数。多すぎるとトピック埋め込みに悪影響を与える可能性あり。 n_gram_range=(1, 1), # CountVectorizerのn-gram範囲。1から3の間の値を推奨。 min_topic_size=10, # トピックの最小サイズ。値を大きくするとクラスタ/トピック数が減少。 nr_topics=20, # トピック数を指定すると、初期トピック数が指定された値に削減される。 low_memory=False, # UMAPの低メモリモードをTrueに設定し、メモリ使用量を削減。UMAPを使用する場合のみ適用。 calculate_probabilities=False, # ドキュメントごとの割り当てられたトピックの確率ではなく、すべてのトピックの確率を計算。 seed_topic_list=None, # 収束するためのトピックごとのシード単語のリスト。 zeroshot_topic_list=None, # ゼロショット分類に使用するトピック名のリスト。 zeroshot_min_similarity=0.7, # ゼロショットトピックとドキュメントの割り当ての最小類似度。 embedding_model=None, # カスタム埋め込みモデルを指定。sentence-transformers、Flair、Spacyなどをサポート。 umap_model=None, # UMAPモデルを明示的に指定できる。 hdbscan_model=None, # デフォルトのhdbscan.HDBSCANモデル以外を指定できる。 vectorizer_model=None, # デフォルトの代わりにカスタムCountVectorizerを指定できる。 ctfidf_model=None, # デフォルトの代わりにカスタムClassTfidfTransformerを指定できる。 representation_model=None, # c-TF-IDFで計算されたトピック表現を微調整するモデルを使用。bertopic.representationのモデルをサポート。 verbose=True, # ログ出力の有無。 ) _topics, _probs = topic_model.fit_transform(docs)
今回は次のようにして、Sentence Transformerと表現学習モデル(Representation Model)、そしてクラスタリングのモデルを明示的に指定します。
from bertopic.representation import LiteLLM from sentence_transformers import SentenceTransformer from sklearn.cluster import KMeans # Use local model representation_model = LiteLLM( model="ollama/deepseek-r1", generator_kwargs={"api_base": "http://localhost:11434"} ) topic_model = BERTopic( language="english", top_n_words=10, n_gram_range=(1, 4), min_topic_size=10, nr_topics=40, low_memory=False, calculate_probabilities=True, seed_topic_list=None, zeroshot_topic_list=None, zeroshot_min_similarity=0.7, embedding_model=SentenceTransformer("all-MiniLM-L12-v2"), umap_model=None, hdbscan_model=KMeans(n_clusters=30), vectorizer_model=None, ctfidf_model=None, representation_model=representation_model, verbose=True, ) _topics, _probs = topic_model.fit_transform(docs)
では、モデルの学習を終えたら、学習済みモデルからトピック情報を確認してみましょう
# トピック情報を確認 topic_model.get_topic_info()

次のようにして、指定したトピックIDについて確認することもできます。今回は、ローカルで動かしているDeepSeek-R1がトピックモデリングと相性が悪いのか、長文が出力されています(内部で使用しているプロンプトが悪いのかもしれません)。
# 明示的にトピックIDを指定して確認することができる topic = topic_model.get_topic(0) print(topic[0][0])
<think>
Okay, I'm trying to help this user extract a short topic label from their query. Let me look at what's provided.
First, there are two documents mentioned. One is a co-authored report from the Gun Owners Action League. It describes an event they had in a statehouse courtyard with about 40 people attending. The second document is an open letter by Dr. Paul H. Blackman for the NRA, discussing the Second Amendment's meaning regarding the militia clause.
The keywords given are: of, to, and, in, that, gun, is, you, it, for, or, of, the, be, not, by, are, this, as, on, guns, they, have, if, with, people, in, the, was, would, but.
I need to create a short topic label based on these documents and keywords. The report talks about an event related to guns and gun owners, while Blackman's letter discusses legal aspects of the Second Amendment concerning militias.
Looking at the keywords, "gun" appears multiple times, as does "Second Amendment." Also, terms like "militia," "right," and "people" are present. So the topic seems to revolve around discussions about guns, particularly focusing on rights and legal aspects related to the Second Amendment and militia groups.
Putting this together, a suitable label could be something that combines gun rights with the Second Amendment's implications regarding militias.
</think>
Gun Rights and the Second Amendment
また、次のようにすることで、トピック情報を可視化することができます。
# トピック情報の可視化 topic_model.visualize_topics()

また、階層型クラスタリングの結果も可視化できるようです。
# クラスタリングの結果 topic_model.visualize_hierarchy()

以上のように、BRETopic自体は簡単に使用することができます。今回は、簡単な使い方だけの紹介でしたが、詳しい内容については、公式ドキュメントやGitHubの実装を確認してください。また、日本語ドキュメントの埋め込みは、デフォルトで設定されているSentense Transfomerのモデルでも可能ですが、明示的に他のモデルを指定してしたい場合は、Sentense Transformerの事前学習済みモデルを確認してください。
おわりに
BERTopicは、クラスタリングとクラスベースTF-IDFを組み合わせた新しいトピックモデルであり、テキストデータから潜在的なトピックを高精度に抽出する強力なツールです。
本稿では、BERTopicの概要、主要なステップ(文書埋め込み、文書クラスタリング、トピック表現)、技術的なメリットと課題について解説しました。BERTopicは、SBERTなどの最新の言語モデルを活用することで、従来のトピックモデルが抱えるセマンティックな関係性の欠如という課題を克服し、一貫性と多様性に優れたトピックを生成します。
BERTopicの柔軟性は、多様な言語モデルに対応できる点にも現れており、GPUがない環境でもDoc2Vecなどの代替モデルを利用できます。また、動的トピックモデリングにも対応しており、時間の経過に伴うトピックの変化を分析することで、トレンドや社会の変化を捉えることが可能です。
BERTopicは、テキストデータ分析の可能性を広げ、ビジネス、研究、教育など、様々な分野での活用が期待されます。
More Information
- arXiv:2203.05794, Maarten Grootendorst, 「BERTopic: Neural topic modeling with a class-based TF-IDF procedure」, https://arxiv.org/abs/2203.05794