質問編集履歴
8
編集・追記依頼の対応
test
CHANGED
File without changes
|
test
CHANGED
@@ -1,10 +1,16 @@
|
|
1
|
+
以下、※の行は追記です。
|
2
|
+
|
3
|
+
|
4
|
+
|
1
5
|
現在やっていること
|
2
6
|
|
3
7
|
---
|
4
8
|
|
5
9
|
Pythonで機械学習を勉強しています。
|
6
10
|
|
7
|
-
現在、
|
11
|
+
現在、Web上のテキスト分類を行うDjangoアプリを作成中です。
|
12
|
+
|
13
|
+
※分類には、ナイーブベイズを用いています。
|
8
14
|
|
9
15
|
|
10
16
|
|
@@ -30,7 +36,7 @@
|
|
30
36
|
|
31
37
|
---
|
32
38
|
|
33
|
-
Djangoカスタムコマンドで、教師データの収集とデータベースへ保存
|
39
|
+
Djangoカスタムコマンドで、教師データの収集とそれのデータベースへの保存を行う。
|
34
40
|
|
35
41
|
↓
|
36
42
|
|
@@ -38,6 +44,8 @@
|
|
38
44
|
|
39
45
|
このとき、上記の過程で保存したデータを取得して学習させる。
|
40
46
|
|
47
|
+
※分類器・ナイーブベイズのクラス変数を宣言し、クラスメソッドで学習を行う。
|
48
|
+
|
41
49
|
↓
|
42
50
|
|
43
51
|
アプリのトップページ(index.html)でURLを入力し、そこのHTMLを取得する。
|
@@ -46,7 +54,7 @@
|
|
46
54
|
|
47
55
|
HTMLを形態素解析し、分類を行う。
|
48
56
|
|
49
|
-
|
57
|
+
(ここで学習済みのナイーブベイズのクラス変数を使いたいのですが、取得できません。)
|
50
58
|
|
51
59
|
↓
|
52
60
|
|
@@ -73,3 +81,229 @@
|
|
73
81
|
・beautifulsoup4 - 4.6.0 → スクレイピング
|
74
82
|
|
75
83
|
・janome - 0.3.5 → 形態素解析
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
追記(2017.12.16)
|
88
|
+
|
89
|
+
---
|
90
|
+
|
91
|
+
naosk8さん、ご回答誠にありがとうございます。追記が遅くなり、申し訳ありません。
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
分類は、ナイーブベイズの理論で行っています。
|
96
|
+
|
97
|
+
その分類器を保存して、ブラウザでの結果表示に再利用しようと考えています。
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
下記のクラスメソッドtrainで学習させた後、そのクラス変数をデータベースに保存します。
|
102
|
+
|
103
|
+
views.pyでデータベースから取得し、ブラウザ上に結果表示をするようにしたいです。
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
ナイーブベイズの分類器でも、データベースへの保存は不向きなのでしょうか。
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
ナイーブベイズによる分類器のコード
|
112
|
+
|
113
|
+
---
|
114
|
+
|
115
|
+
```Python
|
116
|
+
|
117
|
+
class NaiveBayes:
|
118
|
+
|
119
|
+
"""
|
120
|
+
|
121
|
+
ナイーブベイズを適用するクラス。
|
122
|
+
|
123
|
+
カスタムコマンドtrainで、このクラスのメソッドtrainを呼び出す。
|
124
|
+
|
125
|
+
その後、メソッドclassifierを呼び出し、分類を行う。
|
126
|
+
|
127
|
+
"""
|
128
|
+
|
129
|
+
def __init__(self): # コンストラクタ
|
130
|
+
|
131
|
+
# 学習データの全単語の集合(加算スムージング用。リストと異なり要素の順番は無い)
|
132
|
+
|
133
|
+
self.vocabularies = set()
|
134
|
+
|
135
|
+
# 学習データのカテゴリー毎の単語セット用 ex: {'花粉症対策': {'スギ花粉': 4, '薬': 2,...} }
|
136
|
+
|
137
|
+
self.word_count = {}
|
138
|
+
|
139
|
+
# 学習データのカテゴリー毎の文書数セット用 ex: {'花粉症対策': 16, ...}
|
140
|
+
|
141
|
+
self.category_count = {}
|
142
|
+
|
143
|
+
# 形態素解析ライブラリJanomeのインスタンス
|
144
|
+
|
145
|
+
self.t = Tokenizer()
|
146
|
+
|
147
|
+
# 学習済みかどうか
|
148
|
+
|
149
|
+
self.isTrained = False
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
def train(self, document, category): # 学習
|
154
|
+
|
155
|
+
# DBに保存した教師データのカラムdocを引数にとって形態素解析
|
156
|
+
|
157
|
+
word_list = self.t.tokenize(document)
|
158
|
+
|
159
|
+
for word in word_list:
|
160
|
+
|
161
|
+
# カテゴリー内の単語出現回数をUP
|
162
|
+
|
163
|
+
self.__word_count_up(word, category)
|
164
|
+
|
165
|
+
# カテゴリーの文書数をUP
|
166
|
+
|
167
|
+
self.__category_count_up(category)
|
168
|
+
|
169
|
+
|
170
|
+
|
171
|
+
def __word_count_up(self, word, category): # 学習データのカテゴリー内の単語出現回数をUP
|
172
|
+
|
173
|
+
# 新カテゴリーなら追加
|
174
|
+
|
175
|
+
self.word_count.setdefault(category, {})
|
176
|
+
|
177
|
+
# カテゴリー内で新単語なら追加
|
178
|
+
|
179
|
+
self.word_count[category].setdefault(word, 0)
|
180
|
+
|
181
|
+
# カテゴリー内の単語出現回数をUP
|
182
|
+
|
183
|
+
self.word_count[category][word] += 1
|
184
|
+
|
185
|
+
# 学習データの全単語集合に加える(重複排除)
|
186
|
+
|
187
|
+
self.vocabularies.add(word)
|
188
|
+
|
189
|
+
|
190
|
+
|
191
|
+
def __category_count_up(self, category): # 学習データのカテゴリーの文書数をUP
|
192
|
+
|
193
|
+
# 新カテゴリーなら追加
|
194
|
+
|
195
|
+
self.category_count.setdefault(category, 0)
|
196
|
+
|
197
|
+
# カテゴリーの文書数をUP
|
198
|
+
|
199
|
+
self.category_count[category] += 1
|
200
|
+
|
201
|
+
|
202
|
+
|
203
|
+
def classifier(self, document): # 分類
|
204
|
+
|
205
|
+
# もっとも近いカテゴリ
|
206
|
+
|
207
|
+
best_category = None
|
208
|
+
|
209
|
+
# 最小整数値を設定
|
210
|
+
|
211
|
+
max_prob = -sys.maxsize
|
212
|
+
|
213
|
+
# 対象文書を形態素解析
|
214
|
+
|
215
|
+
word_list = self.t.tokenize(document)
|
216
|
+
|
217
|
+
# カテゴリ毎に文書内のカテゴリー出現率P(C|D)を求める
|
218
|
+
|
219
|
+
for category in self.category_count.keys():
|
220
|
+
|
221
|
+
# 文書内のカテゴリー出現率P(C|D)を求める
|
222
|
+
|
223
|
+
prob = self.__score(word_list, category)
|
224
|
+
|
225
|
+
if prob > max_prob:
|
226
|
+
|
227
|
+
max_prob = prob
|
228
|
+
|
229
|
+
best_category = category
|
230
|
+
|
231
|
+
return best_category
|
232
|
+
|
233
|
+
|
234
|
+
|
235
|
+
def verify_acc(self) : # 精度検証
|
236
|
+
|
237
|
+
ok = 0
|
238
|
+
|
239
|
+
all_testdatas_list = list(CollectedData_test.objects.all())
|
240
|
+
|
241
|
+
for test_data in all_testdatas_list:
|
242
|
+
|
243
|
+
print(ok)
|
244
|
+
|
245
|
+
cate_classify = self.classifier(test_data.doc)
|
246
|
+
|
247
|
+
if cate_classify == test_data.category:
|
248
|
+
|
249
|
+
ok += 1
|
250
|
+
|
251
|
+
# 正解率=正答数/テストデータの総数
|
252
|
+
|
253
|
+
acc = ok / len(Constant.ID_test.value)
|
254
|
+
|
255
|
+
return acc
|
256
|
+
|
257
|
+
|
258
|
+
|
259
|
+
def __score(self, word_list, category): # 文書内のカテゴリー出現率P(C|D)
|
260
|
+
|
261
|
+
# カテゴリー出現率P(C)を取得 (アンダーフロー対策で対数をとり、加算)
|
262
|
+
|
263
|
+
score = math.log(self.__prior_prob(category))
|
264
|
+
|
265
|
+
# カテゴリー内の単語出現率を文書内のすべての単語で求める
|
266
|
+
|
267
|
+
for word in word_list:
|
268
|
+
|
269
|
+
# カテゴリー内の単語出現率P(Wn|C)を計算 (アンダーフロー対策で対数をとり加算)
|
270
|
+
|
271
|
+
score += math.log(self.__word_prob(word, category))
|
272
|
+
|
273
|
+
return score
|
274
|
+
|
275
|
+
|
276
|
+
|
277
|
+
def __prior_prob(self, category): # カテゴリー出現率P(C)
|
278
|
+
|
279
|
+
# 学習データの対象カテゴリーの文書数 / 学習データの文書数合計
|
280
|
+
|
281
|
+
return float(self.category_count[category] / sum(self.category_count.values()))
|
282
|
+
|
283
|
+
|
284
|
+
|
285
|
+
def __word_prob(self, word, category): # カテゴリー内の単語出現率P(Wn|C)
|
286
|
+
|
287
|
+
# 単語のカテゴリー内出現回数 + 1 / カテゴリー内単語数 + 学習データの全単語数 (加算スムージング)
|
288
|
+
|
289
|
+
prob = (self.__in_category(word, category) + 1.0) / \
|
290
|
+
|
291
|
+
(sum(self.word_count[category].values()) + \
|
292
|
+
|
293
|
+
len(self.vocabularies) * 1.0)
|
294
|
+
|
295
|
+
return prob
|
296
|
+
|
297
|
+
|
298
|
+
|
299
|
+
def __in_category(self, word, category): # 単語のカテゴリー内出現回数を返す
|
300
|
+
|
301
|
+
if word in self.word_count[category]:
|
302
|
+
|
303
|
+
# 単語のカテゴリー内出現回数
|
304
|
+
|
305
|
+
return float(self.word_count[category][word])
|
306
|
+
|
307
|
+
return 0.0
|
308
|
+
|
309
|
+
```
|
7
test
CHANGED
File without changes
|
test
CHANGED
File without changes
|
6
更新
test
CHANGED
File without changes
|
test
CHANGED
File without changes
|
5
文章の修正
test
CHANGED
File without changes
|
test
CHANGED
File without changes
|
4
タグの変更
test
CHANGED
File without changes
|
test
CHANGED
File without changes
|
3
test
CHANGED
@@ -1 +1 @@
|
|
1
|
-
Djangoのデータベース
|
1
|
+
Djangoのデータベースに、自作クラスの変数を保存する方法
|
test
CHANGED
File without changes
|
2
文章の修正・加筆
test
CHANGED
File without changes
|
test
CHANGED
@@ -18,15 +18,9 @@
|
|
18
18
|
|
19
19
|
|
20
20
|
|
21
|
-
|
21
|
+
学習を行い、終了と同時にDjangoのデータベースにその分類器のクラスのインスタンスを保存する。
|
22
22
|
|
23
|
-
1.インスタンス変数をグローバル化して、コマンドを実行してからviews.py(分類器クラスのインスタンスimport済み)を動かす。
|
24
|
-
|
25
|
-
2.学習を行い、終了したと同時にDjangoのデータベースにその分類器のクラスのインスタンスを保存する。
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
この方法で試みていますが、自作クラスのインスタンスをDjangoデータベースに保存する仕方が分かりません。
|
30
24
|
|
31
25
|
どなたか、どうか私にご教授いただけないでしょうか...?
|
32
26
|
|
@@ -64,18 +58,18 @@
|
|
64
58
|
|
65
59
|
---
|
66
60
|
|
67
|
-
Anaconda 5.0.1
|
61
|
+
Anaconda - 5.0.1
|
68
62
|
|
69
|
-
Django 1.11.3
|
63
|
+
Django - 1.11.3
|
70
64
|
|
71
|
-
Python 3.6.3
|
65
|
+
Python - 3.6.3
|
72
66
|
|
73
67
|
|
74
68
|
|
75
69
|
使用している外部ライブラリ
|
76
70
|
|
77
|
-
・requests 2.18.4 URL先からリソース取得
|
71
|
+
・requests - 2.18.4 → URL先からリソース取得
|
78
72
|
|
79
|
-
・beautifulsoup4 4.6.0 スクレイピング
|
73
|
+
・beautifulsoup4 - 4.6.0 → スクレイピング
|
80
74
|
|
81
|
-
・janome 0.3.5 形態素解析
|
75
|
+
・janome - 0.3.5 → 形態素解析
|
1
脱字
test
CHANGED
File without changes
|
test
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
Pythonで機械学習を勉強しています。
|
6
6
|
|
7
|
-
現在
|
7
|
+
現在、ベイズの考え方を用いてWeb上のテキスト分類を行うDjangoアプリを作成中です。
|
8
8
|
|
9
9
|
|
10
10
|
|