2016-09-06 3 views
3

アレイの突然の変化をどうやって見つけますか?両方の例でアレイの突然の変化をすべて検出する

1,3,8,14,58,62,69 
In this case, there is a jump from 14 to 58 

OR

79,77,68,61,9,3,1 
In this case, there is a drop from 61 to 9 

は、大小のジャンプがあります。たとえば、次の配列を持っている場合。たとえば、2番目のケースでは、77から68までの小さなドロップがあります。しかし、より大きなジャンプ/ドロップが見つかった場合、これは無視しなければなりません。私は私の心の中でアルゴリズムを以下しているが、私は、これはすべての可能なケースをカバーするかどうかわからない:

ALGO 
Iterate over array 
Diff (i+1)-i 
store first difference in a variable 
if next diff is bigger than previous then overwrite 

次の例では、このALGOは、次のような場合のために動作しません。

あり
1, 2, 4, 6, 34, 38, 41, 67, 69, 71 

この配列の2つのジャンプです。したがって、それはのように配置する必要があります

[1, 2, 4, 6], [34, 38, 41], [67, 69, 71] 
+0

1、2、4、6、34、38、41、67、69、71の出力は? '[1,2,4,6]、[34,38,41]、[67,69,71]'または '28'(最大ジャンプ)?? – Shahid

+0

出力は、ジャンプ/ドロップの開始のインデックス/値になります。例えば[1,2,4,6]、[34,38,41]、[67,69,71]は6と41のような出力を持ちます。 – Twitty

+2

これは[エッジ検出](https: //en.wikipedia.org/wiki/Edge_detection)問題、または1Dアナログ、[ステップ検出](https://en.wikipedia.org/wiki/Step_detection)を参照してください。 –

答えて

3

最後に、これは純粋な統計です。データセットがあります。あなたは特定の形式のoutliersを探しています。その意味で、「突然の変更」を検出するという要件はあまり正確ではありません。

私はあなたがここに戻るべきだと思います。あなたの問題の背後にある数学をより深く見て、実際の問題(例えば、平均、偏差などに基づいて)に明確な意味論や鮮明な定義を思い付くことができます。上記のウィキペディアのリンクは、その部分の良い出発点になるはずです。

そこから、Java実装に到達するには、hereと表示される可能性があります。

1

私はMoving Averageを使用して調べていますが、これは値の最後のX値の平均を調べることです。値の変更(Y1〜Y2)に基づいてこれを実行します。平均からの大きな偏差は大きなシフトと見ることができます。

ただし、データセットの移動平均が小さいほど、悪い結果が生じる可能性があります。このような小さなサンプルサイズで、代わりに、配列内のすべての値の平均を取る方が良いかもしれません:

double [] nums = new double[] {79,77,68,61,9,3,1}; 
double [] deltas = new double[nums.length-1]; 
double advDelta = 0; 

for(int i=0;i<nums.length-1;i++) { 
    deltas[i] = nums[i+1]-nums[i]; 
    advDelta += deltas[i]/deltas.length; 
} 

// search for deltas > average 
for(int i=0;i<deltas.length;i++) { 
    if(Math.abs(deltas[i]) > Math.abs(advDelta)) { 
     System.out.println("Big jump between " + nums[i] + " " + nums[i+1]); 
    } 
} 
+0

私が質問で提供したすべての例で動作するようです。私は他人が答えを分析するのを待って、隠されたシナリオでこれが失敗しないことを確かめます。 – Twitty

+1

このアルゴリズムは、上記平均差を見つけることを単純に試みています。シリーズに突然大きな差がある場合、これは失敗します。 「1,4,8,13,19,39,60,84,109」のように。差は「3,4,5,6,20,21,24,25」であり、ジャンプは19〜39でしかないが、その差が全平均よりも大きいので、次の数字の結果をジャンプとして与える。実際の移動平均を試す必要があります。 – 11thdimension

0

私は割合で動作するようにあなたをお勧めします。 たとえば、大きなジャンプは6から34になるので、パーセンテージ= abs((34-6)/ 34)* 100、つまり82%を定義できます。 大きなドロップについては、データが69から9に変わると言うことができるので、パーセント= abs((9-69)/ 69)* 100、つまり87%を定義できます。

あなたは大きなジャンプを定義するパーセンテージしきい値を定義することができます。大きなドロップ、10%のようなもの、またはあなたのために働くもの。

希望に役立ちます。

1

この問題には絶対的な解決策がないため、ソリューションを適用するコンテキストのしきい値を決定する必要があります。

ジャンプするルールはありません。人間は、今のところ一目でデータ全体を見ることができるため、これらの変化を判断することができます。しかし、データセットが十分に大きければ、どのジャンプが考慮されるべきかを私たちが言うのは難しいだろう。例えば、連続する数字の平均差が10である場合、それより上の差はジャンプと見なされます。しかし、大規模なデータセットでは、スパイクの一種であるか、または10から差異が突然100になるような新しい通常の差異を開始する差異が存在する可能性があります。差の平均値10に基づいてジャンプを取得するかどうかを決定する必要があります。我々はそれが我々が固定セットサイズでローカル番号のセットを維持する意味、@ug_

しかし、移動平均によって提案された移動する必要があるとしてmoving averageを使用することが可能ですだけで、ローカルのスパイクに興味がある場合は100

。その上で我々は差の平均を計算し、それらを地方の差と比較する。

ここでも、ローカルセットのサイズを決定するために問題が発生します。このしきい値は、キャプチャしたジャンプの粒度を決定します。非常に大きなセットは、より近いジャンプを無視する傾向があり、小さいセットは、誤ったポジティブをもたらす傾向があります。

しきい値を設定しようとする簡単な解決方法に従います。この場合、ローカル設定サイズが3で、それはそれは私たちの違いの最小カウントを与えるとして使用できる最小だが「それはあなたの場合は2

public class TestJump { 
    public static void main(String[] args) { 
     int[] arr = {1, 2, 4, 6, 34, 38, 41, 67, 69, 71}; 
     //int[] arr = {1,4,8,13,19,39,60,84,109}; 

     double thresholdDeviation = 50; //percent jump to detect, set for your reuirement 
     double thresholdDiff = 3; //Minimum difference between consecutive differences to avoid false positives like 1,2,4 

     System.out.println("Started"); 

     for(int i = 1; i < arr.length - 1; i++) { 
      double diffPrev = Math.abs(arr[i] - arr[i-1]); 
      double diffNext = Math.abs(arr[i+1] - arr[i]); 

      double deviation = Math.abs(diffNext - diffPrev)/diffPrev * 100; 

      if(deviation > thresholdDeviation && Math.abs(diffNext - diffPrev) > thresholdDiff) { 
       System.out.printf("Abrupt change @ %d: (%d, %d, %d)%n", i, arr[i-1], arr[i], arr[i+1]); 
       i++; 
      } 
      //System.out.println(deviation + " : " + Math.abs(diffNext - diffPrev)); 
     } 

     System.out.println("Finished"); 
    } 
} 

出力

Started 
Abrupt change @ 3: (4, 6, 34) 
Abrupt change @ 6: (38, 41, 67) 
Finished 

である必要医学的データや画像のスパイクを発見するなどの大きな問題を解決しようとするなら、ニューラルネットワークをチェックアウトする必要があります。

関連する問題