Golomb-Rice符号の長さ解析で、エントロピーと比べたときの冗長度比較を追記しておきたい。冗長度の定義は

による。エントロピー \(H\) と符号長 \(L\) に対して \(H - L / H\) という定義。さっそく計測してみたら、平均が大きいところでRice符号よりも冗長度が高い…。これは正直に載せておこう。結果と考察を箇条書きすると、

  • 幾何分布の平均が1.5以上になるところで冗長度が高い。
  • 一様乱数に対しては常に良い。
  • 再帰的Golomb-Riceは、小さい符号語を一葉乱数とみなしているのが強みに思える。昨日の観察結果から、残差が0に近いところではほぼ一様乱数(減少傾向はあるけどエントロピーがほぼ一様乱数のそれ)になっていた。
    • 2段目のパラメータについては幾何分布の無記憶性が効く。残差を1段目のパラメータで引いてもその分布は近似的に幾何分布に従う。よってGolomb-Rice符号でよい(しかも、理論的には通常のRice符号での最適パラメータでよい)。実際には裾が重いので現実には当てはまらないが、近似にはなっている。

フィルタの考察にはいる。

  • スペクトル解析と最大エントロピー法 ARモデルの次数決定法について、最終予測残差法について書いてある。読むべき。
  • Linear prediction 音声信号でのLPCの次数をAICとMDLで決める取り組み。前も挙げたかも知れないけど、改めて。
  • 音声音響信号処理のための確率モデルと学習アルゴリズム 33pあたりからLPCの確率的解釈について話題。
    • 「LPCはスペクトル包絡推定に相当」。
    • 音声のパワースペクトル密度をARの時間発展行列を使って書き直し、複素ガウス分布仮定のもとで最尤推定すると、板倉斎藤距離が出てくる。LPCは、観測したパワースペクトルとARの全極スペクトルを板倉斎藤距離で最小化している。

一番気にしているのはフィルタ次数。次数を高めれば2乗誤差は減るけど、過適合が良くないのではないかとずっと考えていた。flakeは最も符号長の短い次数を探しているから重要なことだと思っている。

そこでPython実装版で試してみた。以下のようにしてパラメータ数についても最適化をかけた。

def search_optimal_layer_structure(self, din):
    """ 最適なレイヤーあたりユニット数の探索・設定 """
    residual = din.copy()
    for idx, (max_num_params, _) in enumerate(self.init_layer_structure):
        params_list = [max_num_params // 2, max_num_params]
        minnparams = None
        for num_params in params_list:
            minnorm = sys.float_info.max
            minnunits = None
            minres = None
            # 最小の残差L1ノルムを達成する分割数をレイヤーに設定
            for nunits in [2 ** i for i in range(0, max(num_params.bit_length() - 1, 1))]:
                if (residual.shape[0] % nunits) == 0:
                    tmplayer = LPCLayer(np.zeros((num_params, 1)), nunits)
                    tmpres = tmplayer.forward_with_set_af_parameter(residual)
                    tmpres_norm = np.mean(np.abs(tmpres))
                    if tmpres_norm < minnorm:
                        minnorm = tmpres_norm
                        minnunits = nunits
                        minres = tmpres
                        minnparams = num_params
        # パラメータとレイヤーを再設定
        weight_name = 'W' + str(idx + 1)
        print("%d %d" % (max_num_params, minnparams))
        self.params[weight_name] = np.zeros((minnparams, 1))
        self.layers['LPC' + str(idx + 1)] = LPCLayer(self.params[weight_name], minnunits)
        residual = minres

実験の結果、手元の音源では、常に最大のパラメータを使ったときにL1ノルムが最小になっていた。すなわち次数選択はあまり効いてきてないらしい。

またスペクトルの平坦性について見ていたところ、補助関数法をL-Dに入れ替えたら様相が大きく変わった。L1ロスは小さくなるし、ネットワーク構成のパラメータ次数を1,2,4,8,...と設定するよりも、32,16,8,...とした方が平坦性が高かった。どういうこと?最適なユニット数検索を入れて検証したい。