「埋め込みモデルでコーパス内の意味関係を探索する」

「美容とファッションのエキスパートが魅力的で生き生きとした記事を執筆!」

最近、研究対象に自由形式のテキストの分析を含む興味を持つ他の学生や研究者と話をしました。残念ながら、書かれた自然言語の意味を把握することは、どのような手段においても容易な課題ではありません。もちろん、細かな読解はありますが、テキストデータをマクロアナリティカル/数量的な視点で見ることを理想的には望んでいます。また、ビッグデータの時代には、細かな読解はほとんど実行不可能です。

私の大好きな方法の1つは、トピックモデルを使用してコーパスの探索的データ分析を行うことであり、それについて複数の記事を書いています。最も痛みの少ない方法で。トピックモデルは素晴らしいですが、テキストのすべてのことに対して普遍的に最適な方法ではありません。

埋め込みとは、テキストデータの数値表現であり、テキストの意味的なクエリにおける標準的なアプローチとなっています。この記事では、埋め込みを使用してテキストデータをいくつかの方法で探索します。

単語の埋め込みを使用した概念間の関係の捕捉

単語の埋め込みモデルは、非教示的な方法で用語の潜在的なベクトル表現を学習する手法のセットです。自然言語から単語埋め込みを学習すると、埋め込み空間での意味的な関係のマップを取得することになります。

単語の埋め込みは通常、大規模なコーパスで訓練されるため、人間の言語の単語間の一般的な関係を捉えることができます。これは、特定のアプリケーションのためのモデルに言語に関する一般的な知識を注入するために有用です。これはまた、転移学習としても知られており、機械学習の注目のトピックです。

大規模なコーパスの一般的な知識を特定のモデルに転送する代わりに、より小規模なコーパスの意味的な特定の側面のマッピングを取得したい場合はどうすれば良いでしょうか?フォーラムからのコメントのコーパスがあるとしましょう。それらの中にどのような連想関係が見つかるかを探索したいです。

これを達成する方法の1つは、私たち自身が事前訓練されたものではなく、このコーパス上で埋め込みモデルをゼロからトレーニングすることです。この例では、コーパスとして20Newsgroupsデータセットを使用し、意味的な関係を探求します。

モデルをトレーニングする

さて、まず始めに単語の埋め込みモデルを使用しましょう。おそらくWord2Vecはおなじみかもしれません。それは研究や実践で静的な単語の埋め込みの使用を広めた方法です。一方、Stanfordの開発者たちによって開発されたGloVeは、ほとんどの状況ではより良い方法とされており、私の経験からも特に小規模なコーパスにおいてはより高品質な埋め込みを提供していることを示唆しています。残念ながら、GloVeはGensimに実装されていませんが、幸いにも私は元々のGloVeコードに完全に対応したGensim互換のインターフェースを作成しました。モデルのトレーニングにはこれを使用します。

Gensim、glovpy、scikit-learnをインストールし、20Newsgroupsとembedding-explorerを取得できるようにしましょう。

pip install glovpy gensim scikit-learn

まずデータセットをロードし、トークン化します。gensimの組み込みのトークナイザーを使用します。また、タスクには意味のある情報を持たないため、ストップワードをフィルタリングします。

from gensim.utils import tokenizefrom sklearn.datasets import fetch_20newsgroupsfrom sklearn.feature_extraction.text import ENGLISH_STOP_WORDSdef clean_tokenize(text: str) -> list[str]:    """テキストをトークン化し、ストップワードを削除する関数"""    tokens = tokenize(text, lower=True, deacc=True)    tokens = [token for token in tokens if token not in ENGLISH_STOP_WORDS]    return tokens# データセットのロードdataset = fetch_20newsgroups(    remove=("headers", "footers", "quotes"), categories=["sci.med"])newsgroups = dataset.data# データセットのトークン化tokenized_corpus = [clean_tokenize(text) for text in newsgroups]

これで、トークン化されたコーパス上で簡単にGloVeモデルをトレーニングすることができます。

from glovpy import GloVe# 単語の埋め込みのトレーニングmodel = GloVe(vector_size=25)model.train(tokenized_corpus)

既にこの単語の埋め込みモデルをクエリすることができます。例えば、「child」と最も関連性の高い10個の単語をチェックしてみましょう。

model.wv.most_similar("child")==============================+------------+----------+| age        | 0.849304 || consistent | 0.844267 || adult      | 0.805101 || range      | 0.800615 || year       | 0.798799 || hand       | 0.792965 || children   | 0.792113 || use        | 0.789804 || restraint  | 0.773764 || belt       | 0.77003  |+------------+----------+

調査して、可視化しましょう!

ただし、個々の単語と他の単語の関係を個別に調査するのはすぐに退屈になります。理想的には、関係を視覚化したり、ネットワークを取得したりしたいと思います。

