7
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

J-PlatPat特許検索データで自然言語処理BERTによるFIコードの予測

Posted at

 科学技術と関連するWebでの情報調査と分析を行っています。
特許データはJ-PlatPatで収集できます。J-PlatPatは独立行政法人工業所有権情報・研修館が提供する特許検索情報サイトです。特許庁のHPからもアクセスすることができます。

J-PlatPatでは、検索結果をcsvファイルでダウンロードできます。csvファイルには要約を含めることができます。この要約の文章でFI分類コード推定のための機械学習モデルを作成してみました。FIはIPCを基礎として細展開された日本国特許庁独自の特許分類です。 国内特許文献のサーチキーとして利用されています。新規に特許出願する際に、事前に類似特許を検索するのに使われます。
コーディングは「BERTによる自然言語処理入門ーTransformerを使った実践プログラムー」の第7章マルチラベル文章分類を参考にしました。
https://github.com/stockmarkteam/bert-book/blob/master/Chapter7.ipynb
Screenshot 2022-10-09 08.49.29.png

J-PlatPat検索条件

検索サイト: J-PlatPat
検索論理式: [食用油脂/TI+食用油脂/AB+食用油脂/CL+食用油脂/BI]
TI:題名、AB:要約、CL:請求項、BI:書誌的事項
日付指定: 公知日、20150101〜
検索件数: 500件  *csvにダウンロードできるのは500件まで。超えた場合は、公知年を分けて検索ダウンロードして、結合して分析します。

開発環境

Google Colaboratory ノートブック, colab Pro
python
ランタイムのタイプ: ハードウェア アクセラレータ(GPU)
ランタイムの仕様(標準)

割り当てられたGPUの確認

筆者はcolab Proを使用しています。接続して割り当てられたGPUの仕様を確認しておきます。
GPUによって機械学習の時間、メモリの容量が変わります。

GPU
!nvidia-smi

下記が出力されます。GPUはTesla T4でメモリ容量は15109MiBです。機械学習実行後に再度上記コードを実行すると使用されたメモリが確認できます。
Screenshot 2022-10-08 13.36.32.png

Install

BERTが実装されているtransormers, 日本語の形態素解析ツールのMeCabが実装されているFugashi, MeCabで形態素解析に用いる辞書ipadic, 機械学習に使うpytorch-lightningをインストールします。

install
!pip install transformers==4.18.0 fugashi==1.1.0 ipadic==1.0.0 pytorch-lightning==1.6.1

Import

import
import pandas as pd
import random
from tqdm import tqdm

import torch
from torch.utils.data import DataLoader
from transformers import BertJapaneseTokenizer, BertModel
import pytorch_lightning as pl

# 日本語の事前学習モデル
MODEL_NAME = 'cl-tohoku/bert-base-japanese-whole-word-masking'

J-PlatPatからダウンロードしたcsvファイルを読み込んでデータフレームに代入

read_csv
df = pd.read_csv('input/特実_国内文献.csv')
print(df.info())

学習・推定するFIコードをone-hot encodingでリスト作成

500件の検索結果でFIコードランキングの上位3位のA23D9(181/500), A23L27(150/500), A23D7(97/500)について検討しました。

one-hot encoding
A23D9_l = []
A23L27_l = []
A23D7_l = []

for fi in df['FI']:
  #print(fi)
  #print('A23D9' in fi)
  if 'A23D9' in fi:
    encode = 1
  else:
    encode = 0
  A23D9_l.append(encode)

  if 'A23L27' in fi:
    encode = 1
  else:
    encode = 0
  A23L27_l.append(encode)

  if 'A23D7' in fi:
    encode = 1
  else:
    encode = 0
  A23D7_l.append(encode)

BERTによるマルチラベル分類するためのモデルをclassで定義

BERTMaltilabel
class BertForSequenceClassificationMultiLabel(torch.nn.Module):

  def __init__(self, modl_name, num_labels):
    super() .__init__()
    # BertModelのロード
    self.bert = BertModel.from_pretrained(MODEL_NAME)
    # 線形変換を初期化しておく
    self.linear = torch.nn.Linear(
        self.bert.config.hidden_size, num_labels
    )

  def forward(
      self,
      input_ids=None,
      attention_mask=None,
      token_type_ids=None,
      labels=None     
  ):
    # データを入力しBERTの最終層の出力を得る
    bert_output = self.bert(
        input_ids=input_ids,
        attention_mask=attention_mask,
        token_type_ids=token_type_ids)
    last_hidden_state = bert_output.last_hidden_state

    # [PAD]以外のトークンで隠れ状態の平均をとる
    averaged_hedden_state = \
      (last_hidden_state*attention_mask.unsqueeze(-1)).sum(1) \
      / attention_mask.sum(1, keepdim=True)

    # 線形変換
    scores = self.linear(averaged_hedden_state)

    # 出力の形式を整える
    output = {'logits': scores}

    # labelsが入力に含まれていたら、損失を計算し出力する
    if labels is not None:
      loss = torch.nn.BCEWithLogitsLoss() (scores, labels.float())
      output['loss'] = loss

    # 属性でアクセスできるようにする
    output = type('bert_output', (object,), output)

    return output

