2

与えられた重みベクトルに基づいて配列をリサンプリングするwekaの実装を読んでいます。コードを読んだ後、この実装の基礎となるアルゴリズムが何であるかわかりません。さらに、次の2行のコードの使用法についてかなり混乱しています。

  Utils.normalize(probabilities, sumProbs / sumOfWeights);

// Make sure that rounding errors don't mess things up
probabilities[numInstances() - 1] = sumOfWeights;

何に使われているのかわかりません。以下はWekaからコピーされたコードです

Instances weka::core::Instances::resampleWithWeights(Random random,double[] weights )       
{

if (weights.length != numInstances()) {
  throw new IllegalArgumentException("weights.length != numInstances.");
}
Instances newData = new Instances(this, numInstances());
if (numInstances() == 0) {
  return newData;
}
double[] probabilities = new double[numInstances()];
double sumProbs = 0, sumOfWeights = Utils.sum(weights);
for (int i = 0; i < numInstances(); i++) {
  sumProbs += random.nextDouble();
  probabilities[i] = sumProbs;
}
Utils.normalize(probabilities, sumProbs / sumOfWeights);

// Make sure that rounding errors don't mess things up
probabilities[numInstances() - 1] = sumOfWeights;
int k = 0; int l = 0;
sumProbs = 0;
while ((k < numInstances() && (l < numInstances()))) {
  if (weights[l] < 0) {
  throw new IllegalArgumentException("Weights have to be positive.");
  }
  sumProbs += weights[l];
  while ((k < numInstances()) &&
       (probabilities[k] <= sumProbs)) { 
  newData.add(instance(l));
  newData.instance(k).setWeight(1);
  k++;
  }
  l++;
}
return newData;

}

4

1 に答える 1

0

最初のコードフラグメント:

Utils.normalize(probabilities, sumProbs / sumOfWeights);

probabilitiesの各要素を2番目の引数で除算するだけです。これは、probabilities最大要素がの配列から最大要素がの配列に変換されます。2番目のコード:sumProbssumOfWeights

probabilities[numInstances() - 1] = sumOfWeights;

最後の(最大)要素が実際にsumOfWeightsある種の丸め誤差によって破棄されたものであり、破棄されなかったことを確認するだけです。

編集これは、メソッド全体がどのように機能するかについての理論です。前半(との宣言までk)は、増加している(独立していない)乱数のベクトルとしてl生成され、最後は重みの合計です。probabilitiesこれは、区間[0、sumOfWeights]のランダムな分割です。これで、重み自体が同じ間​​隔のパーティションになります。暗黙的に、既存の各インスタンスは、重みベースのパーティションの各要素に1つずつ割り当てられます。

メソッドの後半は、(インデックスを使用してl)重みパーティションに沿って単純にステップします。ランダムパーティションが指定された重みパーティションに分類される回数だけ、 lthインスタンスをサンプリングします。この説明は少しぎこちない言葉で表現されていることに気づきました。おそらく、何が起こっているのかを示す写真が役立つでしょう。

0                                                   sumOfWeights
↓                                                       ↓

|     *   *         *       *               * *     *   * ← Random partition
|    ^      ^           ^      ^     ^     ^         ^  ^ ← Weights partition

   0     2        1        1       0     0       3     1  ← # of samples

メソッドの後半で*は、各重み区間(で囲まれている^)にランダムなパーティション境界(で示されている)がいくつあるかを単純にカウントします。少し考えてみると、これは、与えられた重みに応じて置換してランダムにサンプリングする有効な方法であることがわかります。

于 2012-12-06T23:00:40.447 に答える