Upgrade to Pro — share decks privately, control downloads, hide ads and more …

spaCy Pipeline上でのSHAPを日本語で試してみた

266d2b867f9f4fb00a4b992dbac6c678?s=47 Hiromasa Sakata
April 13, 2022
100

spaCy Pipeline上でのSHAPを日本語で試してみた

2022/4/8開催のNLP Hacks vol.3での発表資料です。

266d2b867f9f4fb00a4b992dbac6c678?s=128

Hiromasa Sakata

April 13, 2022
Tweet

Transcript

  1. spaCy Pipeline上でのSHAPを日本語で試してみた 株式会社レトリバ 坂田大直

  2. 自己紹介 ▪ 名前: 坂田 大直 (さかた ひろまさ) ▪ 所属: 株式会社レトリバ

    ▪ 仕事内容:自然言語処理分野の研究受託、製品開発
  3. 目次 ▪ SHAPとは? ▪ Spacyとは? ▪ Spacy Pipelineを使った文書分類

  4. SHAPとは?① • SHAPは、各データポイントの各特徴量ごとにモデルの出力への貢献度を提示してくれる手法。 • ある特徴量を無視したときの予測値の変化量、つまりその特徴量の貢献度(=SHAP値)を計算。 • あるデータポイントで特徴量を無視するとは、分かっている特徴量の値を固定して他のデータポイ ントにも適用して、全データポイントの予測値の平均を取ること。

  5. SHAPとは? ② • SHAPは X1, X2を特徴量とする。 f 𝑋1 , 𝑋2

    = 1.5 × 𝑋1 + 1.0 × 𝑋2 データポイントi と データポイントj があったとき 𝑥𝑖,1 = 2.0, 𝑥𝑖,2 = 1.0, 𝑥𝑗,1 = 4.0, 𝑥𝑗,2 = 2.0 のとき、 f 𝑋1 = 𝑥𝑖,1 , 𝑋2 = 𝑥𝑖,2 = 4.0, f 𝑋1 = 𝑥𝑗,1 , 𝑋2 = 𝑥𝑗,2 = 8.0 ・エンドポイントiの X2を無視 f 𝑋1 = 𝑥𝑖,1 , 𝑋2 = 𝑥𝑖,2 = 4.0, f 𝑋1 = 𝑥𝑖,1 , 𝑋2 = 𝑥𝑗,2 = 5.0 上記の平均をとる f 𝑋1 = 𝑥𝑖,1 = (4.0 + 5.0) / 2 = 4.5
  6. SHAPとは? ③ • 文書分類では、「特徴量の無視 」 == 「単語トークンを[MASK]トークンへの置き換え」 • ある文書中の単語が、その文書の予測ラベルの予測への貢献度を算出。

  7. Spacyとは? • テキスト分析の様々なタスクに関して、様々なComponentを組み合わせて簡単にPipelineを作成でき る。 • 設定変更のみでも、様々な下流タスクのパイプラインを構築可能。 Library Architecture https://spacy.io/api より引用。

    https://spacy.io/usage/processing -pipelinesより引用。
  8. 文書分類実験 ~ データ準備 ~ • 使用データ:Livedoor NEWSコーパス(https://www.rondhuit.com/download.html) • 2012年9月上旬にLivedoor Newsから収集されたニュース記事のデータセット

    • ニュースサイト名がラベルとして付いている。 • 以下の9種類のラベルが付いたマルチクラス分類タスク 'topic-news', 'livedoor-homme', 'sports-watch', 'smax', 'peachy', 'movie-enter', 'dokujo-tsushin', 'it-life-hack', 'kaden-channel’
  9. 文書分類実験 ~ データ準備 ~ • Ginzaを使用 • Ginza(https://megagonlabs.github.io/ginza/)はSpacyで日本語データを扱うため のライブラリ。 •

    形態素解析器にSudachiPy(https://github.com/WorksApplications/SudachiPy)を 採用している。 • データの読み込み • 読み込んだGinzaの解析器を使ってデータをSpacyの学習コマンドで読み込める形式に変換。 • それぞれのニュース記事をDocクラスのインスタンスに格納。 • この際、Doc.catsにラベル情報を格納。 • 学習データ、開発データ、検証データに分割し、それぞれDocBinクラスに格納。
  10. 文書分類実験 ~ データ準備 ~ • 依存モジュールのインストール • データの読み込み(概略) import spacy

    docs = []c-news', 'livedoor-homme', nlp = spacy.load("ja_ginza_electra") with open(“smax-article.txt”, “r”) as f: doc = nlp(f.read()) doc.cats = {“smax”: 1.0, ‘topic-news’: 0.0, ‘livedoor- homme’:0.0(略) } docs.append(doc) $ $ pip install -U spacy ginza ja-ginza ja-ginza-electra ginzatransformers sudachitra
  11. 文書分類実験 ~ データ準備 ~ データを分割してDocBinに概略 import random Import math random.seed(RANDOM_SEED)

    random.shuffle(docs) num_docs = len(docs) train_docs = docs[: math.floor(num_docs * 0.8)] dev_docs = docs[math.floor(num_docs * 0.8): math.floor(num_docs * 0.9)] test_docs = docs[math.floor(num_docs * 0.9): ] train_doc_bin = DocBin(docs=train_docs) train_doc_bin.to_disk("train_livedoor.spacy")
  12. 文書分類実験 ~ Spacy学習Configの準備~ • GinzaのGitリポジトリから設定ファイルの元をダウンロード https://github.com/megagonlabs/ginza/blob/develop/config/ja_ginza_electra .cfg • 以下の部分を書き換える。 textcatは文書分類用コンポーネント。

    [paths] train = "train_livedoor.spacy" dev = "dev_livedoor.spacy" [nlp] ~(略)~ pipeline = ["transformer", "textcat"] ~(略)~ [components.textcat] factory = "textcat" [components.textcat.model] @architectures = "spacy.TextCatEnsemble.v2" [components.textcat.model.tok2vec] @architectures = "spacy-transformers.TransformerListener.v1" grad_factor = 1.0 pooling = {"@layers":"reduce_mean.v1"} upstream = "*"
  13. 文書分類実験 ~ configの更新と学習コマンド実行~ • 未記入に設定を埋め、学習コマンドの実行。 • livedoor_electra_textcat に文書分類モデルが出力される。 $ python

    -m spacy init fill- config ja_ginza_electra.cfg ja_ginza_electra_filled.cfg $ python -m spacy train ja_ginza_electra_filled.cfg --verbose -- output livedoor_electra_textcat --gpu-id 0
  14. 文書分類実験 ~ SHAPのExpalinerの準備~ ・SpacyのTextCategorizerの出力がSHAPに合わない。Transformersの形式に変更する必要性。 import spacy textcat_spacy = spacy.load("livedoor_electra_textcat/model-best") tokenizer_spacy

    = spacy.tokenizer.Tokenizer(textcat_spacy.vocab) classes = list(textcat_spacy.get_pipe("textcat").labels) def predict(texts): texts = [str(text) for text in texts] results = [] for doc in textcat_spacy.pipe(texts): results.append([doc.cats[cat] for cat in classes]) return results
  15. 文書分類実験 ~ Spacyの出力のラッパーの準備~ ・SpacyのTextCategorizerの出力がSHAPに合わない。Transformersの形式に変更する必要性。 import spacy textcat_spacy = spacy.load("livedoor_electra_textcat/model-best") tokenizer_spacy

    = spacy.tokenizer.Tokenizer(textcat_spacy.vocab) classes = list(textcat_spacy.get_pipe("textcat").labels) def predict(texts): texts = [str(text) for text in texts] results = [] for doc in textcat_spacy.pipe(texts): results.append([doc.cats[cat] for cat in classes]) return results
  16. 文書分類実験 ~ SHAPのExplainerに渡す~ ・先ほどのpredict関数とtransformersのtokenizerを渡す。 from sudachitra import ElectraSudachipyTokenizer tokenizer =

    ElectraSudachipyTokenizer.from_pretrained("megagonlabs/tra nsformers-ud-japanese-electra-base-discriminator") explainer = shap.Explainer( predict, masker=shap.maskers.Text(tokenizer=tokenizer), algorithm="permutation", output_names=classes, max_evals=1500, )
  17. 文書分類実験 ~ 可視化結果~ • GinzaのGitリポジトリから設定ファイルの元をダウンロード https://github.com/megagonlabs/ginza/blob/develop/config/ja_ginza_electra .cfg • 単語の貢献度合いによって長さの違うバーとして可視化されている。

  18. 参考文献 • Spacy ドキュメント(https://spacy.io/usage) • Pythonではじめる テキストアナリティクス入門 榊 剛史 (編集,

    著), 石野 亜耶 (著), 小早川 健 (著), 坂地 泰紀 (著), 嶋田 和孝 (著), 吉田 光男 (著), 講談社 • 機械学習を解釈する技術 森下 光之助 (著),