特許公報が似ているかどうかDoc2Vecで判断

１．背景
---
（理解が間違っていたらすみませんが）Doc2Vecは、文章が似ているかどうかの判断ができるんだろうな、と考えました。
「判断」とは曖昧なもので、人によっても異なるものです。
もし、Doc2Vecが定量的な数値として「判断」の基準を示してくれれば、これほどありがたいものはありません。
こんな考えから、Doc2Vecを使ってみました。

２．環境
---
ubuntu 16.04
python 3

３．材料
---
Doc2Vecに判断してもらう材料として、次のものを用意しました。
本願　　　:特開2014-223436
刊行物１　:特開2005-176862
刊行物２　:特開2006-326215
刊行物３　:特開2001-218930
ランダム１:特開2012-123654
ランダム２:特開2015-123654

これは、本願、刊行物１〜３については、特許不服審判「不服2016-15403」からのもってきたものです。

１の背景でも触れましたが、「判断」とは曖昧なので、特許について似ている似ていないを判断するプロである特許庁の方々の判断結果と、Doc2Vecの判断結果を比較したいと考えました。

本願と刊行物以外に「ランダム」というものがあります。
これは、本願と刊行物はプロが選んだ似ているもの同士なので、Doc2Vecによって優位な差がでないかもしれません。
優位な差を出したいために、適当な（番号のしも６桁が同じもの）を僕が探してきて、ランダム１，２としまいた。

４．本筋から外れる部分で
---
一応、特許不服審判について、簡単に説明させていただきます。

出願人Aが特許出願（特開2014-223436）をしました。
特許庁で審査官さん（審査のプロの方々）が審査を行いまいたが、特許にはできないと判断しました。

出願人Aは、審査官さんの判断になっとくできず、審判を訴えました。
それで今度は、審判官さんが審判を行いましたが、やはり出願人Aの特許出願は、特許にはできないと判断しました。
審判官さんは特許にはできないという判断の根拠として、出願人Aの特許出願より以前に、他の人がすでに「同じような似ている特許出願」をしているから、ということで、審判官は同じような特許出願として刊行物１～３を示しています。

言い換えると、審判官は「出願人Aの特許出願と、刊行物１～３は、似ている」と判断したことになります。

まずはこんな流れです。


５．データの準備
---
さて、審判官は「出願人Aの特許出願と、刊行物１～３を、似ている」と判断したが、Doc2Vecは、審判官と同じように判断するのでしょうか？

では実際にどのように行うのか。
以前のブログでも引用させてもらった「@enta0701」さんのコードを改良させていたきまいた。
https://qiita.com/Chizaizizii/items/45a4e9538c12e2c9d5d7

入力データとして、次のようなものを用紙しました。

本願　　　:特開2014-223436（請求項部分を全文）
刊行物１　:特開2005-176862（詳細な説明部分を全文）
刊行物２　:特開2006-326215（詳細な説明部分を全文）
刊行物３　:特開2001-218930（詳細な説明部分を全文）
ランダム１:特開2012-123654（詳細な説明部分を全文）
ランダム２:特開2015-123654（詳細な説明部分を全文）

繰り返しになりますが、本願は、出願人Aの特許出願、刊行物１～３は、不服審判「不服2016-15403」の本文より抽出しています。
ランダム１、ランダム２は、僕がランダムに選んだ特許公報です(;´∀｀)

本願と刊行物１～３のグループ（仮にグループA）に対し、Doc2Vecの比較結果に有意な差がでることを期待し、ランダム（技術的に何の関連性もなさそうな特許公報）の要約を２つ（仮にグループB）ほど盛り込んでみました。

グループAとグループBの比較結果に差が出れば、Doc2Vecは「出願人Aの特許出願と、刊行物１～３を、似ている」と判断したと結論付けたいと思います(^▽^;)



６．実装
---
こんな感じです。

```py
# -*- 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', "刊行物１"), ('doc3', "刊行物２"), ('doc4', "刊行物３"), ('doc5', "ランダム１"), ('doc6', "ランダム２"))
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]))
```



７．結果
---
さて、結果はこんな感じになりました。

```
[[本願]
	刊行物２ : 0.8545494079589844
	刊行物３ : 0.7431389689445496
	刊行物１ : 0.7000955939292908
	ランダム２ : 0.5176839828491211
	ランダム１ : 0.3967837691307068
[刊行物１]
	本願 : 0.7000956535339355
	刊行物３ : 0.48298516869544983
	刊行物２ : 0.44776421785354614
	ランダム１ : 0.3875276446342468
	ランダム２ : 0.21002274751663208
[刊行物２]
	本願 : 0.8545494079589844
	刊行物１ : 0.44776421785354614
	刊行物３ : 0.3732856810092926
	ランダム２ : 0.2865113615989685
	ランダム１ : 0.22178468108177185
[刊行物３]
	本願 : 0.7431389093399048
	刊行物１ : 0.48298513889312744
	ランダム２ : 0.4452183246612549
	刊行物２ : 0.3732856810092926
	ランダム１ : 0.1128430962562561
[ランダム１]
	ランダム２ : 0.7021363973617554
	本願 : 0.3967837691307068
	刊行物１ : 0.3875276744365692
	刊行物２ : 0.22178471088409424
	刊行物３ : 0.1128431037068367
[ランダム２]
	ランダム１ : 0.7021363973617554
	本願 : 0.5176840424537659
	刊行物３ : 0.44521835446357727
	刊行物２ : 0.2865113615989685
	刊行物１ : 0.21002274751663208
```

この結果をみると、Doc2Vecは、本願に対して刊行物１〜３は似ている、本願に対しランダム１〜２は刊行物１〜３のようには似ていないと判断できているように見えます。

次は、もっといろいろと試してみたいと思います。