3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GLiNER-Decoder-Large-v1.0とは?ニュース記事から企業・製品・人物をサクッと抽出

Posted at

はじめに

ニュース記事を読んでいて、
「結局どの会社が登場して、何を発表したの?」
「人名や日付だけ自動でまとめられないかな?」
と思ったことはありませんか?
今回使うのは GLiNER-Decoder-Large-v1.0。これ、ラベル名(例:企業・人物・製品)を自分で決めるだけで、ニュースから必要な情報をゼロショットで抜き出してくれるスグレモノです。しかも Colab 上でサクッと動きます。
ということで、さっそく「トヨタがEVを発表、同じ日にテスラもSUVを公開」という記事を食わせてみました。


GLiNER-Decoder-Large-v1.0とは?

GLiNER (Generalist Language Model for Named Entity Recognition) は、事前に決められたラベルに縛られず、任意のエンティティタイプをゼロショットで抽出できるNERモデルです。
その中でも GLiNER-Decoder-Large-v1.0 は、従来のエンコーダ型GLiNERに「デコーダ」を組み合わせた強化版。

特徴まとめ
・オープンオントロジー対応:未知のラベルでも使える
・マルチラベル対応:1つのテキストから複数ラベルを同時に付与
・大規模デコーダの知識活用:より柔軟で文脈に強い
・効率的推論:GPU上でも軽快に動作

要するに、「好きなラベル名をその場で決めて → 文章から一気に抽出」できる便利ツールです。


使ってみた

今回要約させた文章がこちら↓

トヨタ自動車は2025年8月21日、東京で開催された記者会見において、新型電気自動車「bZ5X」を正式に発表した。
このモデルは航続距離600キロを実現し、年内に日本とアメリカ市場で発売される予定だ。
会見には佐藤恒治社長が出席し、「持続可能なモビリティ社会を実現するための重要な一歩だ」とコメントした。
さらに、販売戦略として欧州市場での投入も検討していることを明らかにした。
一方、競合のテスラは同日、カリフォルニアで新型SUV「Model Y Pro」を公開し、価格競争が激化する見通しだ。

抽出できた結果
実際の出力はこんな感じになりました。

ラベル 抽出テキスト
企業 トヨタ自動車, テスラ
製品 bZ5X, Model Y Pro
人物 佐藤恒治
場所 東京, カリフォルニア
日付 2025年8月21日
イベント 記者会見

ちゃんと記事の要点が一覧化されました。
人名・企業・製品・場所が一発で整理されるのは便利です。

面白いポイント

・ゼロショット対応 → 「企業」「製品」といったラベルを好きに定義できる
・日本語ニュースでもOK → 英語モデルにありがちな“英語ラベル必須”ではなく、そのまま日本語でいける
・複数記事に拡張できる → フォルダに入れた記事をまとめて処理 → 出現頻度ランキングも簡単

使い道のアイデア

・経済ニュース → 「企業」「製品」「市場」だけ抽出して業界動向を自動サマリ
・政治ニュース → 「人物」「政党」「政策」を抽出して関係図を作成
・スポーツ記事 → 「選手」「チーム」「大会」を抜き出して試合レポートを自動整理

精度を上げるコツ

threshold=0.3〜0.5で調整(低いと拾い多め、高いと精度重視)
文ごとに推論するとスパンが安定
ラベルはシンプルに → 「企業」だけでOK、「会社名」みたいに複雑にしない
・日付は正規表現で補完しておくと確実


手順(コピペOK:インストール→推論→集計→保存)

1セルで実行できます

# === ニュース記事 NER(GLiNER-Decoder)一発実行セル ===
# 1) 必要パッケージ
try:
    from gliner import GLiNER
except ImportError:
    !pip -q install gliner pandas
    from gliner import GLiNER
import re, pandas as pd

# 2) モデル読み込み(GPUがあれば自動使用)
model = GLiNER.from_pretrained("knowledgator/gliner-decoder-large-v1.0")

