[PYTHON] [Version japonaise] Jugement de la similitude des mots pour les mots polynomiaux utilisant ELMo et BERT

Aperçu

Les modèles de traitement du langage naturel tels que ELMo et BERT fournissent des représentations contextuelles distribuées par mot. Vous pouvez vous attendre à pouvoir distinguer les significations utilisées dans les phrases pour les mots polynomiaux qui ont plusieurs significations. Articles publiés précédemment

Ensuite, en utilisant la version anglaise d'ELMo et BERT, nous avons vérifié si le mot «right» peut distinguer les trois sens de «right», «correct» et «right». Cette fois, nous utiliserons la version japonaise d'ELMo et de BERT pré-appris pour réaliser une expérience similaire sur des mots polynomiaux japonais.

ELMo et BERT, qui ont été pré-appris en japonais, utilisent le modèle publié par Stockmark.

Problème de réglage

Dans la version anglaise de l'expérience, j'ai distingué les trois significations de «right», mais je n'ai pas pu trouver un bon exemple avec trois significations ou plus en japonais, donc je considérerai plusieurs mots polynomiaux avec deux significations. Un total de 32 exemples de phrases est utilisé, avec 4 phrases pour chaque sens des quatre mots polynomiaux «tout à fait», «irrespectueux», «innocent» et «cou». La plupart des exemples de phrases sont tirés de dictionnaires de langue japonaise sur Internet, et certains d'entre eux ont été modifiés.

J'ai fait un cookie pour la première fois, mais ce n'était pas difficile et je pense que c'était assez délicieux. '' Il ne le dit pas, mais il se soucie beaucoup d'être court. '' `Le restaurant là-bas est bon marché mais assez délicieux. '' «Il y a beaucoup de gens qui ne se lavent pas les mains après les toilettes. ''

«J'en ai assez. Tout plus est bien. '' «Vous n'êtes pas obligé de faire ça. '' «À ce moment-là, j'ai décidé que le terrain ne serait pas utilisé et je savais que ce serait bien si je pouvais demander de l'argent. '' `Pourtant, contrairement à d'autres personnes, l'enseignant peut travailler tout en jouant, donc ça va. ''

