ヘルダーの不等式の証明をスケッチ

ヘルダーの不等式の証明はいつも忘れるので、備忘録として証明の「スケッチ」は残しておこうという主旨である(はてなブログにおける数式の練習も兼ねて)。

1. ヘルダーの不等式とは

$1 \leq p \leq \infty$,$q$は$p$の調和共役とする.すなわち, $$ \frac{1}{p} + \frac{1}{q} = 1 $$

が成り立つものとする.3つ組 $(X, \mathcal{B}, \mu)$を測度空間とする.$f$,$g$は$X$上の可測関数とする. このとき,以下が成り立つ.

$$ ||f \cdot g||_{1} \leq ||f|| _ {p} ||g|| _ {q} $$

2. 記号の準備
  • $L _ 1$ノルム $$ ||f|| _ 1 = \int _ X\; |f| \; d\mu $$

  • $L _ p$ノルム $$ ||f|| _ p = \left( \int _ X\; |f| ^ p \; d\mu \right)^{\frac{1}{p}} $$

3. 証明のスケッチ

まず以下のヤングの不等式を認めることにする. $$ ab \leq \frac{a ^ p}{p} + \frac{b ^ q}{q} \;\;\; (a,\; b > 0) $$

この不等式を$\theta > 0$を用いて少し変形する. $$ ab = (\theta a) (\theta ^ {-1} b) \leq \frac{\theta ^ {a} a ^ {p}}{p} + \frac{\theta ^ {-q} b ^ {q}}{q} $$

ここで$a = |f|$および$b = |g|$として $$ |f||g| \leq \frac{\theta ^ {p} |f| ^ {p} }{p} + \frac{\theta ^ {-q} |g| ^ {q}}{q} $$ となるので、両辺を積分することで

$$ ||f \cdot g|| _ {1} \leq \frac{\theta ^ {p} ||f|| _ {p} ^ {p} }{p} + \frac{\theta ^ {-q} ||g|| _{q} ^ {q}}{q} $$

という不等式が成り立つ。そこで $\theta > 0$を $$ \theta ^ {p} ||f|| _ {p} ^ {p} = \theta ^ {-q} ||g|| _{q} ^ {q} $$

となるように選ぶ.すると不等式の右辺は$\theta ^ {p} ||f|| _ {p} ^ {p}$でくくり出すことができて $$ ||f \cdot g|| _ {1} \leq \left ( \frac{1}{p} + \frac{1}{q} \right ) \cdot \theta ^ {p} ||f|| _ {p} ^ {p} = \theta ^ {p} ||f|| _ {p} ^ {p} $$

となる.さてここで $$ \left ( \frac{||g|| _ {q}}{\theta} \right ) ^ {q} = \left ( \theta ||f|| _ {p} \right ) ^ {p} $$

なのだから,両辺の「$q$乗根」を取って

$$ \frac{||g|| _ {q}}{\theta} = \left ( \theta||f|| _ {p} \right ) ^ {\frac{p}{q}} $$

である.$q/p$は

$$ 1 + \frac{p}{q} = p \Leftrightarrow \frac{p}{q} = p -1 $$

と計算できるから,結局

$$ \begin{align} \frac{||g|| _ {q}}{\theta} &= \left ( \theta ||f|| _ {p} \right ) ^ {p -1} \\ ||g|| _ {q} &= \theta ^ {p} ||f|| _ {p} ^ {p -1} \end{align} $$ となる.よって,

$$ ||f \cdot g|| _ {1} \leq ||f|| _ {p} \cdot \theta ^ {p} ||f|| _ {p} ^ {p-1} = ||f|| _ {p} ||g|| _ {q} $$

を得て、証明が終わる.

Pythonの音声区間検出ライブラリ inaSpeechSegmenterを試してみた話

Pythonでいい感じの音声区間検出してくれるライブラリはないかなと探していたら、inaSpeechSegmenterというものが見つかったので使ってみた。
github.com

デフォルトでは音声の区間、音楽の区間、ノイズの区間、無音の区間を検出し、その区間ラベルと時間情報(開始・終了時刻)の情報を返してくれる。面白いのは音声区間においてジェンダーの区別もデフォルトでしてくれるということ。