# 3) ラベル(説明付き→曖昧さ低減)
labels = [
    "企業: 会社名や団体名(例: トヨタ、テスラ、NTTドコモ)",
    "製品: 製品・モデル名(例: iPhone, bZ5X, Model Y Pro)",
    "人物: 個人名(例: 佐藤恒治)",
    "場所: 地名や国名(例: 東京, カリフォルニア)",
    "日付: 年月日(例: 2025年8月21日)",
    "イベント: 記者会見・発表会などの出来事名"
]

# 4) 記事本文(差し替え可)
text = """トヨタ自動車は2025年8月21日、東京で開催された記者会見において、新型電気自動車「bZ5X」を正式に発表した。
このモデルは航続距離600キロを実現し、年内に日本とアメリカ市場で発売される予定だ。
会見には佐藤恒治社長が出席し、「持続可能なモビリティ社会を実現するための重要な一歩だ」とコメントした。
さらに、販売戦略として欧州市場での投入も検討していることを明らかにした。
一方、競合のテスラは同日、カリフォルニアで新型SUV「Model Y Pro」を公開し、価格競争が激化する見通しだ。"""

# 5) 文ごと推論(スパン暴走抑制)
def extract_by_sentence(model, text, labels, thr=0.5, num_gen_sequences=1):
    out, offset = [], 0
    sents = [s for s in text.split("。") if s]
    for sent in sents:
        ents = model.predict_entities(sent, labels, threshold=thr, num_gen_sequences=num_gen_sequences)
        for e in ents:
            e["start"] += offset
            e["end"]   += offset
            out.append(e)
        offset += len(sent) + 1  # 「。」ぶん
    return out

# 6) かんたん後処理(助詞などのトリム)
TRIM_TAIL = ("で", "において", "として", "など", "について")
TRIM_HEAD = ("同日",)
def clean_span(e):
    t = e.get("text", "").strip()
    for suf in TRIM_TAIL:
        if t.endswith(suf): t = t[:-len(suf)]
    for pre in TRIM_HEAD:
        if t.startswith(pre): t = t[len(pre):]
    t = re.sub(r"\s+", " ", t).strip()
    e["text"] = t
    return e

entities = extract_by_sentence(model, text, labels, thr=0.5, num_gen_sequences=1)
entities = [clean_span(e) for e in entities]

# 7) 正規表現で日付補完
date_pat = re.compile(r"\d{4}年\d{1,2}月\d{1,2}日")
if not any(str(e.get("label","")).startswith("日付") for e in entities):
    for m in date_pat.finditer(text):
        entities.append({"start": m.start(), "end": m.end(), "text": m.group(), "label": "日付", "score": 1.0})

# 8) 表に整形+重複整理
df = pd.DataFrame(entities)
for col in ["entity","text","label","score","start","end"]:
    if col not in df.columns: df[col] = None
df["label"] = df["label"].astype(str).str.split(":", n=1, expand=True)[0]
df = (df.sort_values("score", ascending=False)
        .drop_duplicates(subset=["label","text"])
        .reset_index(drop=True))

print("=== 抽出結果 ===")
display(df[["label","text","score","start","end"]])

# 9) ラベル別の頻出集計
freq = (df.groupby(["label","text"]).size()
          .reset_index(name="count")
          .sort_values(["label","count"], ascending=[True, False]))
print("=== ラベル別 頻出集計 ===")
display(freq)

# 10) CSV保存
df.to_csv("news_entities.csv", index=False)
freq.to_csv("news_summary.csv", index=False)
print("保存しました -> news_entities.csv, news_summary.csv")

検出が弱いときの“緩め設定”パッチ
・短いラベルに変更
threshold=0.35 / num_gen_sequences=2 に変更

labels_simple = ["企業","製品","人物","場所","日付","イベント"]
entities = extract_by_sentence(model, text, labels_simple, thr=0.35, num_gen_sequences=2)
entities = [clean_span(e) for e in entities]
# 以下は同じ(整形→集計→保存)

まとめ

GLiNER-Decoder-Large-v1.0 は「ニュースを自動でデータ化する魔法のツール」。好きなラベルを与えるだけで、誰が・いつ・どこで・何をしたのかが一目でわかります。
今回はトヨタとテスラのニュースを題材にしましたが、ビジネス・政治・スポーツ・エンタメまで応用可能。情報整理やリサーチを効率化したい人には、まさにピッタリのモデルです。


フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

Twitter
Medium

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?