«Hier soir, j'ai été déçu de vous montrer quelque chose de disgracieux. '' «Dans l'ensemble, pensez-vous que vous dites une chose aussi irrespectueuse? '' `Il prononçait des remarques irrespectueuses, mais il ne s'est pas bien passé sur le lieu de travail et a démissionné immédiatement. '' «Que dites-vous? Ne soyez pas irrespectueux. Ce n'est pas là que vous venez. retourner! ''

«J'ai été un peu déçu de la bibliothèque de mon frère. '' «Je suis désolé pour ce stylo à bille. '' «Un élève n'a pas respecté le chapeau du policier et s'est mis à courir en un coup d'œil. '' «Eh bien, quand il est parti, il n'a pas respecté la lettre qui n'était pas la sienne de la table. ''

En regardant innocemment l'éclat de la lune, quelque chose comme un souvenir hérité des temps anciens a été rappelé dans Tengo. '' «Et je voulais penser que si je continuais cet effort innocemment, cela mènerait finalement à une percée. '' Un cerf joue innocemment dans le feu à travers le sukinohana et dans l'érection étincelante d'un brun rougeâtre. '' «Le bruit des vagues frappait instinctivement les rochers sur le rivage toute la journée, brisé et éclaboussé. ''

«Dès que j'ai visité cet endroit et consulté sur la façon de me balancer, le mari de ma sœur m'a donné 300 yens. '' À ce moment-là, une femme avec un bébé allaitant se tenait à la porte et implorait l'innocence. '' «La mère de l’homme arrêté a révélé lors de l’entretien que le suspect avait été agressé la veille. '' «Le résultat a été que Kotaro a reçu une lettre d'innocence et a été contraint d'utiliser la route d'Ichiri jusqu'à son vieux père. ''

«Je m'attache toujours les cheveux parce que ça me gêne quand je serre mon cou. '' Rire avec une voix tendue en se penchant en arrière. '' Il y avait une décoration blanche sur le col des vêtements, probablement pour mettre en valeur la beauté du long cou. '' «L'employé fronça un peu les sourcils, réfléchit, puis secoua poliment la tête. ''

«Les travailleurs en congé pour accident du travail ne peuvent pas être licenciés. '' Ce projet a les chefs de chacun des membres de cette équipe. '' Si vous ne voulez pas être renvoyé, obtenez des résultats! '' «J'ai été renvoyé de l'entreprise, mais je n'ai pas pu le dire à ma famille et j'ai fait semblant d'aller à l'entreprise tous les jours et de passer du temps dans le parc. ''

Je pense qu'il est courant d'écrire "Kubi" en Katakana pour le sens B de "cou", mais je l'écris en kanji pour en faire la même expression que le sens A.

Entrez ces exemples de phrases dans ELMo et BERT pour extraire le vecteur incorporé du mot cible et la similitude cosinus entre les vecteurs.

cossim(\mathbf{u} ,\mathbf{v} ) = \frac{\mathbf{u} \cdot \mathbf{v}}{|\mathbf{u}| \, |\mathbf{v}|}

Vérifier que les mots ayant la même signification ont un degré élevé de similitude.

la mise en oeuvre

Le calcul a été fait sur Google colaboratory. TensorFlow utilise la série version 1.x.

Préparation

Importez les bibliothèques requises et montez Google Drive.

import json
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

#Bibliothèque pour utiliser le japonais avec matplotlib
!pip install japanize_matplotlib
import japanize_matplotlib

#Monter Google Drive
from google.colab import drive
drive.mount('/content/drive')

Le modèle de pré-apprentissage de la bourse utilise le dictionnaire MeCab + NEologd comme tokenizer. La procédure d'installation est celle décrite dans cet article, mais je la republierai.

#Installation de MeCab
!apt install aptitude swig
!aptitude install mecab libmecab-dev mecab-ipadic-utf8 git make curl xz-utils file -y

#Installation du dictionnaire NEologd
%cd /content
!git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
%cd mecab-ipadic-neologd
!echo yes | ./bin/install-mecab-ipadic-neologd -n

#Installez la bibliothèque pour appeler MeCab en python
!pip install mecab-python3
!pip install unidic-lite  #Sans ce mecab-J'obtiens une erreur lors de l'exécution de python3
import MeCab

Le travail se fait dans le répertoire / content / drive / 'My Drive' / synonym_classification.

%cd /content/drive/'My Drive'/synonym_classification

Ensuite, préparez une liste d'exemples de phrases à utiliser.

target_words = ["très bien", "Manque de respect", "Innocent", "cou"]

texts1 = ["J'ai fait un cookie pour la première fois, mais ce n'était pas difficile et je pense que c'était assez délicieux.", 
          "Il ne dit rien, mais il tient beaucoup à être court.", 
          "Le restaurant là-bas est bon marché mais assez délicieux.", 
          "Il y a beaucoup de gens qui ne se lavent pas les mains après les toilettes.", 
          "J'en ai assez. Tout plus est bien.", 
          "Vous n'êtes pas obligé de faire ça.", 
          "À ce moment-là, j'ai décidé que le terrain ne serait pas utilisé et je savais que ce serait bien si je pouvais demander de l'argent.", 
          "Pourtant, contrairement à d'autres personnes, le professeur va bien parce qu'il peut travailler tout en jouant."]

texts2 = ["Hier soir, j'ai été déçu de vous montrer quelque chose de disgracieux.", 
          "Dans l'ensemble, pensez-vous que vous dites une chose aussi irrespectueuse?", 
          "Il a prononcé toutes les remarques irrespectueuses, mais il ne s'est pas bien passé sur le lieu de travail et a démissionné immédiatement.", 
          "Que dis-tu Ne soyez pas irrespectueux. Ce n'est pas là que vous venez. retourner!", 
          "J'ai été un peu déçu de la bibliothèque de mon frère.", 
          "Je suis désolé pour ce stylo à bille.", 
          "Un élève n'a pas respecté le chapeau du policier et s'est mis à courir en un coup d'œil.", 
          "Eh bien, quand il est parti, il a manqué de respect à la lettre qui n'était pas la sienne de la table."]

texts3 = ["Tout en regardant l'éclat de la lune, quelque chose comme un souvenir hérité des temps anciens a été rappelé dans Tengo.", 
          "Le bruit des vagues a instinctivement frappé les rochers sur le rivage toute la journée, écrasés et éclaboussés. ..", 
          "Et je voulais penser que si je continuais cet effort innocemment, cela mènerait finalement à une percée.", 
          "Les cerfs jouent innocemment dans le feu de sukinohana et l'érection étincelante d'un brun rougeâtre.", 
          "Dès que j'ai visité cet endroit et consulté sur la façon de me balancer, le mari de ma sœur m'a donné 300 yens.", 
          "À ce moment-là, une femme avec un bébé allaitant se tenait à la porte et implorait l'innocence.", 
          "La mère de l'homme arrêté a déclaré lors de l'entretien que le suspect avait été agressé par l'argent la veille.", 
          "En conséquence, Kotaro a reçu une lettre d'innocence et a été contraint d'utiliser la route d'Ichiri jusqu'à son vieux père.", ]
          
texts4 = ["Je m'attache toujours les cheveux parce qu'ils me gênent quand je serre mon cou.", 
          "Il rit d'une voix tendue en penchant la tête en arrière.", 
          "Il y avait une décoration blanche sur le col des vêtements, probablement pour mettre en valeur la beauté du long cou.", 
          "L'employé fronça un peu les sourcils, réfléchit, puis secoua poliment la tête.", 
          "Les travailleurs en congé pour accident du travail ne peuvent pas être licenciés.", 
          "Le projet dépend de chacun des membres de l'équipe.", 
          "Si vous ne voulez pas être viré, obtenez des résultats!", 
          "Il a été renvoyé de l'entreprise, mais il n'a pas pu le dire à sa famille et a passé chaque jour dans le parc à faire semblant d'aller au bureau."]

Puisque vous devez entrer un fichier dans BERT, écrivez-le dans un fichier texte.

with open('texts1.txt', mode='w') as f:
  f.write('\n'.join(texts1))
with open('texts2.txt', mode='w') as f:
  f.write('\n'.join(texts2))
with open('texts3.txt', mode='w') as f:
  f.write('\n'.join(texts3))
with open('texts4.txt', mode='w') as f:
  f.write('\n'.join(texts4))

Étant donné que l'entrée dans ELMo doit être tokenisée à l'avance, préparez une fonction tokenizer et tokenize chaque phrase.

def mecab_tokenizer(texts, 
                    dict_path="/usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd"):
  mecab = MeCab.Tagger("-Owakati -d " + dict_path)
  token_list = []
  for s in texts:
      parsed = mecab.parse(s).replace('\n', '')
      token_list += [parsed.split()]
  return token_list
token_list1 = mecab_tokenizer(texts1)
token_list2 = mecab_tokenizer(texts2)
token_list3 = mecab_tokenizer(texts3)
token_list4 = mecab_tokenizer(texts4)

Le contenu de token_list1 est le suivant.

['Pour la première fois', 'biscuit', 'À', 'Fabrication', 'Ta', 'mais', '、', 'Difficile', 'ne pas', 'Ta', 'Shi', '、', 'très bien', 'おいShiく', 'Faire', 'Ta', 'Quand', 'pense', '。']
['il', 'Est', 'bouche', 'À', 'Est', 'Publié', 'Absent', 'mais', '、', 'Retour', 'Mais', 'petit', 'chose', 'À', 'À', 'très bien', 'Qi', 'À', 'Shi', 'main', 'je', 'Masu', '。']
['là bas', 'de', 'Restaurant', 'Est', '、', 'pas cher', 'deに', 'très bien', 'Délicieux', 'Hmm', 'est', 'Yo', '。']
['toilette', 'de', 'après', 'alors', '、', 'main', 'À', 'Lavé', 'Absent', 'Homme', 'Est', 'très bien', 'Beaucoup', 'je', 'Masu', '。']
['Déjà', 'suffisant', 'Quoi', 'Mieux', 'Ta', '。', 'cette', 'c'est tout', 'Est', 'très bien', 'est', '。']
['Tel', 'chose', 'Jusqu'à ce que', 'Shi', 'main', 'Est-ce', 'Sans pour autant', 'main', 'Aussi', 'très bien', 'est', '。']
['cette', 'Quand', 'À', 'Est', 'terre', 'Est', 'Est-ce', 'Absent', 'chose', 'À', 'Shi', 'main', '、', 'Argent', 'alors', 'S'il vous plaît', 'Mais', 'alorsき', 'Masure', 'Si', 'très bien', 'Est', 'Quand', 'je connais', 'main', 'je', 'Ta', 'de', 'alors', 'ござje', 'Masu', 'Mais', '。']
['Encore', '、', 'prof', 'Est', 'Autre', 'de', 'Homme', 'Quand', 'Différent', 'main', '、', 'jouer', 'Tandis que', 'emploi', 'Mais', 'Peut faire', 'dealors', 'très bien', 'alors', 'Je vous remercie', 'Masu', '。']

Le mot cible doit être séparé en un seul jeton pour la tâche d'identification des mots polynomiaux, mais il est vrai que «tout à fait» est un jeton dans chaque phrase. D'autres mots cibles pourraient également être symbolisés. En fait, la partie la plus difficile cette fois a été de sélectionner un mot polynomial répondant à cette condition.

En fait, je voulais comparer les résultats en utilisant d'autres BERT japonais pré-appris en plus du modèle de la marque boursière, mais avec des dictionnaires autres que le dictionnaire NEologd, par exemple, "OK" devient un jeton, ou WordPiece Lors de la création de jetons avec ou Phrase Piece, "Yui" et "Structure" ont été séparés, et la tâche de discrimination des mots polynominaux n'a pas pu être exécutée. Pour cette raison, cette fois, nous comparons uniquement ELMo et BERT pré-formés en bourse.

ELMo Le modèle ELMo utilise cette implémentation (https://github.com/HIT-SCIR/ELMoForManyLangs) avec des paramètres pré-entraînés en bourse. Comment utiliser cet article que j'ai écrit plus tôt

Est le même que.

!pip install overrides
!git clone https://github.com/HIT-SCIR/ELMoForManyLangs.git
%cd ./ELMoForManyLangs
!python setup.py install
%cd ..

Téléchargez le modèle de pré-formation stockmark depuis ici et placez-le dans le dossier . / ELMo_ja_word_level. Il existe un "modèle d'incorporation d'unité de mot" et un "modèle d'incorporation d'unité de caractère / d'unité de mot", mais cette fois nous utiliserons le "modèle d'incorporation d'unité de mot".

Maintenant que le modèle est prêt, créez une instance ʻEmbedder` et définissez une fonction pour calculer et récupérer le vecteur incorporé du mot cible.

