
【副業実験記#7】Python+KeyBERTで日本語テキストからキーワードを抽出してみた話
/ 11 min read
Table of Contents
参考記事【副業実験記#6】Python+GiNZAで形態素解析して日本語テキストを自動改行してみた話
つづき。
はじめに
引き続き、雑学動画自動生成ツールを自作できないか、検討してみているお話です。
今回は、文章からキーワードを自動で抽出してくれるPythonライブラリである「KeyBERT」について、雑学動画自動生成ツールで使えるか検証してみた話です。
検証準備
Pythonのインストール
「Python」で雑学動画自動生成ツールを作るつもりなので、検証でも同様に使います。
詳細は以下の記事にまとめていますので、ご興味ある方は、そちらをご覧ください。
PyCharmのインストール
Pythonでの開発を楽にしてくれる統合開発環境「PyCharm」を使います。
Pythonで雑学動画自動生成ツールを作る際に使うつもりなので、検証でも同様に使います。
詳細は以下の記事にまとめていますので、ご興味ある方は、そちらをご覧ください。
検証用Pythonプロジェクトおよびvenvの作成
検証用「Pythonプロジェクト」を作成します。
PyCharmで簡単に作成できます。
Pythonプロジェクトを作成したら、その中で「venv」(Python仮想環境)を作成しておきます。
詳細は以下の記事にまとめていますので、ご興味ある方は、そちらをご覧ください。
https://sepapalab.com/why-use-venv-in-python/
Pythonパッケージのインストール
今回は、以下のパッケージを使用します。
| No | パッケージ | 説明 | 備考 |
|---|---|---|---|
| 1 | keybert | テキストの中から重要なキーワードを自動で抽出してくれるPythonライブラリパッケージです。 | |
| 2 | sentence-transformers | 文章や文同士の意味の近さを数値で表すためのライブラリパッケージです。 | |
| 3 | fugashi | 有名な日本語解析エンジン MeCab のPythonラッパーです。 | ・Pythonラッパー=PythonからMeCabを簡単に使うためのもの |
| 4 | unidic-lite | fugashiが使う「日本語の辞書データ(サイズ軽量版)」です。単語の意味や品詞などの情報を含んでいます。 |
KeyBERTは、基本的に英語向けということで、今回は「SentenceTransfomers」と日本語向けの埋め込みモデルである「cl-tohoku/bert-base-japanese」も一緒に使って試してみます。
この「cl-tohoku/bert-base-japanese」を使うために、「fugashi」や「unidic-lite」をインストールしています。
検証用Pythonプロジェクトでvenvを起動し、パッケージをインストールします。
ターミナルでコマンド実行してインストールする方法やPyCharm上で画面を操作してインストールする方法がありますが、今回は、PyCharm上で画面を操作し、venvにパッケージをインストールします。
参考記事PyCharmでvenv仮想環境へパッケージをインストールする方法【Windows 】【初心者向け】
検証してみた
KeyBERTを使用したキーワード抽出処理の流れ
以下の流れでKeyBERTを使っていくようでした。
-
「SentenceTransformers」を使い日本語モデルを読み込む
-
読み込んだ日本語モデルを「keyBERT」に渡す
-
keyBERTで日本語テキストからキーワードを抽出する
KeyBERTを使用したキーワード抽出処理の試し
では実際に、keyBERTと日本語モデル「cl-tohoku/bert-base-japanese」を使って、日本語テキストからキーワードを抽出してみます。
keyBERTと日本語モデル「cl-tohoku/bert-base-japanese」を使ったPythonサンプルコード
from keybert import KeyBERTfrom sentence_transformers import SentenceTransformer
# 日本語対応のBERTモデルを読み込みmodel = SentenceTransformer('cl-tohoku/bert-base-japanese')
# KeyBERTにモデルを渡すkw_model = KeyBERT(model)
# キーワードを抽出したいテキストtext = "Pythonはプログラミング言語のひとつで、データ分析やAI開発にも使われています。"
# キーワード抽出(トップ10件)keywords = kw_model.extract_keywords(text, top_n=10)
# 結果表示for kw in keywords: print(kw)Pythonサンプルコード実行結果
('データ分析やai開発にも使われています', 0.9273)('pythonはプログラミング言語のひとつで', 0.9215)・・・。
思った以上に、抽出されるキーワードの粒度が粗い・・・。
あえて日本語モデルを使うのをやめて実行してみましたが、粒度は変わらずでした。
動画タイトルからキーワードを抽出してハッシュタグに使うことなどを想定していたましたが、このままだと使えそうにありません。
ChatGPTさんに相談したところ、keyBERTを使わなくとも、「SentenceTransformers」×「fugashi」×「scikit-learn」で似たような処理ができるということだったので、試してみました。
「SentenceTransformers」×「fugashi」×「scikit-learn」を使ったキーワード抽出(の手前)のPythonサンプルコード
import fugashifrom sentence_transformers import SentenceTransformerfrom sklearn.metrics.pairwise import cosine_similarity
# モデル読み込み(東北大でもOK)model = SentenceTransformer("cl-tohoku/bert-base-japanese")
# 入力input_text = "Pythonはプログラミング言語のひとつで、データ分析やAI開発にも使われています。"
def extract_noun_phrases(text): words = list(fugashi.Tagger()(text)) phrases = [] i = 0 while i < len(words): word = words[i] # 名詞 + 接尾辞 のペア(例:ひと + つ → ひとつ) if "名詞" in word.feature: phrase = word.surface # 次が接尾辞ならくっつける if i + 1 < len(words) and "接尾辞" in words[i + 1].feature: phrase += words[i + 1].surface i += 1 phrases.append(phrase) i += 1 return list(set(phrases)) # 重複除去
candidates = extract_noun_phrases(input_text)
# 埋め込みベクトル化doc_vec = model.encode([input_text])cand_vecs = model.encode(candidates)
# 類似度スコアを計算scores = cosine_similarity(doc_vec, cand_vecs)[0]
# 候補+スコアのペアを作るscored = list(zip(candidates, scores))scored.sort(key=lambda x: x[1], reverse=True)
# 表示for w, s in scored: print(f"{w}: {s:.4f}")Pythonサンプルコード実行結果
Python: 0.7277データ: 0.6582プログラミング: 0.6475ひとつ: 0.6181分析: 0.6071言語: 0.5833開発: 0.5749AI: 0.5471“「fugashi」で日本語テキストの名詞を抽出”し、抽出した名詞に対して類似度スコアを計算しましたが、こっちの方がハッシュタグを生成する用途で使えそうですね。
ここでふと疑問が。
「fugashiではなく、GiNZAではどうか?」
と思ったので、ChatGPTさんに相談したところ、「fugashi」の部分を「GiNZA」に置き換えても大丈夫そうだったので、試してみました。
「SentenceTransformers」×「GiNZA」×「scikit-learn」を使ったキーワード抽出(の手前)のPythonサンプルコード
import spacyfrom sentence_transformers import SentenceTransformerfrom sklearn.metrics.pairwise import cosine_similarity
# GiNZAモデルの読み込み(ja_ginza_electraが高精度)nlp = spacy.load("ja_ginza_electra")model = SentenceTransformer("cl-tohoku/bert-base-japanese")
# 入力文input_text = "Pythonはプログラミング言語のひとつで、データ分析やAI開発にも使われています。"
# 名詞句(noun chunk)を候補として抽出def extract_noun_phrases_with_ginza(text): doc = nlp(text) return list(set([chunk.text for chunk in doc.noun_chunks if len(chunk.text.strip()) > 1]))
candidates = extract_noun_phrases_with_ginza(input_text)
# ベクトル化してスコア計算doc_vec = model.encode([input_text])cand_vecs = model.encode(candidates)scores = cosine_similarity(doc_vec, cand_vecs)[0]
# スコア付きで並べるscored = list(zip(candidates, scores))scored.sort(key=lambda x: x[1], reverse=True)
# 表示for word, score in scored: print(f"{word}: {score:.4f}")Pythonサンプルコード実行結果
Python: 0.7277プログラミング言語: 0.6830データ分析: 0.6397AI開発: 0.6162“「fugashi」の代わりに「GiNZA」で日本語テキストの名詞を抽出”し、抽出した名詞に対して類似度スコアを計算しましたが、こっちの方が抽出される粒度が大きい代わりに、単語のまとまり具合が適切な感じです。
こちらの方がハッシュタグ的には適切なキーワードのような気もします。
あと、この粒度なら「Stable Diffusion web UI」のプロンプトに渡す粒度に適しているように思えました。
それぞれ、用途に応じて使い分けることもできそうに思いました。
おわりに
「keyBERT」ですが、日本語テキストからキーワードを抽出できることが分かりましたが、想定していた結果が得られなかったので、雑学動画自動生成ツールで使うかどうかは微妙です・・・。
その代わり、以下の代替方法によるキーワード抽出を使う可能性が高いです。
-
「SentenceTransformers」×「fugashi」×「scikit-learn」
-
「SentenceTransformers」×「GiNZA」×「scikit-learn」
ここら辺は、AI画像生成時のプロンプト自動生成やハッシュタグ自動生成で使おうと思います。
これで、「keyBERT」の検証を一通り終えたので、次の技術やツールの検証に移ろうと思います。
(今回も検証用のコードは、ChatGPT(GPT-4oモデル)に出力してもらったものを微修正したものです)
今回の記事も、同じように副業に悩んでいる人、手探りで取り組んでいる人にとって、何かの参考になれば嬉しいです。
これからも記録を続けていく予定なので、よければフォローしてもらえると嬉しいです。
つづき。
参考記事【副業実験記#8】Python+MoviePyで動画を自動生成してみた話