axinc-ai / ailia-models

The collection of pre-trained, state-of-the-art AI models for ailia SDK
2.04k stars 325 forks source link

ADD cross-encoder-mmarco-mMiniLMv2-L12-H384-v1 #1444

Closed kyakuno closed 6 months ago

kyakuno commented 7 months ago

マルチリンガルreranker https://huggingface.co/corrius/cross-encoder-mmarco-mMiniLMv2-L12-H384-v1 Apache

kyakuno commented 6 months ago

xlmrobertaなのでtokenizerはそのまま使えそう。

kyakuno commented 6 months ago

オリジナルのモデルが消えた話 https://github.com/UKPLab/sentence-transformers/issues/2306 https://www.reddit.com/r/MachineLearning/comments/1286n6w/d_multilingual_retrieve_rerank_models/

kyakuno commented 6 months ago

使用方法は下記がわかりやすい。 https://huggingface.co/jeffwan/mmarco-mMiniLMv2-L12-H384-v1

kyakuno commented 6 months ago

大元のmultilingual marcoは下記みたい。 https://github.com/unicamp-dl/mMARCO

kyakuno commented 6 months ago

モデル。 https://huggingface.co/unicamp-dl/mMiniLM-L6-v2-mmarco-v2

kyakuno commented 6 months ago

このモデルは3年前のもので、これを、cross encoderアーキテクチャにしたのが最新のモデルみたい。 englishだけのma marcoのものは下記にモデルがある。 https://www.sbert.net/docs/pretrained-models/ce-msmarco.html

kyakuno commented 6 months ago

marco : minilm -> crossencoder mmarco : minilm -> crossencoder という流れ。

kyakuno commented 6 months ago

とりあえず、このissueの先頭のmirrorされたモデルをエクスポートすれば良さそう。

kyakuno commented 6 months ago

推論コードの例。

from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch

model_name = "corrius/cross-encoder-mmarco-mMiniLMv2-L12-H384-v1"
#model_name = "jeffwan/mmarco-mMiniLMv2-L12-H384-v1"

model = AutoModelForSequenceClassification.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)

features_en = tokenizer(['How many people live in Berlin?', 'How many people live in Berlin?'], ['Berlin has a population of 3,520,031 registered inhabitants in an area of 891.82 square kilometers.', 'New York City is famous for the Metropolitan Museum of Art.'],  padding=True, truncation=True, return_tensors="pt")
features_ja = tokenizer(['ベルリンには何人が住んでいますか?', 'ベルリンには何人が住んでいますか?'], ['ベルリンの人口は891.82平方キロメートルの地域に登録された住民が3,520,031人います。', 'ニューヨーク市はメトロポリタン美術館で有名です。'],  padding=True, truncation=True, return_tensors="pt")

model.eval()
with torch.no_grad():
    scores_en = model(**features_en).logits
    print(scores_en)
    scores_ja = model(**features_ja).logits
    print(scores_ja)
kyakuno commented 6 months ago

corrius/cross-encoder-mmarco-mMiniLMv2-L12-H384-v1とjeffwan/mmarco-mMiniLMv2-L12-H384-v1は同じモデルみたい。

#corrius/cross-encoder-mmarco-mMiniLMv2-L12-H384-v1
#tensor([[10.7615],
#        [-8.1277]])
#tensor([[ 9.3747],
#        [-6.4083]])

#jeffwan/mmarco-mMiniLMv2-L12-H384-v1
#tensor([[10.7615],
#        [-8.1277]])
#tensor([[ 9.3747],
#        [-6.4083]])
kyakuno commented 6 months ago

ONNXへの変換

pip3 install optimum
optimum-cli export onnx --model jeffwan/mmarco-mMiniLMv2-L12-H384-v1 mmarco-mMiniLMv2-L12-H384-v1.onnx
kyakuno commented 6 months ago

変換したONNXは470.8MB。

kyakuno commented 6 months ago

推論コード

from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch

model_name = "jeffwan/mmarco-mMiniLMv2-L12-H384-v1"

model = AutoModelForSequenceClassification.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)