from ELMoForManyLangs.elmoformanylangs import Embedder
from overrides import overrides

elmo_model_path = "./ELMo_ja_word_level"
elmo_embedder = Embedder(elmo_model_path, batch_size=64)

def my_index(l, x, default=-1):
  return l.index(x) if x in l else default

def find_position(token_list, word):
  pos_list = [my_index(t, word) for t in token_list]
  assert -1 not in pos_list
  return pos_list

def get_elmo_word_embeddings(token_list, target_word):
  embs_list = elmo_embedder.sents2elmo(token_list, output_layer=-2)
  pos_list = find_position(token_list, target_word)
  word_emb_list = []
  for i, embs in enumerate(embs_list):
    word_emb_list.append(embs[:, pos_list[i], :])
  return word_emb_list

L'argument output_layer de la méthode d'instance Embedder sents2elmo spécifie la couche à partir de laquelle le vecteur incorporé est extrait, et les détails sont les suivants. 0: couche d'incorporation du premier mot indépendante du contexte 1: couche LSTM première couche 2: deuxième couche LSTM -1: moyenne de 3 couches (par défaut) -2: Sortie des trois couches Cette fois, ʻoutput_layer = -2` est spécifié pour comparer la différence entre les couches de sortie.

Entrez le texte symbolisé pour calculer le vecteur incorporé pour le mot cible.