Pytorch Lightningでファインチューニングするモデルのclass定義

BERTMaltilabel_pl
class BertForSequenceClassificationMultiLabel_pl(pl.LightningModule):

  def __init__(self, model_name, num_labels, lr):
    super() .__init__()
    self.save_hyperparameters()
    self.bert_scml = BertForSequenceClassificationMultiLabel(
        model_name, num_labels=num_labels
    )

  def training_step(self, batch, batch_idx):
    output = self.bert_scml(**batch)
    loss = output.loss
    self.log('train_loss', loss)
    return loss

  def validation_step(self, batch, batch_idx):
    output = self.bert_scml(**batch)
    val_loss = output.loss
    self.log('val_loss', val_loss)

  def test_step(self, batch, batch_idx):
    labels = batch.pop('labels')
    output = self.bert_scml(**batch)
    scores = output.logits
    labels_predicted = ( scores > 0 ).int()
    num_correct = ( labels_predicted == labels ).all(-1).sum().item()
    accuracy = num_correct/scores.size(0)
    self.log('accuracy', accuracy)

  def configure_optimizers(self):
    return torch.optim.Adam(self.parameters(), lr=self.hparams.lr)

checkpoint = pl.callbacks.ModelCheckpoint(
    monitor = 'val_loss',
    mode = 'min',
    save_top_k=1,
    save_weights_only=True,
    dirpath = 'model/',
)

trainer = pl.Trainer(
    gpus=1,
    max_epochs=5,
    callbacks = [checkpoint]
)

トークナイザーとデータローダー

ダウンロードしたcsvの列'要約'の文章には、改行記号などが含まれていますので削除します。

tokenizer&dataloader
tokenizer = BertJapaneseTokenizer.from_pretrained(MODEL_NAME)
# 各データの形式を整える
max_length = 256
dataset_for_loader = []

for i in range(500):
  text = str(df['要約'][i])
  text = text.replace('【要約】\r\n', '')
  text = text.replace('\r\n', '')
  text = text.replace('<BR>', '')

  
  labels = [A23D9_l[i], A23L27_l[i], A23D7_l[i]]
  encoding = tokenizer(
      text,
      max_length=max_length,
      padding='max_length',
      truncation=True
  )
  encoding['labels'] = labels
  encoding = { k: torch.tensor(v) for k, v in encoding.items() }
  dataset_for_loader.append(encoding)

# データセットの分割
random.shuffle(dataset_for_loader)
n = len(dataset_for_loader)
n_train = int(0.6*n)
n_val = int(0.2*n)
dataset_train = dataset_for_loader[:n_train]  # 学習データ
dataset_val = dataset_for_loader[n_train:n_train+n_val]  # 検証データ
dataset_test = dataset_for_loader[n_train+n_val:]  # テストデータ

# データセットからデータローダを作成
dataloader_train = DataLoader(
    dataset_train, batch_size=32, shuffle=True
)
dataloader_val = DataLoader(dataset_val, batch_size=256)
dataloader_test = DataLoader(dataset_test, batch_size=256)

モデル作成と評価 

model&evalu
model = BertForSequenceClassificationMultiLabel_pl(
    MODEL_NAME,
    num_labels=3,   #対象とするFI数
    lr=1e-5
)
trainer.fit(model, dataloader_train, dataloader_val)
test = trainer.test(dataloaders=dataloader_test)
print(f'Accuracy: {test[0] ["accuracy"]:.2f}')
出力結果
Accuracy: 0.57

3つのFIとものAccuracy(正答率)は0.57前後になりました。各FIのAccuracyは0.8前後でした。参考にするツールとしてはまずまずのようですが、もう少し高めたいですね。
出現頻度の低いFIもありますので、他の評価指標、適合率(Precision)、再現率(Recall)、
F値(F-measure)でも見ておいたほうが良さそうです。

要約文章を入力してFIを推定

