質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

0回答

562閲覧

Djangoのデータベースに、自作クラスの変数を保存する方法

Mocchan2718

総合スコア15

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2017/12/02 10:54

編集2017/12/16 14:17

以下、※の行は追記です。

現在やっていること

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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

naosk8

2017/12/16 07:12

的外れなことを言っていたらすみません。janomeで解体したパーツを、word2vecなどで分類していて、その"word2vec的な分類器"を保存して再利用したいということでしょうか。ちなみに、分類器は巨大になり得るのでデータベースへの保存には向かないと思いますが、blob形式のカラムを用意すれば保存できるのかなと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問