質問編集履歴

2

インデントの修正

2019/02/04 13:38

投稿

shut_student
shut_student

スコア10

test CHANGED
File without changes
test CHANGED
@@ -86,37 +86,39 @@
86
86
 
87
87
 
88
88
 
89
+ #不要な部分の削除
90
+
89
91
  def trim_doc(doc):
90
92
 
91
- lines = doc.splitlines()
93
+ lines = doc.splitlines()
92
-
94
+
93
- valid_lines = []
95
+ valid_lines = []
94
-
96
+
95
- is_valid = Falseadsf
97
+ is_valid = False
96
-
98
+
97
- horizontal_rule_cnt = 0
99
+ horizontal_rule_cnt = 0
98
-
100
+
99
- break_cnt = 0
101
+ break_cnt = 0
100
-
102
+
101
- for line in lines:
103
+ for line in lines:
102
-
104
+
103
- if horizontal_rule_cnt < 2 and 'Reply-to:' in line:
105
+ if horizontal_rule_cnt < 2 and 'Reply-to:' in line:
104
-
106
+
105
- horizontal_rule_cnt += 1
107
+ horizontal_rule_cnt += 1
106
-
108
+
107
- is_valid = horizontal_rule_cnt == 2
109
+ is_valid = horizontal_rule_cnt == 2
108
-
110
+
109
- continue
111
+ continue
110
-
112
+
111
- if not(is_valid):
113
+ if not(is_valid):
112
-
114
+
113
- continue
115
+ continue
114
-
116
+
115
- break_cnt = 0asfd
117
+ break_cnt = 0
116
-
118
+
117
- valid_lines.append(line)
119
+ valid_lines.append(line)
118
-
120
+
119
- return ''.join(valid_lines)
121
+ return ''.join(valid_lines)
120
122
 
121
123
 
122
124
 
@@ -140,7 +142,7 @@
140
142
 
141
143
  words.append(chunks[0])
142
144
 
143
- return LabeledSentence(words=words, tags=[name])
145
+ return LabeledSentence(words=words, tags=[name])
144
146
 
145
147
 
146
148
 

1

書式の改善

2019/02/04 13:38

投稿

shut_student
shut_student

スコア10

test CHANGED
File without changes
test CHANGED
@@ -1,27 +1,255 @@
1
+ ###前提・実現したいこと
2
+
1
- doc2vecを使っ文書の類似度を出そうとしています。
3
+ doc2vecを用い
2
4
 
3
5
  VirtualBoxのcentOS上で、python3.6を使ってdoc2vecを動かしています。
4
6
 
5
7
 
6
8
 
9
+ 実現したいプログラムは
10
+
11
+ ・類似する単語の検索機能
12
+
13
+ です。
14
+
15
+
16
+
17
+ 参考にしたプログラムはこちらのサイトにあったものです。
18
+
7
19
  https://qiita.com/akira_/items/f9bb46cad6834da32367
8
20
 
