以下、※の行は追記です。
現在やっていること
Pythonで機械学習を勉強しています。
現在、Web上のテキスト分類を行うDjangoアプリを作成中です。
※分類には、ナイーブベイズを用いています。
実現したいこと
分類の結果表示のために、学習済みの分類器クラスのインスタンスをviews.pyで使用したいです。
このクラスには主に、訓練を行うメソッドや事後確率を計算して分類するメソッドが実装されています。
学習を行い、終了と同時にDjangoのデータベースにその分類器のクラスのインスタンスを保存する。
この方法で試みていますが、自作クラスのインスタンスをDjangoデータベースに保存する仕方が分かりません。
どなたか、どうか私にご教授いただけないでしょうか...?
想定している処理
Djangoカスタムコマンドで、教師データの収集とそれのデータベースへの保存を行う。
↓
同じくカスタムコマンドで、教師データを基に学習を行う。
このとき、上記の過程で保存したデータを取得して学習させる。
※分類器・ナイーブベイズのクラス変数を宣言し、クラスメソッドで学習を行う。
↓
アプリのトップページ(index.html)でURLを入力し、そこのHTMLを取得する。
↓
HTMLを形態素解析し、分類を行う。
(ここで学習済みのナイーブベイズのクラス変数を使いたいのですが、取得できません。)
↓
別のページに移動して結果を表示する。
環境
Anaconda - 5.0.1
Django - 1.11.3
Python - 3.6.3
使用している外部ライブラリ
・requests - 2.18.4 → URL先からリソース取得
・beautifulsoup4 - 4.6.0 → スクレイピング
・janome - 0.3.5 → 形態素解析
追記(2017.12.16)
naosk8さん、ご回答誠にありがとうございます。追記が遅くなり、申し訳ありません。
分類は、ナイーブベイズの理論で行っています。
その分類器を保存して、ブラウザでの結果表示に再利用しようと考えています。
下記のクラスメソッドtrainで学習させた後、そのクラス変数をデータベースに保存します。
views.pyでデータベースから取得し、ブラウザ上に結果表示をするようにしたいです。
ナイーブベイズの分類器でも、データベースへの保存は不向きなのでしょうか。
ナイーブベイズによる分類器のコード
Python
1class NaiveBayes: 2 """ 3 ナイーブベイズを適用するクラス。 4 カスタムコマンドtrainで、このクラスのメソッドtrainを呼び出す。 5 その後、メソッドclassifierを呼び出し、分類を行う。 6 """ 7 def __init__(self): # コンストラクタ 8 # 学習データの全単語の集合(加算スムージング用。リストと異なり要素の順番は無い) 9 self.vocabularies = set() 10 # 学習データのカテゴリー毎の単語セット用 ex: {'花粉症対策': {'スギ花粉': 4, '薬': 2,...} } 11 self.word_count = {} 12 # 学習データのカテゴリー毎の文書数セット用 ex: {'花粉症対策': 16, ...} 13 self.category_count = {} 14 # 形態素解析ライブラリJanomeのインスタンス 15 self.t = Tokenizer() 16 # 学習済みかどうか 17 self.isTrained = False 18 19 def train(self, document, category): # 学習 20 # DBに保存した教師データのカラムdocを引数にとって形態素解析 21 word_list = self.t.tokenize(document) 22 for word in word_list: 23 # カテゴリー内の単語出現回数をUP 24 self.__word_count_up(word, category) 25 # カテゴリーの文書数をUP 26 self.__category_count_up(category) 27 28 def __word_count_up(self, word, category): # 学習データのカテゴリー内の単語出現回数をUP 29 # 新カテゴリーなら追加 30 self.word_count.setdefault(category, {}) 31 # カテゴリー内で新単語なら追加 32 self.word_count[category].setdefault(word, 0) 33 # カテゴリー内の単語出現回数をUP 34 self.word_count[category][word] += 1 35 # 学習データの全単語集合に加える(重複排除) 36 self.vocabularies.add(word) 37 38 def __category_count_up(self, category): # 学習データのカテゴリーの文書数をUP 39 # 新カテゴリーなら追加 40 self.category_count.setdefault(category, 0) 41 # カテゴリーの文書数をUP 42 self.category_count[category] += 1 43 44 def classifier(self, document): # 分類 45 # もっとも近いカテゴリ 46 best_category = None 47 # 最小整数値を設定 48 max_prob = -sys.maxsize 49 # 対象文書を形態素解析 50 word_list = self.t.tokenize(document) 51 # カテゴリ毎に文書内のカテゴリー出現率P(C|D)を求める 52 for category in self.category_count.keys(): 53 # 文書内のカテゴリー出現率P(C|D)を求める 54 prob = self.__score(word_list, category) 55 if prob > max_prob: 56 max_prob = prob 57 best_category = category 58 return best_category 59 60 def verify_acc(self) : # 精度検証 61 ok = 0 62 all_testdatas_list = list(CollectedData_test.objects.all()) 63 for test_data in all_testdatas_list: 64 print(ok) 65 cate_classify = self.classifier(test_data.doc) 66 if cate_classify == test_data.category: 67 ok += 1 68 # 正解率=正答数/テストデータの総数 69 acc = ok / len(Constant.ID_test.value) 70 return acc 71 72 def __score(self, word_list, category): # 文書内のカテゴリー出現率P(C|D) 73 # カテゴリー出現率P(C)を取得 (アンダーフロー対策で対数をとり、加算) 74 score = math.log(self.__prior_prob(category)) 75 # カテゴリー内の単語出現率を文書内のすべての単語で求める 76 for word in word_list: 77 # カテゴリー内の単語出現率P(Wn|C)を計算 (アンダーフロー対策で対数をとり加算) 78 score += math.log(self.__word_prob(word, category)) 79 return score 80 81 def __prior_prob(self, category): # カテゴリー出現率P(C) 82 # 学習データの対象カテゴリーの文書数 / 学習データの文書数合計 83 return float(self.category_count[category] / sum(self.category_count.values())) 84 85 def __word_prob(self, word, category): # カテゴリー内の単語出現率P(Wn|C) 86 # 単語のカテゴリー内出現回数 + 1 / カテゴリー内単語数 + 学習データの全単語数 (加算スムージング) 87 prob = (self.__in_category(word, category) + 1.0) / \ 88 (sum(self.word_count[category].values()) + \ 89 len(self.vocabularies) * 1.0) 90 return prob 91 92 def __in_category(self, word, category): # 単語のカテゴリー内出現回数を返す 93 if word in self.word_count[category]: 94 # 単語のカテゴリー内出現回数 95 return float(self.word_count[category][word]) 96 return 0.0
あなたの回答
tips
プレビュー