5つの特許の要約を入力してFIの推定を出力させました。

FI推定
# 入力する文章リスト
text_list = []
for i in range(5):
  text  = str(df['要約'][i])
  text = text.replace('【要約】\r\n', '')
  text = text.replace('\r\n', '')
  text = text.replace('<BR>', '')
  text_list.append(text)

# モデルのロード
best_model_path = checkpoint.best_model_path
model = BertForSequenceClassificationMultiLabel_pl.load_from_checkpoint(best_model_path)
bert_scml = model.bert_scml.cuda()

# データの符号化
encoding = tokenizer(
    text_list,
    padding = 'longest',
    return_tensors = 'pt'
)
encoding = { k: v.cuda() for k, v in encoding.items() }

# BERTへデータを入力し分類スコアを得る
with torch.no_grad():
  output = bert_scml(**encoding)
scores = output.logits
labels_predicted = ( scores > 0).int().cpu().numpy().tolist()

# 結果を表示
for text, label in zip(text_list, labels_predicted):
  print('--')
  print(f'入力 : {text}')
  print(f'出力 : {label}')

リストはA23D9, A23L27, A23D7の順です。
1がyes,0がnoです。

出力結果
入力 : 課題米飯等の澱粉含有食品の製造時に用いるだけで澱粉含有食品の風味を損なうことなく十分な血糖上昇抑制効果を付与することができる澱粉含有食品の血糖上昇抑制用添加剤及び澱粉含有食品の製造方法を提供する。【解決手段食用油脂5〜60%、リゾリン脂質0.1〜10%、多価アルコール10〜65%、及び水分5〜30%を含有することを特徴とする澱粉含有食品の血糖上昇抑制用添加剤選択図  なし
出力 : [0, 0, 0]
--
入力 : (57)課題ベーカリー食品の風味を強く感じさせたり味のコク味を高めたりする作用を有するベーカリー食品用油脂組成物を提供するさらにベーカリー食品用油脂組成物の製造方法ベーカリー生地およびベーカリー食品を提供する。【解決手段本発明のベーカリー食品用油脂組成物は原料油脂に対しレトルト処理を施すことで得られたレトルト油脂を含有する。【選択図なし
出力 : [1, 0, 0]
--
入力 : (57)課題本発明の目的は様々な食品に風味付けを行うことができ当該食品の風味や香りを向上できる風味油の製造方法を提供することである。【解決手段水分含量が40〜90質量の食品素材を含む食用油脂を一次加熱する一次加熱工程と前記食用油脂を一次加熱よりも10以上高い温度で二次加熱する二次加熱工程とを含む風味油の製造方法とするなお前記一次加熱工程において加熱温度は100〜120℃でありまた前記二次加熱工程において加熱温度が130〜150℃であることが好ましい。【選択図なし
出力 : [0, 0, 0]
--
入力 : (57)課題本発明は複合ベーカリー生地の内生地に使用することで製造時の作業性が良好であり歩留まりが向上しさらに焼成された複合ベーカリー製品の腰もちが向上し複合ベーカリー製品の焼成内生地のソフトさが向上し焼成内生地から焼成上生地への水分移行を抑制する油脂組成物を提供することを目的とする。【解決手段上記課題を解決するために、(食用油脂中に、(ブランチングエンザイムを含有する複合ベーカリー生地の内生地に使用する油脂組成物を提供する。(食用油脂中に、(ブランチングエンザイムを含有する油脂組成物を複合ベーカリー生地の内生地に使用することで製造時の作業性が良好であり歩留まりが向上しさらに焼成された複合ベーカリー製品の腰もちが向上し複合ベーカリー製品の焼成内生地のソフトさが向上し焼成内生地から焼成上生地への水分移行を抑制することができる。【選択図なし
出力 : [0, 0, 0]
--
入力 : (57)課題構成脂肪酸総量に占めるαリノレン酸の含有量が30質量以上80質量以下であるαリノレン酸高含有食用油脂を含む油脂組成物の加熱臭を抑制する方法を提供する。【解決手段αリノレン酸高含有食用油脂を含む油脂組成物に食用油脂Aを50質量以上80質量以下含有させる前記油脂組成物の加熱臭の抑制方法であって  前記αリノレン酸高含有食用油脂が構成脂肪酸総量に占めるαリノレン酸の含有量が30質量以上80質量以下であり  前記食用油脂Aがコーン油および米油から選ばれる一種又は二種である前記方法である。【選択図なし
出力 : [1, 0, 0]
7
10
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
7
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?