AI系基盤技術と、オープンソースを用いた機械学習による特許文書解析(補足1)

2020年10月4日
アジア特許情報研究会 西尾 潤

前処理、形態素解析、ベクトル化

本稿は特技懇誌 No.298, pp.25-37 (2020) に収録できなかった内容を追記するものです。

本稿(補足1)では、特許文書のテキスト情報を前処理、形態素解析、ベクトル化する方法にはそれぞれどのようなものがあるか、ソースコードを交えて紹介します。

特技懇誌投稿記事の図4のうち、下図のように濃色で示す部分に当たり、処理の流れは 生文 → 形態素解析 → 数値化(ベクトル化)となります。

 

母集団

母集団には、出願番号、公報番号、発明の名称、特許分類、要約、請求項、その他の情報が含まれます。

その中で要約、請求項はテキスト情報であり、【要約】、【特許請求の範囲】、【請求項1】などスミ付き括弧、「前記」、「該」など特許文章に特徴的に用いられるが技術内容と関係がない語等を削除することでテキスト情報からノイズを除去することや、大文字と小文字とを統一したり、同義語をそれらの代表の語に統一したりする用語統制等を行う前処理を行うことで機械学習の精度を向上させることができます。

前処理

ここでは、正規表現にマッチする語を削除する基本コードを紹介します。

【.*?】は、スミ付き括弧の中にすべての文字(.)が0回以上存在する(*)文字列の中で最も短いもの(?)がマッチすることを表現しています。