elmo_embeddings = get_elmo_word_embeddings(token_list1, target_words[0])
elmo_embeddings += get_elmo_word_embeddings(token_list2, target_words[1])
elmo_embeddings += get_elmo_word_embeddings(token_list3, target_words[2])
elmo_embeddings += get_elmo_word_embeddings(token_list4, target_words[3])
elmo_embeddings = np.array(elmo_embeddings)

print(elmo_embeddings.shape)
# (32, 3, 1024)

Comme l'incorporation de mots qui ne dépend pas du contexte de la première couche ne peut être utilisée pour distinguer les mots ambigus, nous utiliserons la moyenne des première et deuxième couches de LSTM et des trois couches appelées vecteur ELMo.

elmo_lstm1_embeddings = elmo_embeddings[:, 1, :]
elmo_lstm2_embeddings = elmo_embeddings[:, 2, :]
elmo_mean_embeddings = np.mean(elmo_embeddings, axis=1)

Avant de calculer la similitude cosinus du vecteur incorporé, préparez également le vecteur incorporé de BERT.

BERT Cet article que j'ai écrit plus tôt décrit également comment utiliser le modèle BERT pré-formé en bourse.

Selon. Tout d'abord, téléchargez le modèle pré-entraîné Stockmark (version TensorFlow) à partir de ce lien et placez-le dans le répertoire . / BERT_base_stockmark. Je vais. Ensuite, importez la série TensorFlow version 1.x et clonez le référentiel officiel BERT.

