FAQ
音楽解析の結果が何を意味していて、どこまで信じてよいのかについてよく挙がる質問をまとめます。何がどうテストされているかは 実装検証、librosa と一致する範囲については librosa互換性 を参照してください。
音楽解析の精度はどのくらいですか?
公開している数値はまだありません。そして librosa との一致は精度の数値ではありません。
librosa と一致するとは、2 つのライブラリが同じ計算をしているという意味です。その計算がキーを正しく言い当てるか、コードを正しく拾うかは別の問題で、答えられるのはアノテーション付きの音源だけです。両者が一致しているクロマベクトルであっても、キー推定がそれを読み違えることはあります。
代わりに用意してあるのは測定の仕組みです。ライブラリ本体のリポジトリの tests/fixtures/music_eval/ に、キー・BPM・ビート・ダウンビート・拍子・コードのマニフェストがあり、tools/eval/summarize_accuracy.py が実行結果をデータセット別の数値(キー正解率と MIREX 加重スコア、コードの WCSR、ビート F 値)に集計します。マニフェストが参照するコーパス(GiantSteps、Isophonics、Billboard、Ballroom、SMC など)は研究用途のライセンスで再配布できないため、マニフェストは空のまま同梱し、測定は手元のコーパスに対して走らせます。make accuracy-report で一連の手順が動きます。
その測定結果が出るまで、現状を正確に言えば「古典的 DSP としてはまともな実装だが、精度はまだ測定されていない」です。
confidence は何を表していますか?
モデル自身の確信であって、精度の推定値ではありません。この 2 つは混同されやすく、そして値で分岐する処理にとってはこの区別が効いてきます。
キー推定の confidence は事後確率です。スコアした全候補キーのプロファイル相関に対するソフトマックスなので、対抗馬が近づくと値は下がります。同じクロマを分け合う平行調どうしは、両方が高い値を出すのではなく、それぞれおよそ半分を報告します。これは「推定が拮抗している」ことが分かるという意味で有用ですが、示しているのは候補集合の中でクロマがどれだけ一方的に 1 つを選んだかであって、その選択がどれだけの頻度で当たるかではありません。
ライブラリのどの部分もアノテーション付き音源で較正されてはいないので、confidence が高いまま間違えることは十分にありえます。confidence でしきい値を切るなら、しきい値は自分の素材に対して決めてください。高い値は「証拠が一方的だった」であって「たぶん正解」ではありません。
セクションの confidence とコードの confidence はさらに別の量で、それぞれの型のところに説明があります。互いに比較できるものではなく、キーの事後確率とも比較できません。
平行調(メジャー/マイナー)が入れ替わって出るのはなぜ?
コードとその平行調は構成音の大半を共有していて、クロマグラムはすべてのオクターブを 12 個の数値に畳んでしまうからです。あるメジャーと、その短 3 度下のマイナーは 3 音のうち 2 音が共通で、音域の情報が失われた後にはどの音がルートかを言う手がかりがほとんど残りません。
コード認識ではこれに対して低域を別に評価しています。ルートを言い当てる手がかりとしては、畳まれたクロマより低域のほうがはるかに信頼できるので、ルートが低域で鳴っている候補を、鳴っていない候補より優先します。この重み付けは意図的に「同点のときの決め手」であって「上書き」ではありません。低域の音がルートと一致するのは基本形のときだけで、強い低域プライアを入れるとすべての転回形がそのベース音の名前に付け替えられてしまうからです。
それでも特定のトラックが平行調で返ってくる場合、効くのは次の 3 つです。ベースパートのある素材を渡すこと(ベースを抜いたステムは、まさにこの手がかりを失った素材です)。コードのキーコンテキストを有効にして、進行から読みを拘束すること。そして最上位だけでなく次点の候補を見ること。KeyAnalyzer は 24 候補すべてを事後確率付きで公開しているので、拮抗した平行調のペアはそこで「ほぼ同じ 2 つのシェア」として見えます。
認識できるコードの種類は?
トライアド(メジャー、マイナー、ディミニッシュ、オーギュメント)、セブンス(ドミナント、メジャー、マイナー、ディミニッシュ、ハーフディミニッシュ)です。サスペンデッド(sus2、sus4、sus2add4)、アドナインス、ナインス、シックスス、マイナーメジャーセブンスも含みます。7sus4、オルタード・ドミナント(11th、13th、7♭9、7♯9)も認識できます。
4 種のトライアドより先の語彙は、全テンプレート集合が有効なとき、つまり useTriadsOnly が off のときにだけ探索されます。単体のコード API は既定で off なので、そのままで全集合が使われます。統合 analyze() のパスは既定で on であり、要求しないかぎりトライアドだけを探索します。全集合を使うには useTriadsOnly: false を渡すか、どちらのコマンドラインでも --with-seventh を指定してください。語彙の外にあるコードは棄却されるのではなく、いちばん近いメンバーとして報告されます。
このうち 3 つは「難しい」のではなく「原理的に曖昧」なので、知っておく価値があります。メジャー・シックススと、その短 3 度下のマイナーセブンスは同じ 4 つのピッチクラスで構成されます。マイナー・シックススとその下のハーフディミニッシュセブンス、7sus4 とその 4 度下の sus2add4 も同様です。クロマグラムでは分離できません。分離すべきものがクロマの中に存在しないからです。分けるのは低域であり、低域が別の読みを示さないかぎり、認識器はより一般的なほうの読みを採ります。ベースパートのない素材では、一般的なほうの名前が返ると考えてください。
セクションのラベルが間違っている/全部 Unknown になるのはなぜ?
構造ラベリングは固定しきい値のヒューリスティックであって、学習済みのセグメンタではありません。そう明記もしてあります。境界の位置はおおむね使えますが、ラベル(Verse、Chorus、Bridge)はベストエフォートで、一般的なポップスの形式に従わない素材ではよく外れます。
Unknown は失敗コードではなく、意図的な答えです。境界がまったく検出されなかったとき、どの肯定的な分岐にも当てはまらなかったとき、そして音楽的機能を主張するには証拠が弱すぎたときに出ます。最後のケースではしきい値未満のスコアがそのまま残るので、どこまで惜しかったかが見えます。
Unknown が増えやすくなるガードが 2 つあります。どちらも意図的なものです。1 つは、クロマで区別できない隣接セグメントをラベリングの前に併合すること。これにより、ひと続きの音楽の途中に現れたノベルティのピークが、それを 2 つの「繰り返しセクション」に割ることはありません。もう 1 つは、ほぼすべてのセクションのペアが互いの繰り返しと判定される場合——均質な素材はまさにこうなります——繰り返しを Verse/Chorus 交替の証拠ではなく「情報を持たないもの」として扱うことです。この扱いがなければ、均質な素材から、一度も変化していない小節をもとにした完全な楽曲形式ができてしまいます。
後段のアルゴリズムには、ラベルより生の信号を渡すほうが向いています。boundaryTimes とクロマのコサイン自己類似度行列は、呼び出し側が自分のしきい値を当てられるように公開してあります。
モーダルのキーはメジャー/マイナーと同じくらい信頼できますか?
いいえ。違いはプロファイルの出どころにあります。
メジャーとマイナーのキープロファイルは出版されたもの——Krumhansl–Kessler、Temperley、Sha'ath、Faraldo、Bellman–Budge——で、いずれも聴取実験かコーパスから導かれています。5 つのモーダル・プロファイル(ドリアン、フリジアン、リディアン、ミクソリディアン、ロクリアン)はそうではありません。同じ形をした構成物です。トニックをいちばん高く、その 5 度と 3 度がそれを裏づけ、そのモードを近隣のメジャー/マイナーから分かつ音がほかのスケール構成音より上に立ち、スケール外はすべて抑える、という組み立てです。意味を担っているのは順序であって、個々の数値は各重みを隣り合う重みの間に置くだけの、それ以上の根拠を持たない値です。
この構成は、それとは独立に作った合成スケールヒストグラムに対して検証してあるので循環はしていません。ただし、プローブトーン研究もアノテーション付きコーパスもその背後にはありません。モーダル検出はもっともらしいヒューリスティックであり、モーダル候補がオプトインなのはそのためです。
自分の素材で精度を測るには?
tests/fixtures/music_eval/ 以下のマニフェストに、音源・アノテーション・期待値を並べた行を書いてから、次を実行します。
export SONARE_MUSIC_FIXTURE_ROOT=/path/to/corpus
make accuracy-report出力を読む前に 2 点だけ。
CI の合否を決める行と、測定値を出す行は別の行です。合否を決める行はアサートするだけで何も出力しないため、観測値には加わりません。測定行には report_only を付けます。これでアサートが出力に変わります。1 つのマニフェストに両方を混在させて構いません。
そして集計は空集合を採点しません。観測値のない次元は unmeasured と報告され、0% にも 100% にもなりません。これは見かけ以上に重要です。使えないデータ点を飛ばして残りを平均する指標は、空集合を満点として採点します。そしてフィクスチャランナーは音源が見つからない行を、失敗ではなくスキップとして扱う設計なので、パスのタイプミスは要約行の上では成功とまったく同じに見えます。unmeasured だらけのページを結果として公開してしまってはいけないパイプラインでは、集計ツールに --require <dimension> を渡してください。
対象コーパスと手順の全体は、ライブラリ本体のリポジトリの tools/eval/README.md にあります。