区間ラベルを列挙しておこう:

  • speech (male/female) 音声
  • music 音楽
  • noise ノイズ
  • noEnergy 無音

インストールは以下。

pip install inaSpeechSegmenter

こんなスクリプトを書いてみた。
gist.github.com

inaSpeechSegmenterは区間ラベルと時間情報のみを取得できる。同ライブラリのseg2csvをインポートすることで、検出結果をcsvに書き出すことができる 。

seg2csv(segmentation, 'myseg.csv')

実用上は複数の音声ファイルに分割したいので、上記のスクリプトではpydubのAudioSegmentの力を借りて音声区間ごとにwavに分割保存したわけである。

spleeterを使って音源分離を試しただけ

はじめに

界隈で有名な、音源分離のためのPythonパッケージであるspleeterを使ってみたという話。
github.com

手順

事前にffmpegとlibsndfileはインストールしておく必要はあるとのこと。
https://github.com/deezer/spleeter/wiki/1.-Installation#using-pip

spleeterのインストールはpipでOK。

pip install spleeter

分離対象となる音楽を用意する。
soundcloud.com

以下のPythonスクリプトを実行する。spleeterは5音源まで対応できるということなので、機械的に試してみた。
gist.github.com
初回実行時はモデルパラメータをダウンロードするために時間がかかることには注意。また、実行時には当該のライブラリ由来で色々と警告が出されるかもしれないが、無視してOKである。

分離結果

元の音楽にはピアノやベースの音源が含まれていないので、対応する分離結果もほぼ無音になるのは興味深い。

  • 2音源(ボーカルとインスト)

soundcloud.com

  • 4音源(ボーカル、ベース、ドラム、その他)

soundcloud.com

  • 5音源(ボーカル、ピアノ、ベース、ドラム、その他)

soundcloud.com

まとめ

少なくとも、ボーカルとドラムの抽出には便利に使えそうなライブラリである。

Pyroomacousticsを使って部分空間法に基づく雑音抑圧を試してみた

概要

Pyroomacousticsというパッケージを使って部分空間法に基づく雑音抑圧をやってみた。

結果
  • 元の音声

soundcloud.com

  • 雑音入りの音声

soundcloud.com

  • 雑音抑圧後の音声

soundcloud.com

雑音を大きく削れば、それだけ元の音も削られるため、ある程度の歪みが発生することは避けられない。apply_subspace関数に渡すパラメータを調整する必要はあるが、雑音抑圧後にミュージカルノイズはあまり発生しないのが特徴と言えるだろう。

Pyroomacousticsを使って雑音抑圧(スペクトルサブトラクション法)のバッチ処理を試してみた

概要

Pyroomacousticsというパッケージに同梱のJupyter notebook(下記リンク)を参考に、スペクトルサブトラクション法に基づく雑音抑圧をバッチ処理的にやってみただけである。ノートブックのほぼコピペなので新しいところはない。
nbviewer.jupyter.org

Pyroomacousticsのインストールは以下。

pip install pyroomacoustics

音声ファイルや雑音ファイルは以下からダウンロードできる。
pyroomacoustics/notebooks at master · LCAV/pyroomacoustics · GitHub

Pythonスクリプト

雑音入の音声を用意し、推定した雑音抑圧フィルタをSTFTスペクトルに乗算することで処理を実現する。処理後のSTFTスペクトルは音声へと逆変換され、結果をファイルに保存するという流れである。
gist.github.com

結果
  • 元の音声

soundcloud.com

  • 雑音入りの音声

soundcloud.com

  • 雑音抑圧後の音声

soundcloud.com



「元の雑音」は抑圧できていることが分かる。

考察

雑音抑圧後にも残る(むしろ新たに発生する)雑音は「ミュージカルノイズ」と呼ばれる。スクリプト中の db_reduc の数値を大きくすると、元の雑音はより抑圧できるが、ミュージカルノイズも増える。雑音抑圧レベルとミュージカルノイズのレベルはトレードオフ関係にあるといえる。

