Error measures for DR chords: Difference between revisions

ArrowHead294 (talk | contribs)
Formatting, nowrap stuff
Inthar (talk | contribs)
Fully DR, rooted linear: Correct analytical solution for x
 
(9 intermediate revisions by the same user not shown)
Line 3: Line 3:


== Conventions and introduction ==
== Conventions and introduction ==
The idea motivating least-squares error measures on a chord as an approximation to a given delta signature is the following (for simplicity, let’s talk about the fully DR case first):
The idea motivating least-squares error measures on a chord as an approximation to a given delta signature is the following:


We want the error of a chord {{nowrap|1:''r''<sub>1</sub>:''r''<sub>2</sub>:...:''r''<sub>''n''</sub>}} (in increasing order), with {{nowrap|''n'' &gt; 1}}, in the linear domain as an approximation to a fully delta-rational chord with signature {{nowrap|+δ<sub>1</sub> +δ<sub>2</sub> ... +δ<sub>''n''</sub>}}, i.e. a chord
We want the error of a chord {{nowrap|1:''r''<sub>1</sub>:''r''<sub>2</sub>:...:''r''<sub>''n''</sub>}} (in increasing order, we also take {{nowrap|''r''<sub>0</sub> {{=}} 1}}), with {{nowrap|''n'' &gt; 1}}, in the linear domain as an approximation to a delta-rational chord with signature {{nowrap|+δ<sub>1</sub> +δ<sub>2</sub> ... +δ<sub>''n''</sub>}} (possibly with some deltas free), i.e. a chord


<math>x : x + \delta_1 : \cdots : x + \sum_{l=1}^n \delta_l</math>
<math>x : x + \delta_1 : \cdots : x + \sum_{l=1}^n \delta_l</math>
Line 11: Line 11:
with root real-valued harmonic ''x''. Let <math>D_0 = 0, D_i = \sum_{k=1}^i \delta_k</math> be the delta signature {{nowrap|+δ<sub>1</sub> +δ<sub>2</sub> ... +δ<sub>''n''</sub>}} written cumulatively.
with root real-valued harmonic ''x''. Let <math>D_0 = 0, D_i = \sum_{k=1}^i \delta_k</math> be the delta signature {{nowrap|+δ<sub>1</sub> +δ<sub>2</sub> ... +δ<sub>''n''</sub>}} written cumulatively.


We want to measure the error ''without having to fix any dyad'' (as one might naively fix a dyad and measure errors in the other deltas in relation to the fixed dyad). To do this we solve a least-squares error problem: use a root-sum-square error function and optimize ''x'' (and any free deltas) to minimize that function.
We want to measure the error ''without having to fix any dyad in the target chord'' (as one might naively fix a dyad and measure errors in the other deltas in relation to the fixed dyad). To do this we solve a least-squares optimization problem: use a root-sum-square objective function and optimize ''x'' (and any free deltas) to minimize that function.


== Domain and error model ==
== Domain and error model ==
Line 21: Line 21:
** ''All-steps'': Only intervals between adjacent notes are compared.
** ''All-steps'': Only intervals between adjacent notes are compared.


We arrive at the following general formula: Let <math>[n] = \{0, 1, 2, ..., n\},</math> let <math>I \subseteq {[n] \choose 2}</math> be the error model, and let <math>f_D</math> represent the domain function (identity for linear, or <math>\log</math>). Then the error function to be minimized by optimizing <math>x</math> and any free deltas is:
We arrive at the following general formula: Let <math>[n] = \{0, 1, 2, ..., n\},</math> let <math>I \subseteq {[n] \choose 2}</math> be the error model, and let <math>f_D</math> represent the domain function (identity for linear, or <math>\log</math>). Then the objective function (measuring the error) to be minimized by optimizing <math>x</math> and any free deltas is:


<math>
<math>
Line 28: Line 28:


