障害を見つけるためのすぐに使える解決策はないと思いますが、問題に取り組む 1 つの (非標準的な) 方法を次に示します。これを使用して、ほとんどの間隔を見つけることができ、少数の誤検知しか得られませんでしたが、アルゴリズムは確かに微調整を使用できました.
私の考えは、逸脱したサンプルの開始点と終了点を見つけることです。最初のステップは、これらのポイントをより明確に目立たせることです。これは、データの対数を取り、連続する値の差を取ることで実行できます。
MATLAB でデータを読み込みます (この例では、dirty-sample-other.wav を使用します)
y1 = wavread('dirty-sample-pictured.wav');
y2 = wavread('dirty-sample-other.wav');
y3 = wavread('clean-highfreq.wav');
data = y2;
次のコードを使用します。
logdata = log(1+data);
difflogdata = diff(logdata);
したがって、元のデータのこのプロットの代わりに:
我々が得る:
ここで、探している間隔は正と負のスパイクとして際立っています。たとえば、対数差のプロットで最大の正の値を拡大すると、次の 2 つの図が得られます。元のデータ用の 1 つ:
1 つは対数の差です。
このプロットは、領域を手動で見つけるのに役立ちますが、理想的には、アルゴリズムを使用してそれらを見つけたいと考えています。私がこれを行った方法は、サイズ 6 の移動ウィンドウを取得し、ウィンドウの平均値 (最小値を除くすべてのポイント) を計算し、これを最大値と比較することでした。最大点が平均値を超え、平均値の少なくとも 2 倍の大きさの唯一の点である場合、それは正の極値としてカウントされます。
次に、カウントのしきい値を使用しました。値を超えて移動するウィンドウの少なくとも半分は、それを受け入れるために極値として検出する必要があります。
すべてのポイントに (-1) を掛けると、このアルゴリズムが再度実行され、最小値が検出されます。
正の極値を「o」で、負の極値を「*」でマークすると、次の 2 つのプロットが得られます。対数の差の 1 つ:
もう 1 つは元のデータ用です。
対数差を示す図の左側を拡大すると、ほとんどの極端な値が見つかっていることがわかります。
ほとんどの間隔が見つかったようで、誤検知はごくわずかです。たとえば、アルゴリズムを実行する'clean-highfreq.wav'
と、1 つの正の極値と 1 つの負の極値しか見つかりません。
極端な値として誤って分類された単一の値は、開始点と終了点を一致させることによって除外される可能性があります。また、失われたデータを置き換えたい場合は、周囲のデータポイントを使用してある種の補間を使用できます。おそらく、線形補間でも十分です。
私が使用したMATLABコードは次のとおりです。
function test20()
clc
clear all
y1 = wavread('dirty-sample-pictured.wav');
y2 = wavread('dirty-sample-other.wav');
y3 = wavread('clean-highfreq.wav');
data = y2;
logdata = log(1+data);
difflogdata = diff(logdata);
figure,plot(data),hold on,plot(data,'.')
figure,plot(difflogdata),hold on,plot(difflogdata,'.')
figure,plot(data),hold on,plot(data,'.'),xlim([68000,68200])
figure,plot(difflogdata),hold on,plot(difflogdata,'.'),xlim([68000,68200])
k = 6;
myData = difflogdata;
myPoints = findPoints(myData,k);
myData2 = -difflogdata;
myPoints2 = findPoints(myData2,k);
figure
plotterFunction(difflogdata,myPoints>=k,'or')
hold on
plotterFunction(difflogdata,myPoints2>=k,'*r')
figure
plotterFunction(data,myPoints>=k,'or')
hold on
plotterFunction(data,myPoints2>=k,'*r')
end
function myPoints = findPoints(myData,k)
iterationVector = k+1:length(myData);
myPoints = zeros(size(myData));
for i = iterationVector
subVector = myData(i-k:i);
meanSubVector = mean(subVector(subVector>min(subVector)));
[maxSubVector, maxIndex] = max(subVector);
if (sum(subVector>meanSubVector) == 1 && maxSubVector>2*meanSubVector)
myPoints(i-k-1+maxIndex) = myPoints(i-k-1+maxIndex) +1;
end
end
end
function plotterFunction(allPoints,extremeIndices,markerType)
extremePoints = NaN(size(allPoints));
extremePoints(extremeIndices) = allPoints(extremeIndices);
plot(extremePoints,markerType,'MarkerSize',15),
hold on
plot(allPoints,'.')
plot(allPoints)
end
編集 - 元のデータの回復に関するコメント
上の図 3 を少し拡大したものを次に示します (外乱は 6.8 から 6.82 の間です)。
値を調べると、データが負の値にミラーリングされているというあなたの理論は、パターンに正確に適合していないようです。しかし、いずれにせよ、単に違いを取り除くという私の考えは確かに正しくありません。周囲のポイントは外乱によって変更されていないように見えるので、影響を受けた領域内のポイントを信頼せず、代わりに周囲のデータを使用して何らかの補間を使用するという元のアイデアにおそらく戻るでしょう。ほとんどの場合、単純な線形補間が非常に良い近似になるようです。