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

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

ただいまの
回答率

90.76%

  • Python 3.x

    5368questions

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

  • Django

    917questions

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

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

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 274

Mocchan2718

score 3

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

現在やっていること

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でデータベースから取得し、ブラウザ上に結果表示をするようにしたいです。

ナイーブベイズの分類器でも、データベースへの保存は不向きなのでしょうか。

ナイーブベイズによる分類器のコード

class NaiveBayes:
    """
    ナイーブベイズを適用するクラス。
    カスタムコマンドtrainで、このクラスのメソッドtrainを呼び出す。
    その後、メソッドclassifierを呼び出し、分類を行う。
    """
    def __init__(self): # コンストラクタ
        # 学習データの全単語の集合(加算スムージング用。リストと異なり要素の順番は無い)
        self.vocabularies = set()
        # 学習データのカテゴリー毎の単語セット用 ex: {'花粉症対策': {'スギ花粉': 4, '薬': 2,...} }
        self.word_count = {}
        # 学習データのカテゴリー毎の文書数セット用 ex: {'花粉症対策': 16, ...}
        self.category_count = {}
        # 形態素解析ライブラリJanomeのインスタンス
        self.t = Tokenizer()
        # 学習済みかどうか
        self.isTrained = False

    def train(self, document, category): # 学習
        # DBに保存した教師データのカラムdocを引数にとって形態素解析
        word_list = self.t.tokenize(document)
        for word in word_list:
            # カテゴリー内の単語出現回数をUP
            self.__word_count_up(word, category)
        # カテゴリーの文書数をUP
        self.__category_count_up(category)

    def __word_count_up(self, word, category): # 学習データのカテゴリー内の単語出現回数をUP
        # 新カテゴリーなら追加
        self.word_count.setdefault(category, {})
        # カテゴリー内で新単語なら追加
        self.word_count[category].setdefault(word, 0)
        # カテゴリー内の単語出現回数をUP
        self.word_count[category][word] += 1
        # 学習データの全単語集合に加える(重複排除)
        self.vocabularies.add(word)

    def __category_count_up(self, category): # 学習データのカテゴリーの文書数をUP
        # 新カテゴリーなら追加
        self.category_count.setdefault(category, 0)
        # カテゴリーの文書数をUP
        self.category_count[category] += 1

    def classifier(self, document): # 分類
        # もっとも近いカテゴリ
        best_category = None
        # 最小整数値を設定
        max_prob = -sys.maxsize
        # 対象文書を形態素解析
        word_list = self.t.tokenize(document)
        # カテゴリ毎に文書内のカテゴリー出現率P(C|D)を求める
        for category in self.category_count.keys():
            # 文書内のカテゴリー出現率P(C|D)を求める
            prob = self.__score(word_list, category)
            if prob > max_prob:
                max_prob = prob
                best_category = category
        return best_category

    def verify_acc(self) : # 精度検証
        ok = 0
        all_testdatas_list = list(CollectedData_test.objects.all())
        for test_data in all_testdatas_list:
            print(ok)
            cate_classify = self.classifier(test_data.doc)
            if cate_classify == test_data.category:
                ok += 1
        # 正解率=正答数/テストデータの総数
        acc = ok / len(Constant.ID_test.value)
        return acc

    def __score(self, word_list, category): # 文書内のカテゴリー出現率P(C|D)
        # カテゴリー出現率P(C)を取得 (アンダーフロー対策で対数をとり、加算)
        score = math.log(self.__prior_prob(category))
        # カテゴリー内の単語出現率を文書内のすべての単語で求める
        for word in word_list:
            # カテゴリー内の単語出現率P(Wn|C)を計算 (アンダーフロー対策で対数をとり加算)
            score += math.log(self.__word_prob(word, category))
        return score

    def __prior_prob(self, category): # カテゴリー出現率P(C)
        # 学習データの対象カテゴリーの文書数 / 学習データの文書数合計
        return float(self.category_count[category] / sum(self.category_count.values()))

    def __word_prob(self, word, category): # カテゴリー内の単語出現率P(Wn|C)
        # 単語のカテゴリー内出現回数 + 1 / カテゴリー内単語数 + 学習データの全単語数 (加算スムージング)
        prob = (self.__in_category(word, category) + 1.0) / \
                   (sum(self.word_count[category].values()) + \
                    len(self.vocabularies) * 1.0)
        return prob

    def __in_category(self, word, category): # 単語のカテゴリー内出現回数を返す
        if word in self.word_count[category]:
            # 単語のカテゴリー内出現回数
            return float(self.word_count[category][word])
        return 0.0
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正の依頼

  • naosk8

    2017/12/16 16:12

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

    キャンセル

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

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

  • ただいまの回答率 90.76%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Python 3.x

    5368questions

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

  • Django

    917questions

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