2
3

テキストをエンベディングして得られる行列でのより詳細で精密な類似度測定計算。

Last updated at Posted at 2024-08-22

91871fe7-d00c-4737-b533-3c01a8eabe5b.png

ショートストーリー: 「コードの中の共鳴」

東京の高層ビルが立ち並ぶ夜の街で、彼の部屋には薄暗い光が差し込んでいた。画面に映し出されたコードと、幾つかの行列が交互に切り替わる中、主人公の田中は深く考え込んでいた。彼は東京の企業でプログラマーとして働いており、今日もまた一つの難題に直面していた。

田中はテキストのエンベディングを使って、文書の類似度を精密に測る方法を模索していた。彼の目の前には、テキストを行列として表現し、それぞれの行と列のコサイン類似度を計算するというアイディアがあった。それは単なる理論ではなく、彼が現実のデータで検証しようとしているものだった。

「行列として表現されたテキスト同士の類似度を、どれだけ詳細に測れるか?」彼は呟いた。コードを実行しながら、彼の頭には次々とアイディアが浮かんできた。行と列、両方のコサイン類似度を計算し、その合計をスコア化することで、テキストの微細な違いや共鳴を捉えようとしていた。

田中は机の上に散らばった書類を片付け、数ヶ月間の研究の集大成ともいえるプログラムを起動した。行列 A と行列 B の間で、列ベクトルと行ベクトルのコサイン類似度を計算し、その結果をマトリックスとして生成する。彼の計算結果が画面に表示されると、数値が行列の中で交錯し、テキストの類似度が視覚化された。

「このスコアが高いほど、テキストの質が似ているんだな。」彼の目は、プログラムの出力と、そこから読み取れるテキストの意味的な類似性に釘付けだった。

ある夜遅く、田中がスクリーンに向かっていると、突然電話が鳴った。画面の向こうには、彼の上司である佐藤が映っていた。「田中さん、どうですか?進捗は?」

田中は少し息を整えてから、興奮気味に答えた。「佐藤さん、この方法で類似度を計算することで、テキストの微細な違いまで捉えられるようになりました。行と列のコサイン類似度を組み合わせることで、非常に精密なスコアが得られるんです。」

佐藤は驚きとともにうなずいた。「それは素晴らしい。これで私たちのテキスト分析が一段と進化することでしょう。実際にデータを用いた解析結果を見せてください。」

田中はその晩、データを詳細に分析し、その結果をプレゼンテーションとしてまとめた。翌日、彼の成果はプロジェクトチーム全体に認められ、テキスト分析の精度が大幅に向上することとなった。彼のアイディアが現実のものとなり、プロジェクトの成功に貢献する瞬間を迎えた。

東京の街が朝日で輝く頃、田中は窓の外を見ながら微笑んだ。コードの中で共鳴するテキストの類似度が、彼にとっては単なる数字以上の意味を持っていた。彼は自分の努力が、テキストの質をより深く理解する手助けとなったことに満足感を覚えた。

テキストをエンベディングして得られる行列での類似度計算について、行と列それぞれでコサイン類似度を計算し、それを合算する方法は、より詳細で精密な類似度測定を実現するための有効な手法です。このアプローチの利点について詳しく説明します。

詳細な類似度測定の理由

行と列の独立した評価:

行ベクトルのコサイン類似度: テキスト内の異なる単語やフレーズが行として表現される場合、行ベクトル間のコサイン類似度を計算することで、テキストの文脈やトピックの類似性を捉えることができます。これは、テキストの異なる部分がどれだけ似ているかを測るのに役立ちます。
列ベクトルのコサイン類似度: 同様に、列ベクトル間のコサイン類似度を計算することで、テキスト全体のトピックやテーマの類似性を評価することができます。列ベクトルは通常、テキストの全体的な意味や重要な単語を表します。

細部まで反映する類似度スコア:

行と列の類似度を独立して評価し、その結果を合算することで、テキストの各部分(行)と全体(列)の両方での類似性を包括的に測定できます。この方法は、単なるフラットなベクトル比較よりも、テキスト内の微細な違いや類似点をより正確に捉えることができます。

文脈と意味の精密な比較:

特に複雑なテキストや長文の場合、行列の構造を利用して部分的な類似性と全体的な類似性を同時に評価することができます。これにより、テキストの意味やコンテキストに基づいたより精密な比較が可能になることが期待されます。

実行結果。

texts_A = ["素早い茶色のキツネが怠け者の犬を飛び越えます。"、"こんにちは世界!"]
texts_B = [
"素早い茶色のキツネが怠け者の犬を飛び越えます。"、
"こんにちは、惑星!"、
"素早い茶色のキツネはとても速いです。"、
"こんにちは、美しい世界!"、
"怠け者の犬がキツネを見ています。"
]

Similarity score between texts_A and texts_B[0]: 0.9064243078540631
Similarity score between texts_A and texts_B[1]: -102.43836623595263
Similarity score between texts_A and texts_B[2]: -27.34124449511474
Similarity score between texts_A and texts_B[3]: -102.3901140238317
Similarity score between texts_A and texts_B[4]: 52.18950883547341

import tensorflow as tf
import tensorflow_hub as hub
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

# テキストをエンベディングするための関数
def embed_text(texts, embed_model):
    embeddings = embed_model(texts)
    return embeddings

# テキストとモデルの準備
texts_A = ["The quick brown fox jumps over the lazy dog.", "Hello world!"]
texts_B = [
    "The fast brown fox leaps over the lazy dog.",
    "Greetings, planet!",
    "The quick brown fox is very fast.",
    "Hello, beautiful world!",
    "The lazy dog watches the fox."
]

# Universal Sentence Encoderモデルのロード
embed_model_url = "https://tfhub.dev/google/universal-sentence-encoder/4"
embed_model = hub.load(embed_model_url)

# テキストをエンベディング
embeddings_A = embed_text(texts_A, embed_model)

# テキスト長の不一致を解消するために、パディングまたはトリミングを行う
def align_and_pad(embeddings_A, embeddings_B):
    len_A = len(embeddings_A)
    len_B = len(embeddings_B)
    
    max_len = max(len_A, len_B)
    
    # パディングまたはトリミング
    padded_A = np.vstack([embeddings_A.numpy(), np.zeros((max_len - len_A, embeddings_A.shape[1]))]) if len_A < max_len else embeddings_A.numpy()[:max_len]
    padded_B = np.vstack([embeddings_B.numpy(), np.zeros((max_len - len_B, embeddings_B.shape[1]))]) if len_B < max_len else embeddings_B.numpy()[:max_len]
    
    return padded_A, padded_B

# 行と列のコサイン類似度を計算する関数
def calculate_combined_similarity_score(embeddings_A, embeddings_B):
    row_similarity_matrix = cosine_similarity(embeddings_A, embeddings_B)
    col_similarity_matrix = cosine_similarity(embeddings_A.T, embeddings_B.T)
    
    row_similarity_score = np.sum(row_similarity_matrix)
    col_similarity_score = np.sum(col_similarity_matrix)
    
    combined_score = row_similarity_score + col_similarity_score
    return combined_score

# 各テキストBとのスコアを計算してプリント
for i, text_b in enumerate(texts_B):
    embeddings_B = embed_text([text_b], embed_model)
    aligned_A, aligned_B = align_and_pad(embeddings_A, embeddings_B)
    combined_score = calculate_combined_similarity_score(aligned_A, aligned_B)
    print(f"Similarity score between texts_A and texts_B[{i}]: {combined_score}")

説明
ライブラリのインポート:

tensorflow と tensorflow_hub を使ってエンベディングモデルをロードし、sklearn.metrics.pairwise を使ってコサイン類似度を計算します。
エンベディング関数:

embed_text 関数で、テキストをエンベディングします。tensorflow_hub を使用して、指定したモデルでテキストをエンベディングします。
テキストとモデルの準備:

例として、2つのテキストリスト texts_A と texts_B を用意し、Universal Sentence Encoder モデルをロードしてエンベディングを計算します。
コサイン類似度の計算:

calculate_combined_similarity_score 関数で、行ベクトルと列ベクトルのコサイン類似度を計算し、その合計をスコアとして出力します。
結果の表示:

最後に、計算されたスコアをプリントします。
このコードは、テキストのエンベディングを行い、それぞれの行と列に対してコサイン類似度を計算することで、精密な類似度スコアを得ることができます。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3