9
- このページ参考にしてプログラムを構築しました。
10
-
11
- エラーが出るところは直して、ほとんど正常に動作するのですが、実行を繰り返すたび精度落ちていき
12
-
13
-
14
-
15
- 別のサイト(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/)を参考にして、簡単な検証を行っても、プログラムを実行するびに精度が落ちていきます。
16
-
17
-
18
-
19
- 1つ目のプログラムの実行結果は
21
+ 文書学習するプログラムと検索するプログラムは分かれていて、
22
+
23
+ 学習するプログラム問題発生しした
24
+
25
+
26
+
27
+ 与えたプログラムは電子メールプレーンテキストにしもので、
28
+
29
+
30
+
31
+ ```
32
+
33
+ def trim_doc(doc):
34
+
35
+ ```
36
+
37
+ で不要な部分を削除してから与えました。
38
+
39
+
40
+
41
+ 実際に書いたコードがこちらです。
42
+
43
+ ```
44
+
45
+ import os
46
+
47
+ import sys
48
+
49
+ import MeCab
50
+
51
+ import collections
52
+
53
+ from gensim import models
54
+
55
+ from gensim.models.doc2vec import LabeledSentence
56
+
57
+
58
+
59
+ INPUT_DOC_DIR = './mail'
60
+
61
+ OUTPUT_MODEL = 'doc2vec.model'
62
+
63
+ PASSING_PRECISION = 93
64
+
65
+
66
+
67
+ #すべてのファイルのリストを取得
68
+
69
+ def get_all_files(directory):
70
+
71
+ for root, dirs, files in os.walk(directory):
72
+
73
+ for file in files:
74
+
75
+ yield os.path.join(root, file)
76
+
77
+
78
+
79
+ #ファイルから文章を返す
80
+
81
+ def read_document(path):
82
+
83
+ with open(path, 'r', errors='ignore') as f:
84
+
85
+ return f.read()
86
+
87
+
88
+
89
+ def trim_doc(doc):
90
+
91
+ lines = doc.splitlines()
92
+
93
+ valid_lines = []
94
+
95
+ is_valid = Falseadsf
96
+
97
+ horizontal_rule_cnt = 0
98
+
99
+ break_cnt = 0
100
+
101
+ for line in lines:
102
+
103
+ if horizontal_rule_cnt < 2 and 'Reply-to:' in line:
104
+
105
+ horizontal_rule_cnt += 1
106
+
107
+ is_valid = horizontal_rule_cnt == 2
108
+
109
+ continue
110
+
111
+ if not(is_valid):
112
+
113
+ continue
114
+
115
+ break_cnt = 0asfd
116
+
117
+ valid_lines.append(line)
118
+
119
+ return ''.join(valid_lines)
120
+
121
+
122
+
123
+ #文章から単語に分割して返す
124
+
125
+ def split_into_words(doc, name=''):
126
+
127
+ mecab = MeCab.Tagger("-Ochasen")
128
+
129
+ valid_doc = trim_doc(doc)
130
+
131
+ lines = mecab.parse(doc).splitlines()
132
+
133
+ words = []
134
+
135
+ for line in lines:
136
+
137
+ chunks = line.split("\t")
138
+
139
+ if len(chunks) > 3 and (chunks[3].startswith('動詞') or chunks[3].startswith('形容詞') or (chunks[3].startswith('名詞') and not chunks[3].startswith('名詞-数'))):
140
+
141
+ words.append(chunks[0])
142
+
143
+ return LabeledSentence(words=words, tags=[name])
144
+
145
+
146
+
147
+ #ファイルから単語のリストを取得
148
+
149
+ def corpus_to_sentences(corpus):
150
+
151
+ docs=[read_document(x) for x in corpus]
152
+
153
+ for idx, (doc, name) in enumerate(zip(docs, corpus)):
154
+
155
+ sys.stdout.write('\r前処理{}/{}'.format(idx, len(corpus)))
156
+
157
+ yield split_into_words(doc, name)
158
+
159
+
160
+
161
+ #学習
162
+
163
+ def train(sentences):
164
+
165
+ model = models.Doc2Vec(alpha=0.0015, sample=1e-4, min_count=1, workers=4)
166
+
167
+ model.build_vocab(sentences)
168
+
169
+ for x in range(30):
170
+
171
+ print(x)
172
+
173
+ model.train(sentences, total_examples=model.corpus_count, epochs=model.iter)
174
+
175
+ ranks = []
176
+
177
+ for doc_id in range(100):
178
+
179
+ inferred_vector = model.infer_vector(sentences[doc_id].words)
180
+
181
+ sims = model.docvecs.most_similar([inferred_vector], topn=len(model.docvecs))
182
+
183
+ rank = [docid for docid, sim in sims].index(sentences[doc_id].tags[0])
184
+
185
+ ranks.append(rank)
186
+
187
+ print(collections.Counter(ranks))
188
+
189
+ if collections.Counter(ranks)[0] >= PASSING_PRECISION:
190
+
191
+ break
192
+
193
+ return model
194
+
195
+
196
+
197
+ if __name__ == '__main__':
198
+
199
+ corpus = list(get_all_files(INPUT_DOC_DIR))
200
+
201
+ sentences = list(corpus_to_sentences(corpus))
202
+
203
+ print()
204
+
205
+ model = train(sentences)
206
+
207
+ model.save(OUTPUT_MODEL)
208
+
209
+ ```
210
+
211
+
212
+
213
+ 下の部分で学習と評価を行っています。
214
+
215
+ ```
216
+
217
+ for x in range(30):
218
+
219
+ print(x)
220
+
221
+ model.train(sentences, total_examples=model.corpus_count, epochs=model.iter)
222
+
223
+ ranks = []
224
+
225
+ for doc_id in range(100):
226
+
227
+ inferred_vector = model.infer_vector(sentences[doc_id].words)
228
+
229
+ sims = model.docvecs.most_similar([inferred_vector], topn=len(model.docvecs))
230
+
231
+ rank = [docid for docid, sim in sims].index(sentences[doc_id].tags[0])
232
+
233
+ ranks.append(rank)
234
+
235
+ print(collections.Counter(ranks))
236
+
237
+ if collections.Counter(ranks)[0] >= PASSING_PRECISION:
238
+
239
+ break
240
+
241
+ ```
242
+
243
+ 評価は、学習した文章のうち100個で類似の文章を検索し、最も類似度の高い文章が自分自身だった回数で行います。
244
+
245
+
246
+
247
+ 評価の出力結果は以下の通りです。
248
+
249
+ ```
20
250
 
21
251
  $python3.6 program_v1.py
22
252
 
23
- 前処理 3950/3951
24
-
25
253
  0
26
254
 
27
255
  Counter({0: 36, 2: 8, 1: 5, 3: 3, 62: 2, 8: 2, 3721: 1, 2457: 1, 296: 1,(以下略)})
@@ -40,18 +268,26 @@
40
268
 
41
269
  以下略
42
270
 
43
-
271
+ ```
272
+
44
-
273
+ 2行目の0,4行目の1 などの数字は学習回数で、
274
+
275
+ Counterはの:の左は文書、右は最も類似度の高い文書が自分自身だった回数を表しています。
276
+
277
+
278
+
45
- このようになります。
279
+ ###発生している問題
280
+
46
-
281
+ 学習を繰り返すたびに自分自身を示す回数が減ってしまうのは何が原因なのでしょうか。
282
+
283
+
284
+
47
-
285
+ また、初めてプログラムを実行したとき、評価で自分自信だった回数は最大36回でした。
48
-
286
+
49
- 2つ目のプログラムも最初の2回ぐらいは参考にしたサイト同じ結果なのすが、34回目と繰り返すたびにおかしな結果になってします。
287
+ 後、作成されたモデルを削除して、再びプログラムを実行したところ、評価自分自身だった数は多くても4回くらす。
50
-
51
-
52
-
53
- 何が原因だと考えられるでしょうか。
288
+
54
-
55
- た、ような解決策があるでしょうか
289
+ なぜ、モデルを作り直しはずなのに最初に実行した時と似た結果にならないのでしょうか
290
+
291
+
56
292
 
57
293
  よろしくお願いします。