雑音抑圧前後のスペクトログラムの表示は今後の予定。

oct2pyを使って独立低ランク行列分析の音源分離デモ(MATLAB)をPython上で動かした話

ブラインド音源分離手法の1つである独立低ランク行列分析(Independent Low-Rank Matrix Analysis; ILRMA)のデモスクリプトが、論文著者により公開されている。
github.com
上記スクリプトMATLAB/Octave用の言語で書かれているが、oct2pyにより(無理やり)Pythonで動かすスクリプトを書いてみた、というのが本記事の主旨である。

以下にPythonスクリプトを示す。オリジナルのMATLABスクリプトにおけるサンプリング周波数変更のためのresample関数をscipy.signal.resample_polyに変更したのが大きい。それ以外は行列のインデックスの調整が主であるが、MATLABにおけるtrueをoctave.logical(1)で置き換えたり、乱数のシードを固定するためにOctaveのseed関数を使うなどした。
gist.github.com

ピアノとドラム音からなる混合観測信号に対して音源分離を行った結果は以下のリンクから試聴できる。

いい感じに音源が分離できていることが分かる。

おまけ
  • ILRMAについて気になった読者はぜひオリジナルの論文にも目を通されたい:

D. Kitamura, N. Ono, H. Sawada, H. Kameoka, H. Saruwatari, "Determined blind source separation unifying independent vector analysis and nonnegative matrix factorization," IEEE/ACM Trans. ASLP, vol. 24, no. 9, pp. 1626-1641, September 2016.

  • 日本語論文は以下。

北村大地, 小野順貴, 澤田宏, 亀岡弘和, 猿渡洋, "独立低ランク行列分析に基づくブラインド音源分離," IEICE Technical Report, EA2017-56, vol. 117, no. 255, pp. 73–80, Toyama, October 2017

  • ILRMAの解説スライドは以下が参考になる。

www.slideshare.net

http://d-kitamura.net/pdf/misc/AlgorithmsForIndependentLowRankMatrixAnalysis.pdf

  • PythonライブラリのpyroomacousticsにはILRMAが実装されている:

Independent Low-Rank Matrix Analysis (ILRMA) — Pyroomacoustics 0.3.1 documentation

oct2pyを使ってMATLAB版legacy-STRAIGHTをPythonから呼び出す

音声の分析合成ツールの1つであるlegacy-STRAIGHTが公開されている。
github.com

このライブラリはMATLAB/Octaveで利用可能なm-fileとして書かれているため、Pythonからは利用できないと諦めていたのだが、最近、m-fileをPythonから起動できるoct2pyなるパッケージの存在を知った。
github.com

タイトルにある通り、oct2py経由でlegacy-STRAIGHTを呼び出すことができたので、本記事はその記録である。

まず公式にある通りoct2pyをインストールする:

pip install oct2py

次にlegacy-STRAIGHTをダウンロードし、src/にある各種ライブラリ群を適切なディレクトリに置く。

Octave forgeからsignalパッケージをダウンロードし、適切なディレクトリに置く。
octave.sourceforge.io

テスト用のwavを用意して、以下のPythonスクリプトを実行する。ちなみにvaiueo2d.wavはlegacy-STRAIGHTのsrc/内にある。

from oct2py import octave
octave.addpath('/path/to/straight')
octave.addpath('/path/to/signal')

x, fs = octave.audioread('vaiueo2d.wav', nout=2)
f0raw = octave.MulticueF0v14(x, fs)
ap = octave.exstraightAPind(x, fs, f0raw)
n3sgram = octave.exstraightspec(x, f0raw, fs)
synthesized_signal = octave.exstraightsynth(f0raw, n3sgram, ap, fs)
octave.audiowrite('out_file.wav', synthesized_signal / 32768, fs)

なお上記のスクリプトにおいて、audioreadの第2引数noutが曲者であった。oct2pyは仕様として、出力の戻り値の個数は明示的に指定する必要がある(noutのデフォルト値は1)。これは知らないとハマる点である。