1.背景
(理解が間違っていたらすみませんが)Doc2Vecは、文章が似ているかどうかの判断ができるんだろうな、と考えました。
「判断」とは曖昧なもので、人によっても異なるものです。
もし、Doc2Vecが定量的な数値として「判断」の基準を示してくれれば、これほどありがたいものはありません。
こんな考えから、Doc2Vecを使ってみました。
2.環境
ubuntu 16.04
python 3
3.材料
Doc2Vecに判断してもらう材料として、次のものを用意しました。
本願 :特開2014-223436
刊行物1 :特開2005-176862
刊行物2 :特開2006-326215
刊行物3 :特開2001-218930
ランダム1:特開2012-123654
ランダム2:特開2015-123654
これは、本願、刊行物1〜3については、特許不服審判「不服2016-15403」からのもってきたものです。
1の背景でも触れましたが、「判断」とは曖昧なので、特許について似ている似ていないを判断するプロである特許庁の方々の判断結果と、Doc2Vecの判断結果を比較したいと考えました。
本願と刊行物以外に「ランダム」というものがあります。
これは、本願と刊行物はプロが選んだ似ているもの同士なので、Doc2Vecによって優位な差がでないかもしれません。
優位な差を出したいために、適当な(番号のしも6桁が同じもの)を僕が探してきて、ランダム1,2としまいた。
4.本筋から外れる部分で
一応、特許不服審判について、簡単に説明させていただきます。
出願人Aが特許出願(特開2014-223436)をしました。
特許庁で審査官さん(審査のプロの方々)が審査を行いまいたが、特許にはできないと判断しました。
出願人Aは、審査官さんの判断になっとくできず、審判を訴えました。
それで今度は、審判官さんが審判を行いましたが、やはり出願人Aの特許出願は、特許にはできないと判断しました。
審判官さんは特許にはできないという判断の根拠として、出願人Aの特許出願より以前に、他の人がすでに「同じような似ている特許出願」をしているから、ということで、審判官は同じような特許出願として刊行物1~3を示しています。
言い換えると、審判官は「出願人Aの特許出願と、刊行物1~3は、似ている」と判断したことになります。
まずはこんな流れです。
5.データの準備
さて、審判官は「出願人Aの特許出願と、刊行物1~3を、似ている」と判断したが、Doc2Vecは、審判官と同じように判断するのでしょうか?
では実際にどのように行うのか。
以前のブログでも引用させてもらった「@enta0701」さんのコードを改良させていたきまいた。
https://qiita.com/Chizaizizii/items/45a4e9538c12e2c9d5d7
入力データとして、次のようなものを用紙しました。
本願 :特開2014-223436(請求項部分を全文)
刊行物1 :特開2005-176862(詳細な説明部分を全文)
刊行物2 :特開2006-326215(詳細な説明部分を全文)
刊行物3 :特開2001-218930(詳細な説明部分を全文)
ランダム1:特開2012-123654(詳細な説明部分を全文)
ランダム2:特開2015-123654(詳細な説明部分を全文)
繰り返しになりますが、本願は、出願人Aの特許出願、刊行物1~3は、不服審判「不服2016-15403」の本文より抽出しています。
ランダム1、ランダム2は、僕がランダムに選んだ特許公報です(;´∀`)
本願と刊行物1~3のグループ(仮にグループA)に対し、Doc2Vecの比較結果に有意な差がでることを期待し、ランダム(技術的に何の関連性もなさそうな特許公報)の要約を2つ(仮にグループB)ほど盛り込んでみました。
グループAとグループBの比較結果に差が出れば、Doc2Vecは「出願人Aの特許出願と、刊行物1~3を、似ている」と判断したと結論付けたいと思います(^▽^;)
6.実装
こんな感じです。
# -*- coding: utf-8 -*-
# py3
from os import path
import MeCab
from gensim.models.doc2vec import Doc2Vec
from gensim.models.doc2vec import TaggedDocument
from collections import OrderedDict
current_dir = path.dirname('__file__')
text = open(path.join(current_dir, 'documents.txt'), 'r').read()
documents = text.split("|")
def words(text):
"""
文章から単語を抽出
"""
out_words = []
tagger = MeCab.Tagger('-Ochasen')
tagger.parse('')
node = tagger.parseToNode(text)
while node:
word_type = node.feature.split(",")[0]
if word_type in ["名詞"]:
out_words.append(node.surface)
node = node.next
return out_words
# 学習データとなる各文書
training_docs = []
for i, document in enumerate(documents):
training_docs.append(TaggedDocument(words=words(document), tags=['doc' + str(i + 1)]))
model = Doc2Vec(documents=training_docs, min_count=1, dm=0)
tags = OrderedDict()
tag_list = (('doc1', "本願"), ('doc2', "刊行物1"), ('doc3', "刊行物2"), ('doc4', "刊行物3"), ('doc5', "ランダム1"), ('doc6', "ランダム2"))
dic = OrderedDict(tag_list)
tags.update(dic)
for k, v in tags.items():
print("[" + v + "]")
for items in model.docvecs.most_similar(k):
print("\t" + tags[items[0]] + " : "+ str(items[1]))
7.結果
さて、結果はこんな感じになりました。
[[本願]
刊行物2 : 0.8545494079589844
刊行物3 : 0.7431389689445496
刊行物1 : 0.7000955939292908
ランダム2 : 0.5176839828491211
ランダム1 : 0.3967837691307068
[刊行物1]
本願 : 0.7000956535339355
刊行物3 : 0.48298516869544983
刊行物2 : 0.44776421785354614
ランダム1 : 0.3875276446342468
ランダム2 : 0.21002274751663208
[刊行物2]
本願 : 0.8545494079589844
刊行物1 : 0.44776421785354614
刊行物3 : 0.3732856810092926
ランダム2 : 0.2865113615989685
ランダム1 : 0.22178468108177185
[刊行物3]
本願 : 0.7431389093399048
刊行物1 : 0.48298513889312744
ランダム2 : 0.4452183246612549
刊行物2 : 0.3732856810092926
ランダム1 : 0.1128430962562561
[ランダム1]
ランダム2 : 0.7021363973617554
本願 : 0.3967837691307068
刊行物1 : 0.3875276744365692
刊行物2 : 0.22178471088409424
刊行物3 : 0.1128431037068367
[ランダム2]
ランダム1 : 0.7021363973617554
本願 : 0.5176840424537659
刊行物3 : 0.44521835446357727
刊行物2 : 0.2865113615989685
刊行物1 : 0.21002274751663208
この結果をみると、Doc2Vecは、本願に対して刊行物1〜3は似ている、本願に対しランダム1〜2は刊行物1〜3のようには似ていないと判断できているように見えます。
次は、もっといろいろと試してみたいと思います。