はじめに
この記事は GMOアドマーケティング Advent Calendar 2022 21日目の記事です。おはようございます。こんにちは。こんばんは。
GMOアドマーケティングのY-Kです。
今回は、
「最近話題の自然言語処理の機械学習のモデルを自分でも軽く触ってみたい!
でも、難しいこと書かれててわからない(号泣)」
という層に向けて、
数ある自然言語処理モデルの中でも有名なBERTモデルを使って、文同士の意味の類似度を計算するという簡単なタスクを
準備
今回もGoogle Colab上で行います。https://colab.research.google.com/?hl=ja
BERTの学習には時間と膨大な学習データ、豊富なインターネットリソースが必要なので、
Hugging Face上で公開されている学習済みBERTモデルを利用していきます。時短です。
https://huggingface.co/
まずは必要なライブラリを使えるようにします。
1 2 3 4 |
!pip install transformers !pip install sentence_transformers !pip install fugashi[unidic-lite] !pip install ipadic |
1 2 3 4 5 6 7 |
from transformers import BertJapaneseTokenizer, BertModel from sentence_transformers import SentenceTransformer from sentence_transformers import models import torch import numpy as np |
1 |
MODEL_NAME = 'cl-tohoku/bert-base-japanese-whole-word-masking' |
1 2 |
tokenizer = BertJapaneseTokenizer.from_pretrained(MODEL_NAME) model = BertModel.from_pretrained(MODEL_NAME) |
そこで、文の意味を理解しやすいように単語(token)ごとに区切り、さらにはその単語を数字ラベルに変換してあげるのが、tokenizerの役割になります。
ご飯を食べるとき、料理をそのまま人体には吸収できないので、噛んで小さくし消化して吸収し易くするのと似たようなものです。
文のベクトル化
BERTに文(単語)を渡すと、入力単語ごとのベクトルを吐き出します。これを用いて、文を文の意味を表すベクトルに変換し、文同士の意味上の類似度を計算するために利用します。
変換する関数は以下です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
def sentence_to_vector(model, tokenizer, sentence): # 文を単語に区切って数字にラベル化 tokens = tokenizer(sentence)<meta charset="utf-8">["input_ids"] # BERTモデルの処理のためtensor型に変換 input = torch.tensor(tokens).reshape(1,-1) # BERTモデルに入力し文のベクトルを取得 with torch.no_grad(): outputs = model(input, output_hidden_states=True) last_hidden_state = outputs.last_hidden_state<meta charset="utf-8">[0] averaged_hidden_state = last_hidden_state.sum(dim=0) / len(last_hidden_state) return averaged_hidden_state |
1 2 |
sentence = "我輩は猫である。" sentence_vector = sentence_to_vector(model, tokenizer, sentence) |
文の類似度計算
文の類似度計算はcos類似度というものを使って算出します。-1.0 ~ 1.0
の間の値で、大きければ大きいほど文の意味が似ているという解釈ができます。
1 2 3 4 5 6 7 8 |
def calc_similarity(sentence1, sentence2): print("{}\n{}".format(sentence1, sentence2)) sentence_vector1 = sentence_to_vector(model, tokenizer, sentence1) sentence_vector2 = sentence_to_vector(model, tokenizer, sentence2) score = torch.nn.functional.cosine_similarity(sentence_vector1, sentence_vector2, dim=0).detach().numpy().copy() print("類似度:", score) |
1 2 3 4 5 |
sentence1 = "吾輩は猫である" sentence2 = "私は猫です" calc_similarity(sentence1, sentence2) |
1 2 3 4 |
出力: 吾輩は猫である 私は猫です 類似度: 0.85347885 |
1 2 3 |
sentence3 = "お昼ご飯にカレーが食べたい" calc_similarity(sentence1, sentence3) |
1 2 3 4 |
出力: 吾輩は猫である お昼ご飯にカレーが食べたい 類似度: 0.76310676 |
さいごに
今回はBERTモデルを使って、文の意味の類似度を算出するタスクを行いました。pythonのライブラリで学習済みのモデルを使えば、専門的な知識がなくとも気軽に自然言語処理モデルを扱うことができると思います。
- 小説をベクトル化して保存、入力された文の意味合いに似た小説を推薦する
- 歌詞をベクトル化し似た意味合い(ジャンル)の他の歌を推薦する
明日はT.Oさんによる「SpotVMを使ってみる」です。
引き続き、GMOアドマーケティング Advent Calendar 2022 をお楽しみください!
■学生インターン募集中!
https://note.gmo-ap.jp/n/nc42c8a60afaf
■エンジニア採用ページはこちら!
https://note.gmo-ap.jp/n/n02cbeb6edb0d
■GMOアドパートナーズ 公式noteはこちら!
https://note.gmo-ap.jp/