幸いにも、私が開発したembedding-explorerパッケージがここで役立ちます。私たちはコンピュータ人文学でよく単語埋め込みモデルやそのモデル内の関係から構築された意味的ネットワークを利用しており、embedding-explorerはこれらをインタラクティブかつ視覚的な方法で探索するのに役立ちます。このパッケージには複数のインタラクティブなWebアプリケーションが含まれており、最初に「ネットワークエクスプローラ」を見てみましょう。

このアプリのアイデアは、埋め込みモデル内の概念が自然にネットワーク構造を形成するというものです。関連性の高い単語は強いつながりを持ち、他の単語にはつながりがない場合もあります。このアプリでは、指定した一連のシード単語と二段階の自由連想に基づいて概念グラフを構築することができます。

連想の各段階では、既存の単語に対して埋め込みモデル内の最も近い5つの単語を取り、それらを連想された単語との接続を持つネットワークに追加します。接続の強さは、埋め込み空間内の概念の余弦距離によって決定されます。このようなネットワークは、私や私の同僚が取り組んだ複数の研究プロジェクトで有用性が証明されています。

さあ、単語埋め込みモデル上でアプリを起動しましょう。

from embedding_explorer import show_network_explorervocabulary = model.wv.index_to_keyembeddings = model.wv.vectorsshow_network_explorer(vocabulary, embeddings=embeddings)

これにより、ブラウザウィンドウが開き、コーパス内の意味的な関係を自由に探索できます。以下は、私が「イエス」、「科学」、「宗教」の周りでどのようなネットワークが生じるかを見ているスクリーンショットです。

Exploring Semantic Relations in our GloVe Model

たとえば、オンライン上で人々がこれらの話題について話す方法は、宗教と科学が政治、社会、哲学を通じて関連していることを示唆しているようです。これは非常に合理的です。科学と宗教の中間に教育があることや、教育が明らかに科学とより関連していることを観察することも興味深いです。これを詳しく調べるのも興味深いかもしれません。

N-グラムのネットワークとセンテンストランスフォーマー

では、単語レベルの関係だけでなく、句や文の関係も見たい場合はどうでしょうか?

私の提案は、N-グラムを使用することです。N-グラムとは、テキスト内で互いに続くN個の用語のことです。たとえば、「I love my little cute dog」という文では、4-gramがあります。「I love my little」、「love my little cute」、「my little cute dog」となります。では、N-グラムの良い意味的表現をどのように学ぶのでしょうか?

理論的には、フレーズや文をトークンとして扱って、GloVeでもこれを行うことができますが、注意が必要です。Nの数が増えると、N-グラムのバリエーションが急激に増加し、特定のN-グラムが1回または2回しか出現しない場合があり、それらの良い表現を学ぶことができないかもしれません。

フレーズ内の単語の埋め込みの平均を取る方法はどうでしょうか?これはかなり有効ですが、問題は、異なる単語の重要性、文内の単語の順序、およびすべての文脈情報を完全に失ってしまうことです。

この問題への解決策は、センテンストランスフォーマーを使用することです。センテンストランスフォーマーは、テキストの文脈に敏感な表現を生成するディープニューラル言語モデルです。これらは数年間すべての他のアプローチを凌駕し、テキストの埋め込みの業界標準となっています。このようなモデルのトレーニングには大量のデータが必要ですが、幸いにもいくつかの優れた事前学習モデルを使用することができます。

N-グラムの抽出

まず、コーパスからN-グラムを抽出しましょう。私は4-gramを選びましたが、任意の数を選択できます。これにはscikit-learnのCountVectorizerを使用します。

from sklearn.feature_extraction.text import CountVectorizer# まず、コーパスに基づいてモデルをトレーニングします。4-gramのみを考慮しますが、現時点では最も頻度の高い4000個のみを採用します。これは自由に試行錯誤できます。feature_extractor = CountVectorizer(ngram_range=(4,4), max_features=4000)feature_extractor.fit(newsgroups)# 次に、ベクトライザーの語彙を取得します。four_grams = feature_extractor.get_feature_names_out()

埋め込みモデル

テキスト表現のために埋め込みモデルが必要です。先ほど述べたように、事前学習済みモデルを使用します。私は非常に安定しており、広く使用されているかつ比較的小さいall-MiniLM-L6-v2を選びました。そのため、おそらく個人のコンピュータでもスムーズに動作するでしょう。

また、scikit-learn互換の方法で文の変換器を使用するために、embetterという別のパッケージを使用します。

pip install embetter[text]

Pythonでモデルを読み込むことができます。

from embetter.text import SentenceEncoderencoder = SentenceEncoder("all-MiniLM-L6-v2")

探索!

次に、モデルとn-gramをembedding-explorerにロードします。

from embedding_explorer import show_network_explorershow_network_explorer(four_grams, vectorizer=encoder)

