最尤(ML)推定量
ここでは、クリーンな信号のパワーの最尤推定量が導出されますが、スペクトルパワー減算と比較して、SNRの二乗平均平方根誤差に関しては改善されていないようです。
前書き
正規化されたクリーンな振幅を紹介しましょう a 正規化されたノイズの大きさ m ノイズ標準偏差で正規化 σ:
a=|Xk|σ,m=|Yk|σ.(1)
式の推定量。質問の3つは見積もりを与えるa^ の a なので:
a^=1σ|Xk|2ˆ−−−−√=1σmax((σm)2−σ2,0)−−−−−−−−−−−−−−−−√={m2−1−−−−−−√0if m>1,if m≤1.(2)
最尤推定量
のより良い推定量を作るために a式より 2、我々はSijbersらの手順に従います。1998.(質問を参照)最尤(ML)推定量を構築するa^ML. それはの価値を与える a 与えられた値の確率を最大にする m.
のPDF |Yk|あるライスパラメータを持ちますνRice=|Xk| とパラメータ(後でわかりやすくするために置き換えます) σRice=12√σ:
PDF(|Yk|)=|Yk|σ2Riceexp⎛⎝⎜−(|Yk|2+|Xk|2)2σ2Rice⎞⎠⎟I0(|Yk||Xk|σ2Rice),(3)
どこ Iαある第一種の変形ベッセル関数。代用|Xk|=σa, |Yk|=σm, そして σ2Rice=12σ2:
=PDF(σm)=2mσe−(m2+a2)I0(2ma),(3.1)
そして変換:
⇒PDF(m)=σPDF(σm)=2me−(m2+a2)I0(2ma).(3.2)
のライスPDF m によってパラメータ化 a ノイズ分散とは無関係です σ2. 最尤推定量 a^ML パラメータの a の値です a 最大化する PDF(m)。それはの解決策です:
mI1(2ma^ML)I0(2ma^ML)−a^ML=0.(4)
式の解。4には次の特性があります。
a^ML=0 if m≤1.(5)
それ以外の場合は、数値的に解決する必要があります。
図1.青、上:最尤推定量 a^ML オレンジ色の下:質問のパワースペクトル減算推定量 a^ 正規化されたクリーンな振幅の a、正規化されたノイズの大きさの関数として m.
σa^ML の最尤推定量です |Xk|,そして、最尤推定の機能的不変性によって、σ2a^2ML の最尤推定量です |Xk|2.
ML推定量の経験的ローランシリーズ
私は数値で計算しようとしました(以下のスクリプトを参照)。a^2ML, しかし、次の範囲では収束していないようです。 m必要。以下は、私が計算した限りでは、ローランシリーズの一部を省略しています。
a^2ML≈m2−121m0−123m2−325m4−1227m6−5729m8−309211m10−1884213m12−12864215m14−98301217m16−839919219m18−7999311221m20(6)
整数シーケンスのオンライン百科事典(OEIS)で分子または分母の整数シーケンスを見つけることができませんでした。最初の5つの負のべき項についてのみ、分子係数はA027710と一致します。ただし、計算されたシーケンス(1,−1,−1,−3,…)OEIS Superseekerへの返信でこれを受け取りました(そこから次の3つの推奨番号を確認しました)−84437184,−980556636,−12429122844 拡張計算による):
Guesss suggests that the generating function F(x)
may satisfy the following algebraic or differential equation:
-1/2*x+1/2+(-x+1/2)*x*diff(F(x),x)+(x-3/2)*F(x)-1/2*F(x)*x*diff(F(x),x)+F(x)^2 = 0
If this is correct the next 6 numbers in the sequence are:
[-84437184, -980556636, -12429122844, -170681035692, -2522486871192, -39894009165525]
表形式の近似と推定誤差ゲイン
以下を含む線形補間されたテーブル(以下のスクリプトを参照) 124071 不均一に分布したサンプル a^2ML−m2 約の最大誤差で近似を与える 6×10−11.
ML推定量の最小二乗近似
最小二乗近似(追加の重みで m2=1)の推定曲線のサンプルが作成され、Laurentシリーズの実験に触発された形で作成されました(下のOctaveスクリプトを参照)。負の可能性を排除するために定数項- 0.5
が変更され- 0.49999998237308493999
ましたa2 で m2=1. 近似は、 m2≥1 約の最大誤差があります 2×10−5 (図3)近似 a^2ML:
a^2 = m^2 - 0.49999998237308493999 -0.1267853520007855/m^2 - 0.02264263789612356/m^4 - 1.008652066326489/m^6 + 4.961512935048501/m^8 - 12.27301424767318/m^10 + 5.713416605734312/m^12 + 21.55623892529696/m^14 - 38.15890985013438/m^16 + 24.77625343690267/m^18 - 5.917417766578400/m^20
図3.の最小二乗近似の誤差 a^2ML.
スクリプトは、増加する負のパワーの数を処理できるようです m2,エラーの極値の数は増え続けますが、最大エラーの減衰は非常に遅くなり、エラーはますます小さくなります。近似はほぼ等リップルですが、Remezの交換の改良により多少のメリットが得られます。
近似を使用して、以下の予想誤差ゲイン曲線が得られました。
図2.サンプルサイズがのモンテカルロ推定 105, of:Solid:推定における二乗誤差の合計のゲイン |Xk| 沿って |Xk|ˆ で推定するのと比較して |Yk|,
破線:推定における二乗誤差の合計のゲイン |Xk|2 沿って |Xk|2ˆ で推定するのと比較して |Yk|2, 点線:推定における二乗誤差の合計のゲイン Xk 沿って |Xk|ˆeiarg(Yk) で推定するのと比較して Yk. 青:MLエスティメータ、オレンジ:クランプされたスペクトルパワー減算。
驚くべきことに、ML推定器は、SNR>約5 dBでの信号推定とSNR>約3 dBでの振幅推定がわずかに優れていることを除いて、ほぼすべての点でクランプスペクトルパワー減算よりも劣っています。これらのSNRでは、2つの推定量はノイズの多い信号を推定値として使用するよりも劣ります。
図1のPythonスクリプトA
このスクリプトは、質問のスクリプトAを拡張します。
def est_a_sub(m):
m = mp.mpf(m)
if m > 1:
return mp.sqrt(m**2 - 1)
else:
return 0
def est_a_ML(m):
m = mp.mpf(m)
if m > 1:
return mp.findroot(lambda a: m*mp.besseli(1, 2*a*m)/(mp.besseli(0, 2*a*m)) - a, [mp.sqrt(2*m**2*(m**2 - 1)/(2*m**2 - 1)), mp.sqrt(m**2-0.5)])
else:
return 0
def est_a_ML_fast(m):
m = mp.mpf(m)
if m > 1:
return mp.sqrt(m**2 - mp.mpf('0.49999998237308493999') - mp.mpf('0.1267853520007855')/m**2 - mp.mpf('0.02264263789612356')/m**4 - mp.mpf('1.008652066326489')/m**6 + mp.mpf('4.961512935048501')/m**8 - mp.mpf('12.27301424767318')/m**10 + mp.mpf('5.713416605734312')/m**12 + mp.mpf('21.55623892529696')/m**14 - mp.mpf('38.15890985013438')/m**16 + mp.mpf('24.77625343690267')/m**18 - mp.mpf('5.917417766578400')/m**20)
else:
return 0
ms = np.arange(0, 5.0078125, 0.0078125)
est_as = [[est_a_ML(m) for m in ms], [est_a_sub(m) for m in ms]];
plot_est(ms, est_as)
Laurentシリーズの数値計算用Pythonスクリプト
このスクリプトは、ローランシリーズの最初の数項を数値で計算します。 a^2ML−m2.これは、この回答のスクリプトに基づいています。
from sympy import *
from mpmath import *
num_terms = 10
num_decimals = 12
num_use_decimals = num_decimals + 5 #Ad hoc headroom
def y(a2):
return sqrt(m2)*besseli(1, 2*sqrt(a2*m2))/besseli(0, 2*sqrt(a2*m2)) - sqrt(a2)
c = []
h = mpf('1e'+str(num_decimals))
denominator = mpf(2) # First integer denominator. Use 1 if unsure
denominator_ratio = 4 # Denominator multiplier per step. Use 1 if unsure
print("x")
for i in range(0, num_terms):
mp.dps = 2*2**(num_terms - i)*num_use_decimals*(i + 2) #Ad hoc headroom
m2 = mpf('1e'+str(2**(num_terms - i)*num_use_decimals))
r = findroot(y, [2*m2*(m2 - 1)/(2*m2 - 1), m2-0.5]) #Safe search range, must be good for the problem
r = r - m2; # Part of the problem definition
for j in range(0, i):
r = (r - c[j])*m2
c.append(r)
mp.dps = num_decimals
print '+'+str(nint(r*h)*denominator/h)+'/('+str(denominator)+'x^'+str(i)+')'
denominator *= denominator_ratio
MLエスティメータを集計するためのPythonスクリプト
このスクリプトは、不均等にサンプリングされたテーブルを作成します [m2,a^2ML] 線形補間に適したペア。近似の定義された最大絶対線形補間誤差をほぼ与えます。 a^2ML 範囲 m=0…mmax.ピーク誤差が十分小さくなるまで、困難な部分にサンプルを追加することにより、テーブルサイズが自動的に増加します。もしmmax 等しい 2 プラス整数の累乗 2, 次に、すべてのサンプリング間隔は、 2. 表の最後に、不連続性のない大規模なm 近似 a^2ML=m2−12. もし a^ML が必要です、私の推測では、テーブルをそのまま補間してから変換する方が良いと思います a^ML=a^2ML−−−√.
次のスクリプトと組み合わせて使用するには、出力をパイプします> linear.m
。
import sys # For writing progress to stderr (won't pipe when piping output to a file)
from sympy import *
from mpmath import *
from operator import itemgetter
max_m2 = 2 + mpf(2)**31 # Maximum m^2
max_abs_error = 2.0**-34 #Maximum absolute allowed error in a^2
allow_over = 0 #Make the created samples have max error (reduces table size to about 7/10)
mp.dps = 24
print('# max_m2='+str(max_m2))
print('# max_abs_error='+str(max_abs_error))
def y(a2):
return sqrt(m2)*besseli(1, 2*sqrt(a2*m2))/besseli(0, 2*sqrt(a2*m2)) - sqrt(a2)
# [m2, a2, following interval tested good]
samples = [[0, 0, True], [1, 0, False], [max_m2, max_m2 - 0.5, True]]
m2 = mpf(max_m2)
est_a2 = findroot(y, [2*m2*(m2 - 1)/(2*m2 - 1), m2-0.5])
abs_error = abs(est_a2 - samples[len(samples) - 1][1])
if abs_error > max_abs_error:
sys.stderr.write('increase max_m, or increase max_abs_error to '+str(abs_error)+'\n')
quit()
peak_taken_abs_error = mpf(max_abs_error*allow_over)
while True:
num_old_samples = len(samples)
no_new_samples = True
peak_trial_abs_error = peak_taken_abs_error
for i in range(num_old_samples - 1):
if samples[i][2] == False:
m2 = mpf(samples[i][0] + samples[i + 1][0])/2
est_a2 = mpf(samples[i][1] + samples[i + 1][1])/2
a2 = findroot(y, [2*m2*(m2 - 1)/(2*m2 - 1), m2-0.5])
est_abs_error = abs(a2-est_a2)
if peak_trial_abs_error < est_abs_error:
peak_trial_abs_error = est_abs_error
if est_abs_error > max_abs_error:
samples.append([m2, a2 + max_abs_error*allow_over, False])
no_new_samples = False
else:
samples[i][2] = True
if peak_taken_abs_error < est_abs_error:
peak_taken_abs_error = est_abs_error
if no_new_samples == True:
sys.stderr.write('error='+str(peak_taken_abs_error)+', len='+str(len(samples))+'\n')
print('# error='+str(peak_taken_abs_error)+', len='+str(len(samples)))
break
sys.stderr.write('error='+str(peak_trial_abs_error)+', len='+str(len(samples))+'\n')
samples = sorted(samples, key=itemgetter(0))
print('global m2_to_a2_table = [')
for i in range(len(samples)):
if i < len(samples) - 1:
print('['+str(samples[i][0])+', '+str(samples[i][1])+'],')
else:
print('['+str(samples[i][0])+', '+str(samples[i][1])+']')
print('];')
図2のPythonスクリプトB
このスクリプトは、質問のスクリプトBを拡張します。
def est_a_ML_fast(m):
mInv = 1/m
if m > 1:
return np.sqrt(m**2 - 0.49999998237308493999 - 0.1267853520007855*mInv**2 - 0.02264263789612356*mInv**4 - 1.008652066326489*mInv**6 + 4.961512935048501*mInv**8 - 12.27301424767318*mInv**10 + 5.713416605734312*mInv**12 + 21.55623892529696*mInv**14 - 38.15890985013438*mInv**16 + 24.77625343690267*mInv**18 - 5.917417766578400*mInv**20)
else:
return 0
gains_SSE_a_ML = [est_gain_SSE_a(est_a_ML_fast, a, 10**5) for a in as_]
gains_SSE_a2_ML = [est_gain_SSE_a2(est_a_ML_fast, a, 10**5) for a in as_]
gains_SSE_complex_ML = [est_gain_SSE_complex(est_a_ML_fast, a, 10**5) for a in as_]
plot_gains_SSE(as_dB, [gains_SSE_a_ML, gains_SSE_a_sub], [gains_SSE_a2_ML, gains_SSE_a2_sub], [gains_SSE_complex_ML, gains_SSE_complex_sub])
最小二乗のオクターブスクリプト
このオクターブスクリプト(この回答の適応)は、m2 に a^2ML−(m2−12)。サンプルは少し上のPythonスクリプトによって準備されました。
graphics_toolkit("fltk");
source("linear.m");
format long
dup_zero = 2000000 # Give extra weight to m2 = 1, a2 = 0
max_neg_powers = 10 # Number of negative powers in the polynomial
m2 = m2_to_a2_table(2:end-1,1);
m2 = vertcat(repmat(m2(1), dup_zero, 1), m2);
A = (m2.^-[1:max_neg_powers]);
a2_target = m2_to_a2_table(2:end-1,2);
a2_target = vertcat(repmat(a2_target(1), dup_zero, 1), a2_target);
fun_target = a2_target - m2 + 0.5;
disp("Cofficients for negative powers of m^2:")
x = A\fun_target
a2 = A*x + m2 - 0.5;
plot(sqrt(m2), sqrt(a2)) # Plot approximation
xlim([0, 3])
ylim([0, 3])
a2(1) # value at m2 = 2
abs_residual = abs(a2-a2_target);
max(abs_residual) # Max abs error of a^2
max(abs(sqrt(a2)-sqrt(a2_target))) # Max abs error of a
plot(sqrt(log10(m2)), a2_target - a2) # Plot error
xlabel("sqrt(log(m^2))")
ylabel("error in approximation of hat a^2_{ML}")
チェビシェフ多項式を使用した近似のためのPythonスクリプトA2
このスクリプトはスクリプトAを拡張し、チェビシェフ多項式を使用してML推定器の代替近似を提供します。最初のチェビシェフノードはm=1 チェビシェフ多項式の数は、近似が非負になるようなものです。
N = 20
est_a_ML_poly, err = mp.chebyfit(lambda m2Reciprocal: est_a_ML(mp.sqrt(1/m2Reciprocal))**2 - 1/m2Reciprocal, [0, 2/(mp.cos(mp.pi/(2*N)) + 1)], N, error=True)
def est_a_ML_fast(m):
global est_a_ML_poly
m = mp.mpf(m)
if m > 1:
return mp.sqrt(m**2 + mp.polyval(est_a_ML_poly, 1/m**2))
else:
return 0