import re
text = '【請求項1】 染色液によるメディアへの着色度合を調整する単独では前記メディア上で視認困難な染色調整剤と、'
#  正規表現のコンパイル
sep = re.compile('【.*?】|\n|\u3000| |\n'
# 正規表現にマッチした部分を置換
output = sep.sub('', text)
print(output) # 染色液によるメディアへの着色度合を調整する単独では前記メディア上で視認困難な染色調整剤と、

参考

Pythonの正規表現の基本的な使い方

分かりやすいpythonの正規表現の例

自然言語処理の前処理・素性いろいろ

形態素解析

形態素解析は、文字列を機械学習で取り扱うことができる最小単位に分割する操作で、形態素解析を行うモジュールを形態素解析器といいます。

日本語形態素解析器には、KAKASIChasenMecabJanomeJUMANSudachiなどがあり、これらは内部に辞書を有し、文法に従って分割するものです。

これらの中でもっとも有名なものはMeCabですが、python環境にインストールするのが難しい問題がありま(した)。

また、出願頻度が多い文字列を順次切り出していくサブワード法によるものとしてsentencepieceがありますが、あらかじめ日本語文書で学習したモデルを使うことが特徴です。

また、Recurrent Neural Network (RNN) モデルを使った Juman++ もあります。

MeCab

import MeCab
m = MeCab.Tagger('-Owakati')
output = m.parse(text)

sentencepiece

import sentencepiece as spm
sp = spm.SentencePieceProcessor()
sp.load('data/wiki-ja.model')
output = ' '.join(sp.EncodeAsPieces(text))

n-gram

単純に n文字 で分割しますが、nが2以上の時、重なり合うように切り出す工夫が必要です。

ngram = list(zip(*(text for i in range(n))))
output = ' '.join([''.join(j) for j in ngram])

3方式の出力比較(␣は筆者が付与したもの)

MeCab 染色␣液␣に␣よる␣メディア␣へ␣の␣着色␣度合␣を␣調整␣する␣単独␣で␣は␣前記␣メディア␣上␣で␣視認␣困難␣な␣染色␣調整␣剤␣と␣、
sentencepiece ▁␣染色␣液␣による␣メディア␣への␣着␣色␣度␣合␣を調整する␣単独で␣は␣前␣記␣メディア␣上で␣視認␣困難な␣染色␣調整␣剤␣と␣、
n-gram 染色液␣色液に␣液によ␣による␣よるメ␣るメデ␣メディ␣ディア␣ィアへ␣アへの␣への着␣の着色␣着色度␣

ベクトル化 

形態素に分割されたテキストを数値化します。

参考:機械学習 〜 テキスト特徴量(CountVectorizer, TfidfVectorizer) 〜

Bag of Words

単語の出現頻度を計算して数値化します。scikit-leran モジュールの Countvectrizer として実装されています。

パラメータとして重要なものがあります。

パラメータ名 デフォルト値 備考
ngram_range (1, 1)
隣接するいくつまでの形態素について計算するか設定する
最初の数値は最小n-gram、最後の数値は最大n-gramを指定する
analyzer ‘word’
単語単位('word')、文字単位('char')、単語・文字併用('char_wb')
vocabulary None
解析に用いたい形態素をリストとして与えることができる
Noneの場合は入力文字列のすべての形態素が用いられる
 
from sklearn.feature_extraction.text import CountVectorizer

vectorizer = CountVectorizer(ngram_range=(1, 1), analyzer='word')
count_vec = vectorizer.fit_transform(corpus) # csr_matrix形式
print(vectorizer.get_feature_names()

TF-IDF

単語の頻度(Term Frequancy)と特定の単語が現れる文書頻度の逆数(Inverse Document Frequancy)から計算される単語のレア度を計算して数値化します。

scikit-leran モジュールの TfidfVectorizer として実装されています。

パラメータの注意事項はCountVectrizer と同様です。

from sklearn.feature_extraction.text import TfidfVectorizer

vectorizer = CountVectorizer(ngram_range=(1, 1), analyzer='word')
tfidf_vec = vectorizer.fit_transform(corpus) # csr_matrix形式で出力
print(vectorizer.get_feature_names() # 解析に用いられた形態素を出力

HashingVectrizer

feature hashingという手法を使った埋め込み表現です。

scikit-leran モジュールの HashingVectorizer を使用して計算します。

単語情報は設定した(n_features)次元に分散されます。ベクトルの要素と単語とは1対1対応ではありません。

from sklearn.feature_extraction.text import HashingVectorizer
n_features = 1048576

vectorizer = HashingVectorizer(ngram_range=(1, 1), analyzer='word', n_features=n_features)
hash_vec = vectorizer.fit_transform(corpus) # csr_matrix形式

Doc2Vec

gensim モジュールの Doc2Vec を用いて、

文章中の隣り合う単語の出現頻度を予測する学習を行い、

得られたモデルに未知の文書を入力すると、学習時に設定した次元のベクトルが得られます。

学習に用いたタグを入力すると、学習に用いた文書のベクトルが得られます。

(参考)

Doc2Vecについてまとめる

Doc2Vecの仕組みとgensimを使った文書類似度算出チュートリアル

Word2Vecとは | 分散表現・Skip-gram法とCBOWの仕組み・ツールや活用事例まで徹底解説

from gensim.models.doc2vec import Doc2Vec
from gensim.models.doc2vec import TaggedDocument
for i in range(len(corpus)):

  training_docs.append(TaggedDocument(words=corpus[i],
                      tags=[data['公報番号'][i]]))
# 学習
model = Doc2Vec(documents=training_docs, vector_size=300, min_count=1, dm=0)

# 学習モデルに文書を入力しベクトルを得る
vec = model.infer_vector(training_docs[i].tags)

ELMo

双方向LSTMを用いて学習させた言語モデルで、文脈を考慮した単語埋め込み表現が得られます。

言語モデルを最初から学習して作るのは膨大な計算リソースを使いますが、大規模日本語ビジネスニュースコーパスを学習したELMoモデルが公開されているのでこれを利用します。

最近の学習モデルはpyTorchが使われることが多くなりました。output_layer=-1 とすることによって、モデルの最終段出力を取り出しています。

ニューラルネットワークにテキストを流すときは、学習時と同じようにテキスト処理をしなければなりません。ここでは、公開されているモデルと同様に、MeCabで処理します。

ELMoの公開されているモデル出力は形態素ごとに1024次元のベクトルになります。文書ごとに出力サイズが変化しますので、形態素ごとのベクトルを平均して固定長の文書ベクトルにします。

(参考)

大規模日本語ビジネスニュースコーパスを学習したELMo(MeCab利用)モデルの紹介

大規模日本語ビジネスニュースコーパスを学習したELMo(MeCab利用)モデルの利用方法と精度比較検証

import torch
from ELMoForManyLangs.elmoformanylangs import Embedder
from overrides import overrides

data = char_e.sents2elmo(texts[n_batch*i:n_batch*(i+1)], output_layer=-1)
# 可変長ベクトルの平均をとり固定長ベクトルにする
new_array = []
for j in range(len(data)):new_array.append(np.average(data[j], axis=0).reshape(1,-1))
new_array = np.vstack(new_array)

sentence-transformers日本語版

2018年10月にGoogleがBERTという手法を発表し、自然言語処理の様々なタスクで最高精度を達成しました。

BERTは置換された単語を周りの文脈から当てるタスクを解くことで学習した、学習済みモデルとして公開されているので、ユーザーは学習モデルを再現して途中の出力を取り出したり、最後にユーザーのタスクに合わせた層を追加してファインチューニングしたりすることができます。

しかし、BERTは学習モデルが重すぎること、1文書として512形態素しか扱えない等の問題があり、その改良版が提案され、ここで用いるsentence-transformersもその1つです。

このモデルでは、形態素で区切ったテキストを入力すると768次元の文書ベクトルが手軽に得られます。

https://github.com/sonoisa/sentence-transformers

(参考)

はじめての自然言語処理|第9回 Sentence BERT による類似文章検索の検証

from sentence_transformers import SentenceTransformer

model_path = '/content/drive/My Drive/training_bert_japanese'
model = SentenceTransformer(model_path, show_progress_bar=False)

vectors = model.encode(corpus)
vectors = np.vstack(vectors)

ソースコード

google Colaboratory で使用可能な jupyter notebook 形式で配布しています。
 

 

AI系基盤技術と、オープンソースを用いた機械学習による特許文書解析(補足2) をみる