これにより、四つ組の語彙の代わりに任意の種を指定できるようになります。以下は、二つの文を入力し、その周囲の四つ組から構築されるネットワークの種類を確認したスクリーンショットです。

コーパス内のフレーズと文を探索する

また、どのフレーズが中間にあるかを観察することも興味深いです。ここでは、法律と歴史が宗教と科学の間のつながりのような役割を果たしているようです。

文書埋め込みによるコーパスレベルの意味構造の調査

これまで、単語やフレーズのレベルでコーパスを調べ、自然に発生する意味構造を見てきました。では、ドキュメントのレベルで何が起こるのか、どのドキュメントが互いに近くにあり、どのようなグループが現れるかについての情報を得たい場合はどうでしょうか。

この問題に対する自然な解決策の一つは、トピックモデリングです。もしあなたがまだそれを行っていない場合は、一度試してみることをお勧めします。この記事では、このタスクと関連のある他の概念の探求を行います。

文書の表現

前述のように、個々の文書をどのように表現するか、その意味的な内容を捉える必要があります。

より従来的な機械学習の方法では、一般的には単語の袋表現やDoc2Vecモデルを使用します。これらも良い選択肢です(試してみる価値があります)が、再び、テキストの文脈理解が欠如しているという問題があります。私たちのコーパスのテキストはあまり長くないため、文の埋め込みには引き続き文の変換器を使用できます。フレーズと同じ埋め込みモデルを使用して続けましょう。

プロジェクションとクラスタリング

ドキュメントの意味表現を探索するための自然な方法は、それらを低次元空間(通常は2次元)に射影し、射影を使用してドキュメントを可視化することです。また、クラスタリングアプローチを使用して、どのようなドキュメントがグループ化されるかを確認することもできます。

これは非常に素晴らしいですが、射影、次元削減、およびクラスタリングアプローチの領域は非常に広範であり、常に「他の方法を使用した場合、これは大幅に異なって見えるのでしょうか?」と考え続けることがありました。この問題に対処するために、embedding-explorerに別のアプリを追加しました。このアプリを使用すると、さまざまな方法で得られるさまざまな種類の視覚化結果を自由に素早く試すことができます。

以下は、私たちのワークフローです。1. 進行する前に、埋め込みの次元を削減するかどうかを決める必要があります。次元削減法から選択するか、または無効にすることができます。2. 埋め込みを2D空間に射影して可視化します。3. 埋め込みをクラスタリングして、どのような種類のドキュメントがグループ化されるかを確認するかもしれません。

embedding-explorerでのクラスタリングとプロジェクションのワークフロー

これを行う際は、(テキストの内容、タイトルなど)ドキュメントに関する外部情報も知る必要があります。そうでないと、私たちには解釈するための情報があまりありません。

次に、次の情報を含む列を持つデータフレームを作成しましょう。1. 各ドキュメントの最初の400文字、テキストの内容を把握できるようにします。2. テキストの長さ、可視化で長いテキストと短いテキストがわかるようにします。3. データセットから来たグループ。

import pandas as pdimport numpy as np# 文字数でのテキストの長さを抽出.lengths = [len(text) for text in corpus]# 各テキストの最初の400文字を抽出.text_starts = [text[:400] for text in corpus]# 各テキストが属するグループを抽出# Sklearnはラベルを整数で返しますので、実際のテキストのラベルにマップしなければなりません。group_labels = np.array(dataset.target_names)[dataset.target]# 使用可能なメタデータでデータフレームを作成します。metadata = pd.DataFrame(dict(length=lengths, text=text_starts, group=group_labels))

次に、メタデータを伝えながらアプリケーションを起動し、ドキュメントに関する情報をホバーして表示できるようにします。

from embedding_explorer import show_clusteringshow_clustering(  newsgroups,  vectorizer=encoder,  metadata=metadata,  hover_name="group", # ホバーボックスのタイトルはグループになります。  hover_data=["text", "length"] # また、これらも表示したいです。)

アプリが起動すると、最初にこの画面が表示されます:

クラスタリングアプリのオプション

クラスタリングを実行した後、クラスタごとに着色されたすべてのドキュメントのマップを表示することができます。ドキュメントのメタデータについてホバーすれば、詳細を確認できます…

クラスタリングアプリのスクリーンショット

さらに、下部ではポイントの色、ラベル、サイズの設定も選択できます。

ドキュメントサイズのクラスタ

まとめ

テキストデータの探索的分析は難しいですが、最新の機械学習技術を使用したインタラクティブな調査についていくつかのアプローチを見てきました。本記事およびembedding-explorer Pythonパッケージが将来の研究や仕事に役立つことを願っています。

平和を ✌️

(本記事のすべての画像はembedding-explorerのドキュメンテーションから取得しました。それらは著者によって作成されました。)

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more