{| class="wikitable"
{| class="wikitable"
|+ style="font-size: 105%;" | Error function for various modes and error models
|+ style="font-size: 105%;" | Objective function for various modes and error models
|-
|-
! Domain
! Domain
! Error model
! Error model
! Error function
! Objective function
|-
|-
! rowspan="3" | Linear
! rowspan="3" | Linear
Line 64: Line 64:
Setting the derivative to 0 gives us the closed-form solution
Setting the derivative to 0 gives us the closed-form solution


<math>x = \frac{\sum_{i=1}^n D_i }{-n + \sum_{i=1}^n r_i},</math>
<math>x = \frac{\sum_{i=1}^n D_i^2 }{\sum_{i=1}^n D_i(r_i-1)},</math>


which can be plugged back into
which can be plugged back into


<math>\sqrt{\sum_{1=1}^n \Bigg( 1 + \frac{D_i}{x} - r_i \Bigg)^2 }</math>
<math>\sqrt{\sum_{i=1}^n \Bigg( 1 + \frac{D_i}{x} - r_i \Bigg)^2 }</math>


to obtain the least-squares linear error.
to obtain the least-squares linear error.
Line 154: Line 154:


=== BFGS-B (one related delta set, arbitrary free deltas) ===
=== BFGS-B (one related delta set, arbitrary free deltas) ===
We let {{nowrap|''x''<sub>1</sub> {{=}} ''x''}} and include additional free variables ''x''<sub>2</sub>, ..., ''x''<sub>n</sub>, one for every additional +?, after coalescing strings of consecutive +?'s into one +? and after trimming leading and trailing free delta segments.
We let {{nowrap|''x''<sub>1</sub> {{=}} ''x''}} and include additional free variables ''x''<sub>2</sub>, ..., ''x''<sub>''n''</sub>, one for every additional +?, after coalescing strings of consecutive +?'s into one +? and after trimming leading and trailing free delta segments.


BFGS-B is a quasi-Newton optimization method (based on BFGS) particularly suited for this problem:
BFGS-B is a quasi-Newton optimization method (based on BFGS) particularly suited for this problem:
* The error function is smooth, allowing use of gradients
* The objective function is smooth, allowing use of gradients
* Fast convergence, requiring at worst 20 iterations for accuracy
* Fast convergence, requiring at worst 20 iterations for accuracy
* Naturally deals with the {{nowrap|''x'' &gt; 0}} constraint using a log barrier and minimizing the transformed function using the unconstrained BFGS method
* Naturally deals with the {{nowrap|''x'' &gt; 0}} constraint using a log barrier and minimizing the transformed function using the unconstrained BFGS method
* Acceptable memory usage given a realistic number of parameters for practical DR chords (up to 3 interior free delta segments, thus 4 parameters).
* Acceptable memory usage given a realistic number of parameters for practical DR chords (up to 3 interior free delta segments, thus 4 parameters).


It is a ''quasi-Newton method'' because it uses an approximation of the Hessian (matrix of mixed second partial derivatives) of the error function at each step.
It is a ''quasi-Newton method'' because it uses an approximation of the Hessian (matrix of mixed second partial derivatives) of the objective function at each step.


In the Python implementation below, <code>x</code> represents the vector <math>(x_1, x_2, ..., x_n),</math> <code>x0</code> is the initial guess for the solution, and <code>f</code> is the error function.
In the Python implementation below, <code>x</code> represents the vector <math>(x_1, x_2, ..., x_n),</math> <code>x0</code> is the initial guess for the solution, and <code>f</code> is the objective function.


<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
Line 415: Line 415:


== External links ==
== External links ==
* [http://inthar-raven.github.io/delta/ Inthar's DR chord explorer (includes least-squares error calculation in both domains and multiple error models)]
* [http://turbofishcrow.github.io/delta/ Inthar's DR chord explorer (includes least-squares error calculation in both domains and multiple error models)]


[[Category:Math]]
[[Category:Math]]