17

私はJavaに不慣れで、単純な単純ベイズ分類器を作成して練習しています。私はまだオブジェクトのインスタンス化に慣れていないので、HashMapsのHashMapを初期化するために何をすべきか疑問に思います。分類子に新しい観測値を挿入するときに、特定のクラスの表示されていない機能名の新しいHashMapを作成できますが、初期化する必要がありますか?

import java.util.HashMap;

public class NaiveBayes {

    private HashMap<String, Integer> class_counts;
    private HashMap<String, HashMap<String, Integer>> class_feature_counts;

    public NaiveBayes() {
        class_counts = new HashMap<String, Integer>();
        // do I need to initialize class_feature_counts?
    }

    public void insert() {
        // todo
        // I think I can create new hashmaps on the fly here for class_feature_counts
    }

    public String classify() {
        // stub 
        return "";
    }

    // Naive Scoring:
    // p( c | f_1, ... f_n) =~ p(c) * p(f_1|c) ... * p(f_n|c)
    private double get_score(String category, HashMap features) {
       // stub
       return 0.0;
    }

    public static void main(String[] args) {
        NaiveBayes bayes = new NaiveBayes();
       // todo
     }
}

この質問は単純ベイズ分類器に固有のものではなく、コンテキストを提供すると思っただけであることに注意してください。

4

4 に答える 4

23

はい、初期化する必要があります。

class_feature_counts = new HashMap<String, HashMap<String, Integer>>();

class_feature_countsに値を追加する場合は、それもインスタンス化する必要があります。

HashMap<String, Integer> val = new HashMap<String, Integer>();
// Do what you want to do with val
class_feature_counts.put("myKey", val);
于 2013-03-25T22:52:56.937 に答える
14

マップのマップのような再帰的な一般的なデータ構造は、完全に悪い考えではありませんが、リファクタリングできるものを示していることがよくあります。内部マップは、単なる地図。これらの内部オブジェクトを初期化する必要がありますが、多くの場合、開発するためのはるかにクリーンで明確な方法です。

たとえば、Map<A,Map<B,C>>AからThingへのマップを実際に保存していることがよくありますが、Thingの保存方法は偶然にもマップです。Map<A,Thing>Thingがマップであるという事実を隠し、代わりに、Thingが次のように定義されている場所のマッピングを保存する方がクリーンで簡単であることがよくあります。

public class Thing {
    // Map is guaranteed to be initialized if a Thing exists
    private Map<B,C> data = new Map<B,C>();

    // operations on data, like get and put
    // now can have sanity checks you couldn't enforce when the map was public
}

また、GuavaのMulitmap / Multisetユーティリティを調べてください。これらは、このような場合に非常に役立ちます。特に、内部オブジェクトの初期化を自動的に実行します。あなたのケースで注目すべきは、実装するときはいつでもMap<E, Integer>、Guavaマルチセットが本当に必要なことです。よりクリーンでクリア。

于 2013-03-25T22:54:01.747 に答える
2

参照変数を介して使用する前に、オブジェクトを作成する必要があります。そのオブジェクトがどれほど複雑であるかは関係ありません。最も一般的なケースですが、コンストラクターで初期化する必要はありません。必要に応じて、代わりに「遅延初期化」を使用することをお勧めします。

于 2013-03-25T22:51:19.907 に答える
2
  1. 変数をで宣言しないでくださいHashMap。制限が多すぎます。
  2. はい、初期化する必要がありますclass_feature_counts。エントリを追加するので、有効なマップである必要があります。実際、それぞれを開始する方法は1つしかないため、コンストラクターではなく宣言時に初期化してください。今までにJava7を使用していることを願っています。この方法の方が簡単です。

    private Map <String、Integer> classCounts = new HashMap <>();

    private Map <String、Map <String、Integer >> classFeatureCounts = new HashMap <>();

コンパイラは<>から型を推測します。また、変数名を標準のJavaキャメルケーススタイルに変更しました。接続されていますclassCountsか?classFeatureCounts

于 2013-03-25T22:57:10.573 に答える