%tensorflow_version 1.x
import tensorflow as tf

!git clone https://github.com/google-research/bert.git

Du code dans le référentiel cloné, tokenization.py doit être modifié pour utiliser MeCab comme tokenizer. Veuillez vous référer à cet article car il sera trop long pour publier à nouveau. Le code ʻextract_features.pyqui récupère le vecteur incorporé n'a pas besoin d'être changé cette fois. En exécutant ce qui suit, le vecteur incorporé pour tous les jetons sera affiché dansbert_embeddings * .jsonl`. Toutes les couches sont spécifiées comme couches pour l'extraction du vecteur incorporé.

#Exécution BERT
for i in range(1, 5):
  input_file = 'texts' + str(i) + '.txt'
  output_file = 'bert_embeddings' + str(i) + '.jsonl'

  !python ./bert/extract_features_mecab_neologd.py \
    --input_file=$input_file \
    --output_file=$output_file \
    --vocab_file=./BERT_base_stockmark/vocab.txt \
    --bert_config_file=./BERT_base_stockmark/bert_config.json \
    --init_checkpoint=./BERT_base_stockmark/output_model.ckpt \
    --layers 0,1,2,3,4,5,6,7,8,9,10,11

Extrayez uniquement le vecteur incorporé du mot cible du fichier jsonl de sortie.

def extract_bert_embeddings(input_path, target_token, target_layer=10): 
  with open(input_path, 'r') as f:
      output_jsons = f.readlines()

  embs = []
  for output_json in output_jsons:
      output = json.loads(output_json)
      for feature in output['features']:
          if feature['token'] != target_token: continue
          for layer in feature['layers']:
              if layer['index'] != target_layer: continue
              embs.append(layer['values'])
  return np.array(embs)
bert_embeddings = []
for i in range(12):
  emb1 = extract_bert_embeddings('./bert_embeddings1.jsonl', 
                                 target_layer=i, target_token=target_words[0])
  emb2 = extract_bert_embeddings('./bert_embeddings2.jsonl', 
                                 target_layer=i, target_token=target_words[1])
  emb3 = extract_bert_embeddings('./bert_embeddings3.jsonl', 
                                 target_layer=i, target_token=target_words[2])
  emb4 = extract_bert_embeddings('./bert_embeddings4.jsonl', 
                                 target_layer=i, target_token=target_words[3])
  embeddings = np.vstack([emb1, emb2, emb3, emb4])
  bert_embeddings.append(embeddings)
bert_embeddings = np.array(bert_embeddings)

résultat

Maintenant que nous avons les vecteurs incorporés pour les deux modèles, déterminons la similitude des mots. Tout d'abord, préparez une fonction pour calculer la matrice de corrélation de similarité cosinus.

def calc_sim_mat(arr):
  num = len(arr) # number of vectors contained in arr
  sim_mat = np.zeros((num, num))
  norm = np.apply_along_axis(lambda x: np.linalg.norm(x), 1, arr) # norm of each vector
  normed_arr = arr / np.reshape(norm, (-1,1))
  for i, vec in enumerate(normed_arr):
    sim = np.dot(normed_arr, np.reshape(vec, (-1,1)))
    sim = np.reshape(sim, -1) #flatten
    sim_mat[i] = sim
  return sim_mat

Tout d'abord, regardons le résultat de l'utilisation du vecteur intégré de la deuxième couche de LSTM pour ELMo et de la deuxième couche de la fin pour BERT.

sim_mat_elmo = calc_sim_mat(elmo_lstm2_embeddings)
sim_mat_bert = calc_sim_mat(bert_embeddings[10])

Préparez et exécutez une fonction qui visualise le résultat du calcul.

def show_sim_mat(sim_mat, labels, title=None, export_fig=False):
  sns.set(font_scale=1.1, font="IPAexGothic") 
  g = sns.heatmap(
      sim_mat,
      vmin=0,
      vmax=1,
      cmap="YlOrRd")
  ticks_pos = range(2, 32, 4)
  plt.xticks(ticks=ticks_pos, labels=labels, rotation='vertical')
  plt.yticks(ticks=ticks_pos, labels=labels)
  for i in range(8, 25, 8):
    plt.plot([0, 32], [i, i], ls='-', lw=1, color='b')
    plt.plot([i, i], [0, 32], ls='-', lw=1, color='b')
  for i in range(4, 29, 8):
    plt.plot([0, 32], [i, i], ls='--', lw=1, color='b')
    plt.plot([i, i], [0, 32], ls='--', lw=1, color='b')
  if title:
    plt.title(title, fontsize=24)
  if export_fig:
    plt.savefig(export_fig, bbox_inches='tight')
  plt.show()
labels = ['Tout à fait un', 'Tout à fait B', 'Manque de respect A', 'Manque de respect B', 'Innocent A', 'Innocent B', 'Cou A', 'Cou B']
show_sim_mat(sim_mat_elmo, labels, 'ELMo', 'ELMo.png')
show_sim_mat(sim_mat_bert, labels, 'BERT', 'BERT.png')

Les résultats sont les suivants. La similitude entre les mots de 32 exemples de phrases est représentée par une carte thermique de 32 x 32 carrés. Une ligne de division est tracée toutes les 4 phrases dans lesquelles les mots polynomiaux sont utilisés de manière interchangeable. Idéalement, la couleur du bloc diagonal de carrés 4x4 sera plus foncée et la couleur des autres parties hors diagonale sera plus claire. <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613488/c55744f2-649d-7628-3724-56689760acc3.png ", height=280> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613488/a67af78a-bb98-52cd-3844-9a6de901ead0.png ", height=280> Concernant ELMo, c'était la même chose dans le calcul de cet article, mais l'angle entre les vecteurs intégrés a tendance à être petit, et la similitude globale est La valeur est grande et la couleur est foncée. Au moins, vous pouvez voir que les blocs diagonaux des carrés 8x8 du même mot sont plus sombres que les autres, mais les significations des mots polynomiaux ne semblent pas si distinctes. Par contre, en ce qui concerne BERT, vous pouvez clairement voir où la couleur du bloc diagonal des carrés 4x4 est plus sombre que celle de la partie hors diagonale. En particulier, je pense que A / B et le manche A se distinguent assez bien.

En passant, il n'est pas possible d'évaluer la précision avec précision simplement en regardant la carte thermique, alors évaluons le résultat à l'aide d'un indice quantitatif. Nous avons préparé quatre exemples de phrases pour chaque signification d'un mot polynomial, de sorte que chaque mot polynomial a trois compagnons avec la même signification. Par conséquent, pour chaque mot polynomial, les trois mots présentant le degré de similitude le plus élevé sont les mots polynomiaux de même signification déduits par le modèle. Calcule la précision de ce modèle pour l'inférence. Le block_size dans la fonction ci-dessous est la taille d'un bloc diagonal dans la carte thermique ci-dessus, qui est maintenant 4. Produit une liste de taux de précision pour chacune des 32 phrases d'exemple et leurs valeurs moyennes.

def eval_precision(sim_mat, block_size):
  num_data = len(sim_mat)
  precision_list = []
  for i in range(num_data):
    block_id = int(i / block_size)
    pred = np.array([1 if (block_id * block_size <= j and j < (block_id+1) * block_size) 
                    else 0 for j in range(num_data)])
    sorted_args = np.argsort(sim_mat[i])[::-1]
    sorted_pred = pred[sorted_args]
    precision = np.mean(sorted_pred[1:block_size])
    precision_list.append(precision)
  precision_arr = np.array(precision_list)
  av_precision = np.mean(precision_arr)
  return av_precision, precision_arr
#ELMo LSTM 2ème couche
av_precision, precision_arr = eval_precision(sim_mat_elmo, block_size=4)
print(np.round(av_precision, 2))
for i in range(8):
  print(np.round(precision_arr[4*i:4*(i+1)], 2))
#BERT 11ème couche
av_precision, precision_arr = eval_precision(sim_mat_bert, block_size=4)
print(np.round(av_precision, 2))
for i in range(8):
  print(np.round(precision_arr[4*i:4*(i+1)], 2))

Le résultat est le suivant.

** [ELMo LSTM 2ème couche] ** ** Moyenne ** 0,54

Exemple de phrase 1 Exemple de phrase 2 Exemple de phrase 3 Exemple de phrase 4
Tout à fait un 1.0 0.33 0.67 0.67
Tout à fait B 0.67 1.0 0.33 0.67
Manque de respect A 0.33 0.33 0.33 0.33
Manque de respect B 0.33 0.67 0.67 1.0
Innocent A 0.67 0.33 0.67 0.33
Innocent B 0.67 0.33 0.33 0.67
Cou A 0.67 0.67 1.0 0.67
Cou B 0.67 0 0 0.67

** [BERT 11ème couche] ** ** Moyenne ** 0,78

Exemple de phrase 1 Exemple de phrase 2 Exemple de phrase 3 Exemple de phrase 4
Tout à fait un 1.0 1.0 1.0 1.0
Tout à fait B 1.0 1.0 1.0 1.0
Manque de respect A 0 0.67 0.67 0.67
Manque de respect B 1.0 0.67 0.67 0.67
Innocent A 1.0 1.0 1.0 1.0
Innocent B 0.67 0.67 0.33 0.33
Cou A 1.0 1.0 1.0 1.0
Cou B 0.67 0 0.67 0.67

Après tout, le résultat est que la précision de BERT est élevée même lorsqu'elle est vue quantitativement. Dans Experiment in English version, le taux de précision moyen était ELMo 0,61 et BERT 0,78, donc les deux modèles ont presque le même niveau de précision que la version anglaise. Il est devenu. Les deux modèles ont du mal à comprendre le sens B du cou, mais est-il influencé par l'écriture du mot «cou» au lieu de «kubi»?

Enfin, nous comparerons la précision des couches qui extraient le vecteur embarqué. Pour BERT, le vecteur incorporé de la moyenne de toutes les couches et de la moyenne des 6 dernières couches est également calculé.

# ELMo
#LSTM 1ère couche
sim_mat_elmo = calc_sim_mat(elmo_lstm1_embeddings)
av_precision, _ = eval_precision(sim_mat_elmo, block_size=4)
print('LSTM1', np.round(av_precision, 2))

#LSTM 2ème couche
sim_mat_elmo = calc_sim_mat(elmo_lstm2_embeddings)
av_precision, _ = eval_precision(sim_mat_elmo, block_size=4)
print('LSTM2', np.round(av_precision, 2))

#Moyenne 3 couches
sim_mat_elmo = calc_sim_mat(elmo_mean_embeddings)
av_precision, _ = eval_precision(sim_mat_elmo, block_size=4)
print('mean', np.round(av_precision, 2))
# BERT
#Chaque couche
for i in range(12):
  sim_mat_bert = calc_sim_mat(bert_embeddings[i])
  av_precision, _ = eval_precision(sim_mat_bert, block_size=4)
  print(i+1, np.round(av_precision, 2))

#Moyenne de toutes les couches
sim_mat_bert = calc_sim_mat(np.mean(bert_embeddings, axis=0))
av_precision, _ = eval_precision(sim_mat_bert, block_size=4)
print('average-all', np.round(av_precision, 2))

#Deuxième moitié 6 couches en moyenne
sim_mat_bert = calc_sim_mat(np.mean(bert_embeddings[-6:], axis=0))
av_precision, _ = eval_precision(sim_mat_bert, block_size=4)
print('average-last6', np.round(av_precision, 2))

Les résultats sont les suivants. Affiche la précision moyenne de toutes les phrases d'exemple.

[ELMo]

couche Taux de conformité moyen
LSTM 1ère couche 0.52
LSTM 2ème couche 0.54
ELMo 0.54

[BERT]

couche Taux de conformité moyen
1ère couche 0.42
2ème couche 0.48
3e couche 0.67
4ème couche 0.73
5ème couche 0.73
6ème couche 0.73
7ème couche 0.72
8ème couche 0.73
9ème couche 0.78
10ème couche 0.78
11ème couche 0.78
12ème couche 0.77
Moyenne de toutes les couches 0.77
Moyenne finale sur 6 couches 0.77

Dans la version anglaise de l'expérience, ELMo a atteint la plus grande précision dans la 1ère couche LSTM et BERT dans la couche intermédiaire, mais cette fois ELMo est la moyenne des 2ème et 3ème couches LSTM, et BERT est la dernière couche autre que la couche finale. C'est la plus haute précision dans l'autre couche. Je pense que la tendance autour de cela dépend des données et des tâches de pré-formation.

en conclusion

L'histoire était la même que l'article que j'ai écrit auparavant, mais j'ai ressenti la difficulté à cause du japonais, comme le besoin d'écrire séparément. En comparant ELMo et BERT, il a été constaté que BERT peut distinguer les mots polynomiaux plus précisément que dans la version anglaise. Il est dommage que nous ne puissions pas comparer avec d'autres modèles pré-appris japonais en raison de la différence entre les jetons.

Recommended Posts

[Version japonaise] Jugement de la similitude des mots pour les mots polynomiaux utilisant ELMo et BERT
Utilisez ELMo et BERT pour déterminer la similitude des mots pour les mots polynomiaux
Python: texte japonais: caractéristique du discours à partir de la similitude des mots
Séparation du nom et du prénom japonais avec BERT
Calcul de la similitude entre les phrases à l'aide de Word2Vec (version simplifiée)
Jugement négatif / positif des phrases par BERT et visualisation des motifs
[Pour les débutants] Un résumé en mots des langages de programmation populaires (version 2018)