teratail header banner
teratail header banner
質問するログイン新規登録

質問編集履歴

2

インデントの修正

2019/02/04 13:38

投稿

shut_student
shut_student

スコア10

title CHANGED
File without changes
body CHANGED
@@ -42,22 +42,23 @@
42
42
  with open(path, 'r', errors='ignore') as f:
43
43
  return f.read()
44
44
 
45
+ #不要な部分の削除
45
46
  def trim_doc(doc):
46
- lines = doc.splitlines()
47
+ lines = doc.splitlines()
47
- valid_lines = []
48
+ valid_lines = []
48
- is_valid = Falseadsf
49
+ is_valid = False
49
- horizontal_rule_cnt = 0
50
+ horizontal_rule_cnt = 0
50
- break_cnt = 0
51
+ break_cnt = 0
51
- for line in lines:
52
+ for line in lines:
52
- if horizontal_rule_cnt < 2 and 'Reply-to:' in line:
53
+ if horizontal_rule_cnt < 2 and 'Reply-to:' in line:
53
- horizontal_rule_cnt += 1
54
+ horizontal_rule_cnt += 1
54
- is_valid = horizontal_rule_cnt == 2
55
+ is_valid = horizontal_rule_cnt == 2
55
- continue
56
+ continue
56
- if not(is_valid):
57
+ if not(is_valid):
57
- continue
58
+ continue
58
- break_cnt = 0asfd
59
+ break_cnt = 0
59
- valid_lines.append(line)
60
+ valid_lines.append(line)
60
- return ''.join(valid_lines)
61
+ return ''.join(valid_lines)
61
62
 
62
63
  #文章から単語に分割して返す
63
64
  def split_into_words(doc, name=''):
@@ -69,7 +70,7 @@
69
70
  chunks = line.split("\t")
70
71
  if len(chunks) > 3 and (chunks[3].startswith('動詞') or chunks[3].startswith('形容詞') or (chunks[3].startswith('名詞') and not chunks[3].startswith('名詞-数'))):
71
72
  words.append(chunks[0])
72
- return LabeledSentence(words=words, tags=[name])
73
+ return LabeledSentence(words=words, tags=[name])
73
74
 
74
75
  #ファイルから単語のリストを取得
75
76
  def corpus_to_sentences(corpus):

1

書式の改善

2019/02/04 13:38

投稿

shut_student
shut_student

スコア10

title CHANGED
File without changes
body CHANGED
@@ -1,15 +1,129 @@
1
+ ###前提・実現したいこと
1
- doc2vecを使って文書の類似度を出そうとしてます。
2
+ doc2vecを
2
3
  VirtualBoxのcentOS上で、python3.6を使ってdoc2vecを動かしています。
3
4
 
5
+ 実現したいプログラムは
6
+ ・類似する単語の検索機能
7
+ です。
8
+
9
+ 参考にしたプログラムはこちらのサイトにあったものです。
4
10
  https://qiita.com/akira_/items/f9bb46cad6834da32367
11
+ 文書を学習するプログラムと検索するプログラムは分かれていて、
5
- このページを参考にしてプログラムを構築しました。
12
+ 学習するプログラムに問題が発生しました。
6
- エラーが出るところは直して、ほとんど正常に動作するのですが、実行を繰り返すたびに精度が落ちていきます。
7
13
 