features_en = tokenizer(['How many people live in Berlin?', 'How many people live in Berlin?'], ['Berlin has a population of 3,520,031 registered inhabitants in an area of 891.82 square kilometers.', 'New York City is famous for the Metropolitan Museum of Art.'],  padding=True, truncation=True, return_tensors="pt")
features_ja = tokenizer(['ベルリンには何人が住んでいますか?', 'ベルリンには何人が住んでいますか?'], ['ベルリンの人口は891.82平方キロメートルの地域に登録された住民が3,520,031人います。', 'ニューヨーク市はメトロポリタン美術館で有名です。'],  padding=True, truncation=True, return_tensors="pt")

import ailia
net = ailia.Net(weight = "mmarco-mMiniLMv2-L12-H384-v1.onnx/model.onnx")
print(features_en)
score_en = net.run([features_en["input_ids"].numpy(), features_en["attention_mask"].numpy()])
print(score_en)
print(features_ja)
score_ja = net.run([features_ja["input_ids"].numpy(), features_ja["attention_mask"].numpy()])
print(score_ja)
kyakuno commented 6 months ago

出力はtorchと一致。

[array([[10.761542],
       [-8.127746]], dtype=float32)]
[array([[ 9.374646],
       [-6.408309]], dtype=float32)]
kyakuno commented 6 months ago

期待するtoken

[     0,      6, 106876,  67540,   2880,   4931,  19758,   6111, 206926,
           1894,     32,      2,      2,      6, 106876,  67540,    154,  24008,
            342,  18949, 119044,    304, 158580, 189402, 219137,    154,  34604,
         160450,   8346, 159616,    281,  92714,    304,  63527,   5016,    487,
          12219,     30,      2]
kyakuno commented 6 months ago

e5と同じtokenizerの出力。

tokenizer = AutoTokenizer.from_pretrained('sentence-transformers/paraphrase-multilingual-mpnet-base-v2')
inputs = tokenizer('ベルリンには何人が住んでいますか?', padding=True, truncation=True, return_tensors='np')
print(inputs)
inputs = tokenizer('ベルリンの人口は891.82平方キロメートルの地域に登録された住民が3,520,031人います。', padding=True, truncation=True, return_tensors='np')
print(inputs)
query

[     0,      6, 106876,  67540,   2880,   4931,  19758,   6111,
        206926,   1894,     32,      2]

contents

[     0,      6, 106876,  67540,    154,  24008,    342,  18949,
        119044,    304, 158580, 189402, 219137,    154,  34604, 160450,
          8346, 159616,    281,  92714,    304,  63527,   5016,    487,
         12219,     30,      2]
kyakuno commented 6 months ago

期待値をデコードすると、接続時のになるので、queryとcontentsを結合し、contentsの先頭の0を2に置き換えれば良い。

print(tokenizer.decode([     0,      6, 106876,  67540,   2880,   4931,  19758,   6111, 206926,
           1894,     32,      2,      2,      6, 106876,  67540,    154,  24008,
            342,  18949, 119044,    304, 158580, 189402, 219137,    154,  34604,
         160450,   8346, 159616,    281,  92714,    304,  63527,   5016,    487,
          12219,     30,      2]))

<s> ベルリンには何人が住んでいますか?</s></s> ベルリンの人口は891.82平方キロメートルの地域に登録された住民が3,520,031人います。</s>
kyakuno commented 6 months ago

厳密には、2回目の2はsep_tokenなのだけど、sep_tokenとeos_tokenが同じシンボルになっているので、2になる。

{
  "bos_token": "<s>",
  "clean_up_tokenization_spaces": true,
  "cls_token": "<s>",
  "eos_token": "</s>",
  "mask_token": {
    "__type": "AddedToken",
    "content": "<mask>",
    "lstrip": true,
    "normalized": true,
    "rstrip": false,
    "single_word": false
  },
  "model_max_length": 512,
  "pad_token": "<pad>",
  "sep_token": "</s>",
  "tokenizer_class": "XLMRobertaTokenizer",
  "unk_token": "<unk>"
}