Sentence Transformers 2.2 : 使用方法 : センテンス埋め込みの計算

Sentence Transformers 2.2 : センテンス埋め込みの計算 (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 11/23/2022 (v2.2.2)

* 本ページは、UKPLab/sentence-transformers の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

クラスキャット 人工知能 研究開発支援サービス

クラスキャット は人工知能・テレワークに関する各種サービスを提供しています。お気軽にご相談ください :

◆ 人工知能とビジネスをテーマに WEB セミナーを定期的に開催しています。スケジュール
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

  • 株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
  • sales-info@classcat.com  ;  Web: www.classcat.com  ;   ClassCatJP

 

Sentence Transformers 2.2 : センテンス埋め込みの計算

センテンス埋め込みを計算する基本的な関数はこのようなものです :

from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')

#Our sentences we like to encode
sentences = ['This framework generates embeddings for each input sentence',
    'Sentences are passed as a list of string.', 
    'The quick brown fox jumps over the lazy dog.']

#Sentences are encoded by calling model.encode()
embeddings = model.encode(sentences)

#Print the embeddings
for sentence, embedding in zip(sentences, embeddings):
    print("Sentence:", sentence)
    print("Embedding:", embedding)
    print("")

Note : センテンス埋め込みについて話してはいますが、より短いフレーズや複数のセンテンスを含む長いテキストに対しても使用できます。パラグラフに対する埋め込みに関するノートについては Input Sequence Length (入力シークエンス長) のセクションをご覧ください。

最初に、sentence-transformer モデルをロードします :

from sentence_transformers import SentenceTransformer
model = SentenceTransformer('model_name_or_path')

事前訓練済みモデルを指定するか、フォルダから sentence-transformer モデルをロードするために貴方のディスク上のパスを渡すこともできます。

利用可能であれば、モデルは自動的に GPU 上で実行されます。このようにモデルに対してデバイスを指定できます :

model = SentenceTransformer('model_name_or_path', device='cuda')

With device any pytorch device (like CPU, cuda, cuda:0 etc.)

センテンス/テキストのセットをエンコードする関連メソッドは model.encode() です。以下で、このメソッドが受け取るパラメータを見つけることができます。幾つかの関連パラメータは batch_size (GPU に依存して最適なバッチサイズは異なります)、convert_to_numpy (numpy 行列を返します) そして convert_to_tensor (pytorch テンソルを返します) です。

class sentence_transformers.SentenceTransformer(
  model_name_or_path: Optional[str] = None,
  modules: Optional[Iterable[torch.nn.modules.module.Module]] = None,
  device: Optional[str] = None,
  cache_folder: Optional[str] = None,
  use_auth_token: Optional[Union[bool, str]] = None
)

SentenceTransformer をロードまたは作成します、それはセンテンス/テキストを埋め込みにマップするために使用できます。

パラメータ

  • model_name_or_path – それがディスク上のファイルパスであれば、モデルをパスからロードします。それがパスでない場合、最初に事前訓練済み SentenceTransformer モデルをダウンロードしようとします。それが失敗すれば、その名前で Huggingface モデル・レポジトリからモデルを構築しようとします。
  • modules – このパラメータはカスタム SentenceTransformer モデルをゼロから作成するために使用できます。
  • device – 計算に使用されるべき (‘cuda’ / ‘cpu’ のような) デバイスです。None であれば、GPU が利用できるか確認します。
  • cache_folder – モデルをストアするパス。
  • use_auth_token – プライベート・モデルをダウンロードするための HuggingFace 認証トークン。

內部モジュール状態を初期化し、nn.Module と ScriptModule の両方に共有されます。

 

encode(
  sentences: Union[str, List[str]],
  batch_size: int = 32,
  show_progress_bar: Optional[bool] = None,
  output_value: str = 'sentence_embedding',
  convert_to_numpy: bool = True,
  convert_to_tensor: bool = False
  device: Optional[str] = None,
  normalize_embeddings: bool = False
)→ Union[List[torch.Tensor], numpy.ndarray, torch.Tensor]

センテンス埋め込みを計算します。

パラメータ

  • sentences – 埋め込みセンテンス (群)
  • batch_size – 計算に使用されるバッチサイズ
  • show_progress_bar – センテンスをエンコードするとき進捗バーを出力します。
  • output_value – センテンス埋め込みを取得する、sentence_embedding がデフォルトです。wordpiece トークン埋め込みを取得する token_embeddings に設定可能です。None に設定すると、すべての出力値を取得します。
  • convert_to_numpy – true の場合、出力は numpy ベクトルのリストです。そうでない場合、pytorch テンソルのリストです。
  • convert_to_tensor – true の場合、戻り値として一つの巨大なテンソルを取得します。convert_to_numpy の設定を上書きします。
  • device – 計算にどの torch.device を使用するか。
  • normalize_embeddings – true の場合、返されるベクトルは長さ 1 です。この場合、コサイン類似度の代わりに、より高速なドット積 (util.dot_score) を使用できます。

戻り値
デフォルトでは、テンソルのリストが返されます。convert_to_tensor の場合、スタックされたテンソルが返されます。convert_to_numpy の場合、numpy 行列が返されます。

 

入力シークエンス長

BERT / RoBERTa / DistilBERT 等のような Transformer モデルでは、ランタイムとメモリ要件は入力長に対して二次関数的に増大します。これは transformer を特定の長さの入力に制限します。BERT & Co. に対する共通の値は 512 単語ピースで、これは (英語の場合) およそ 300-400 単語に相当します。これより長いテキストは最初の x 単語ピースに切り捨てられます。

デフォルトでは、提供されるメソッドは 128 単語ピースの制限を使用し、より長い入力は切り捨てられます。このようにして最大シークエンス長を取得して設定できます :

from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')

print("Max Sequence Length:", model.max_seq_length)

#Change the length to 200
model.max_seq_length = 200

print("Max Sequence Length:", model.max_seq_length)

Note : 長さを個々の transformer モデルにより最大にサポートされる長さよりも増やすことはできません。モデルがより短いテキストで訓練された場合、長いテキストに対する表現はそれほど良くはないかもしれないことにも注意してください。

 

埋め込みのストアとロード

最も簡単な方法は、事前計算された埋め込みをディスク上にストアしてディスクからそれをロードするために pickle を使用することです。これは、センテンスの巨大なセットをエンコードする必要がある場合に特に有用です。

from sentence_transformers import SentenceTransformer
import pickle

model = SentenceTransformer('all-MiniLM-L6-v2')
sentences = ['This framework generates embeddings for each input sentence',
    'Sentences are passed as a list of string.', 
    'The quick brown fox jumps over the lazy dog.']


embeddings = model.encode(sentences)

#Store sentences & embeddings on disc
with open('embeddings.pkl', "wb") as fOut:
    pickle.dump({'sentences': sentences, 'embeddings': embeddings}, fOut, protocol=pickle.HIGHEST_PROTOCOL)

#Load sentences & embeddings from disc
with open('embeddings.pkl', "rb") as fIn:
    stored_data = pickle.load(fIn)
    stored_sentences = stored_data['sentences']
    stored_embeddings = stored_data['embeddings']

 

マルチプロセス / マルチ GPU エンコーディング

入力テキストを 1 つ以上の GPU で (or CPU マシンの複数のプロセスで) エンコードすることができます。
例えば、computing_embeddings_mutli_gpu.py を参照してください。

関連メソッドは start_multi_process_pool() で、これはエンコードのために使用されるマルチプロセスを開始します。

SentenceTransformer.start_multi_process_pool(target_devices: Optional[List[str]] = None)

幾つかの、独立なプロセスでエンコーディングを処理するためにマルチプロセスを開始します。このメソッドは複数の GPU でエンコードしたい場合に勧められます。GPU 毎に 1 つのプロセスだけを開始することが勧められます。このメソッドは encode_multi_process とともに動作します。

パラメータ

  • target_devices – PyTorch ターゲットデバイス, e.g. cuda:0, cuda:1… None の場合、すべての利用可能な CUDA デバイスが使用されます。

戻り値

  • ターゲットプロセス、入力キューと出力キューを含む辞書を返します。

 

Transformers によるセンテンス埋め込み

私たちの事前訓練済みモデルの殆どは Huggingface.co/Transformers に基づき、また Huggingface のモデルレポジトリにホストされています。sentence-transformers のインストールなしにセンテンス埋め込みモデルを使用することも可能です。

from transformers import AutoTokenizer, AutoModel
import torch


#Mean Pooling - Take attention mask into account for correct averaging
def mean_pooling(model_output, attention_mask):
    token_embeddings = model_output[0] #First element of model_output contains all token embeddings
    input_mask_expanded = attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float()
    sum_embeddings = torch.sum(token_embeddings * input_mask_expanded, 1)
    sum_mask = torch.clamp(input_mask_expanded.sum(1), min=1e-9)
    return sum_embeddings / sum_mask



#Sentences we want sentence embeddings for
sentences = ['This framework generates embeddings for each input sentence',
             'Sentences are passed as a list of string.',
             'The quick brown fox jumps over the lazy dog.']

#Load AutoModel from huggingface model repository
tokenizer = AutoTokenizer.from_pretrained("sentence-transformers/all-MiniLM-L6-v2")
model = AutoModel.from_pretrained("sentence-transformers/all-MiniLM-L6-v2")

#Tokenize sentences
encoded_input = tokenizer(sentences, padding=True, truncation=True, max_length=128, return_tensors='pt')

#Compute token embeddings
with torch.no_grad():
    model_output = model(**encoded_input)

#Perform pooling. In this case, mean pooling
sentence_embeddings = mean_pooling(model_output, encoded_input['attention_mask'])

利用可能なモデルはここで見つけられます : https://huggingface.co/sentence-transformers

上の例では AutoModel (これは BERT モデルをロードします) の上に平均プーリングを追加しています。max-pooling (最大プーリング) を持ったり CLS トークンを使用するモデルもあります。このプーリングを正しく適用する方法は、sentence-transformers/bert-base-nli-max-tokens 及び /sentence-transformers/bert-base-nli-cls-token を見てください。

 

以上