8
- 別のサイト(https://kitayamalab.wordpress.com/2016/11/14/python-%E3%81%A8-gensim-%E3%81%A7-doc2vec-%E3%82%92%E4%BD%BF%E3%81%86/)を参考にして、簡単な検証を行っても、プログラムを実行するたび精度が落ちていきます。
14
+ 与えたプログラムは電子メールプレーンテキストしたもので、
9
15
 
16
+ ```
17
+ def trim_doc(doc):
18
+ ```
19
+ で不要な部分を削除してから与えました。
20
+
21
+ 実際に書いたコードがこちらです。
22
+ ```
23
+ import os
24
+ import sys
25
+ import MeCab
26
+ import collections
27
+ from gensim import models
28
+ from gensim.models.doc2vec import LabeledSentence
29
+
30
+ INPUT_DOC_DIR = './mail'
31
+ OUTPUT_MODEL = 'doc2vec.model'
32
+ PASSING_PRECISION = 93
33
+
10
- 1つ目プログラム実行結果は
34
+ #すべてファイルリストを取得
35
+ def get_all_files(directory):
36
+ for root, dirs, files in os.walk(directory):
37
+ for file in files:
38
+ yield os.path.join(root, file)
39
+
40
+ #ファイルから文章を返す
41
+ def read_document(path):
42
+ with open(path, 'r', errors='ignore') as f:
43
+ return f.read()
44
+
45
+ def trim_doc(doc):
46
+ lines = doc.splitlines()
47
+ valid_lines = []
48
+ is_valid = Falseadsf
49
+ horizontal_rule_cnt = 0
50
+ break_cnt = 0
51
+ for line in lines:
52
+ if horizontal_rule_cnt < 2 and 'Reply-to:' in line:
53
+ horizontal_rule_cnt += 1
54
+ is_valid = horizontal_rule_cnt == 2
55
+ continue
56
+ if not(is_valid):
57
+ continue
58
+ break_cnt = 0asfd
59
+ valid_lines.append(line)
60
+ return ''.join(valid_lines)
61
+
62
+ #文章から単語に分割して返す
63
+ def split_into_words(doc, name=''):
64
+ mecab = MeCab.Tagger("-Ochasen")
65
+ valid_doc = trim_doc(doc)
66
+ lines = mecab.parse(doc).splitlines()
67
+ words = []
68
+ for line in lines:
69
+ chunks = line.split("\t")
70
+ if len(chunks) > 3 and (chunks[3].startswith('動詞') or chunks[3].startswith('形容詞') or (chunks[3].startswith('名詞') and not chunks[3].startswith('名詞-数'))):
71
+ words.append(chunks[0])
72
+ return LabeledSentence(words=words, tags=[name])
73
+
74
+ #ファイルから単語のリストを取得
75
+ def corpus_to_sentences(corpus):
76
+ docs=[read_document(x) for x in corpus]
77
+ for idx, (doc, name) in enumerate(zip(docs, corpus)):
78
+ sys.stdout.write('\r前処理{}/{}'.format(idx, len(corpus)))
79
+ yield split_into_words(doc, name)
80
+
81
+ #学習
82
+ def train(sentences):
83
+ model = models.Doc2Vec(alpha=0.0015, sample=1e-4, min_count=1, workers=4)
84
+ model.build_vocab(sentences)
85
+ for x in range(30):
86
+ print(x)
87
+ model.train(sentences, total_examples=model.corpus_count, epochs=model.iter)
88
+ ranks = []
89
+ for doc_id in range(100):
90
+ inferred_vector = model.infer_vector(sentences[doc_id].words)
91
+ sims = model.docvecs.most_similar([inferred_vector], topn=len(model.docvecs))
92
+ rank = [docid for docid, sim in sims].index(sentences[doc_id].tags[0])
93
+ ranks.append(rank)
94
+ print(collections.Counter(ranks))
95
+ if collections.Counter(ranks)[0] >= PASSING_PRECISION:
96
+ break
97
+ return model
98
+
99
+ if __name__ == '__main__':
100
+ corpus = list(get_all_files(INPUT_DOC_DIR))
101
+ sentences = list(corpus_to_sentences(corpus))
102
+ print()
103
+ model = train(sentences)
104
+ model.save(OUTPUT_MODEL)
105
+ ```
106
+
107
+ 下の部分で学習と評価を行っています。
108
+ ```
109
+ for x in range(30):
110
+ print(x)
111
+ model.train(sentences, total_examples=model.corpus_count, epochs=model.iter)
112
+ ranks = []
113
+ for doc_id in range(100):
114
+ inferred_vector = model.infer_vector(sentences[doc_id].words)
115
+ sims = model.docvecs.most_similar([inferred_vector], topn=len(model.docvecs))
116
+ rank = [docid for docid, sim in sims].index(sentences[doc_id].tags[0])
117
+ ranks.append(rank)
118
+ print(collections.Counter(ranks))
119
+ if collections.Counter(ranks)[0] >= PASSING_PRECISION:
120
+ break
121
+ ```
122
+ 評価は、学習した文章のうち100個で類似の文章を検索し、最も類似度の高い文章が自分自身だった回数で行います。
123
+
124
+ 評価の出力結果は以下の通りです。
125
+ ```
11
126
  $python3.6 program_v1.py
12
- 前処理 3950/3951
13
127
  0
14
128
  Counter({0: 36, 2: 8, 1: 5, 3: 3, 62: 2, 8: 2, 3721: 1, 2457: 1, 296: 1,(以下略)})
15
129
  1
@@ -19,11 +133,15 @@
19
133
  3
20
134
  Counter({1: 2, 3891: 2, 3941: 2, 5: 2, 2880: 2, 0: 2, 2057: 1, 1166: 1, 3399: 1,(以下略)})
21
135
  以下略
136
+ ```
137
+ 2行目の0,4行目の1 などの数字は学習回数で、
138
+ Counterはの:の左は文書、右は最も類似度の高い文書が自分自身だった回数を表しています。
22
139
 
23
- このようになります。
140
+ ###発生している問題
141
+ 学習を繰り返すたびに自分自身を示す回数が減ってしまうのは何が原因なのでしょうか。
24
142
 
143
+ また、初めてプログラムを実行したとき、評価で自分自信だった回数は最大36回でした。
25
- 2つ目のプログラムも最初の2回ぐらいは参考にしたサイト同じ結果なのですが34回目と繰り返すたびにおかしな結果になってします。
144
+ 後、作成されたモデルを削除して、再びプログラムを実行したところ評価で自分自身だった数は多くても4回くらす。
145
+ なぜ、モデルを作り直したはずなのに、最初に実行した時と似た結果にならないのでしょうか。
26
146
 
27
- 何が原因だと考えられるでしょうか。
28
- また、どのような解決策があるでしょうか
29
147
  よろしくお願いします。