Commit b4bef024 authored by Steve Tjoa's avatar Steve Tjoa

dtw initializtion

parent 324a76d1
......@@ -11820,7 +11820,7 @@ div#notebook {
<div class="text_cell_render border-box-sizing rendered_html">
<p><strong>Dynamic time warping (DTW)</strong> (<a href="https://en.wikipedia.org/wiki/Dynamic_time_warping">Wikipedia</a>; FMP, p. 131) is an algorithm used to align two sequences of similar content but possibly different lengths.</p>
<p>Given two sequences, $x[n], n \in \{0, ..., N_x - 1\}$, and $y[n], n \in \{0, ..., N_y - 1\}$, DTW produces a set of index coordinate pairs $\{ (i, j) ... \}$ such that $x[i]$ and $y[j]$ are similar.</p>
<p>We will use the same approach described in the notebooks <a href="dp.html">Dynamic Programming</a> and <a href="lcs.html">Longest Common Subsequence</a>.</p>
<p>We will use the same dynamic programming approach described in the notebooks <a href="dp.html">Dynamic Programming</a> and <a href="lcs.html">Longest Common Subsequence</a>.</p>
</div>
</div>
......@@ -11884,7 +11884,7 @@ div#notebook {
<div class="output_text output_subarea output_execute_result">
<pre>&lt;matplotlib.legend.Legend at 0x1175965d0&gt;</pre>
<pre>&lt;matplotlib.legend.Legend at 0x108828210&gt;</pre>
</div>
</div>
......@@ -12518,6 +12518,15 @@ ERGRrKfBRUREREREsp4GFxERERERyXr/ALLpGQK5/Mj/AAAAAElFTkSuQmCC
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>For more distance metrics, see <a href="https://docs.scipy.org/doc/scipy/reference/spatial.distance.html"><code>scipy.spatial.distance</code></a>.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
......@@ -12580,23 +12589,19 @@ $$ \mathrm{argmin} \ \{ d(x[i-1], y[j]), d(x[i], y[j-1]), d(x[i-1], j-1]) \} $$
<div class=" highlight hl-ipython2"><pre><span></span><span class="k">def</span> <span class="nf">dtw_table</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
<span class="n">nx</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="n">ny</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">y</span><span class="p">)</span>
<span class="n">table</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">0</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">ny</span><span class="o">+</span><span class="mi">1</span><span class="p">)]</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">nx</span><span class="o">+</span><span class="mi">1</span><span class="p">)]</span>
<span class="n">table</span> <span class="o">=</span> <span class="n">numpy</span><span class="o">.</span><span class="n">zeros</span><span class="p">((</span><span class="n">nx</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">ny</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span>
<span class="c1"># Compute left column separately, i.e. j=0.</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">nx</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">scipy</span><span class="o">.</span><span class="n">spatial</span><span class="o">.</span><span class="n">distance</span><span class="o">.</span><span class="n">euclidean</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">d</span> <span class="o">+</span> <span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
<span class="n">table</span><span class="p">[</span><span class="mi">1</span><span class="p">:,</span> <span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">numpy</span><span class="o">.</span><span class="n">inf</span>
<span class="c1"># Compute top row separately, i.e. i=0.</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">ny</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">scipy</span><span class="o">.</span><span class="n">spatial</span><span class="o">.</span><span class="n">distance</span><span class="o">.</span><span class="n">euclidean</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">y</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
<span class="n">table</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">d</span> <span class="o">+</span> <span class="n">table</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="n">table</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">:]</span> <span class="o">=</span> <span class="n">numpy</span><span class="o">.</span><span class="n">inf</span>
<span class="c1"># Fill in the rest.</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">nx</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">ny</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">scipy</span><span class="o">.</span><span class="n">spatial</span><span class="o">.</span><span class="n">distance</span><span class="o">.</span><span class="n">euclidean</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="n">y</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
<span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">d</span> <span class="o">+</span> <span class="nb">min</span><span class="p">(</span><span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="p">],</span> <span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
<span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">d</span> <span class="o">+</span> <span class="nb">min</span><span class="p">(</span><span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">],</span> <span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
<span class="k">return</span> <span class="n">table</span>
</pre></div>
......@@ -12639,7 +12644,7 @@ $$ \mathrm{argmin} \ \{ d(x[i-1], y[j]), d(x[i], y[j-1]), d(x[i-1], j-1]) \} $$
<span class="n">z0</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">z0</span> <span class="o">=</span> <span class="n">x</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">print</span> <span class="p">(</span><span class="s1">&#39;</span><span class="si">%4s</span><span class="s1"> |&#39;</span> <span class="o">%</span> <span class="n">z0</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">%4d</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">z</span> <span class="k">for</span> <span class="n">z</span> <span class="ow">in</span> <span class="n">row</span><span class="p">)</span>
<span class="k">print</span> <span class="p">(</span><span class="s1">&#39;</span><span class="si">%4s</span><span class="s1"> |&#39;</span> <span class="o">%</span> <span class="n">z0</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">%4.0f</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">z</span> <span class="k">for</span> <span class="n">z</span> <span class="ow">in</span> <span class="n">row</span><span class="p">)</span>
</pre></div>
</div>
......@@ -12658,14 +12663,14 @@ $$ \mathrm{argmin} \ \{ d(x[i-1], y[j]), d(x[i], y[j-1]), d(x[i-1], j-1]) \} $$
<div class="output_subarea output_stream output_stdout output_text">
<pre> 1 3 4 3 1 -1 -2 -1 0
+----------------------------------------
| 0 1 4 8 11 12 13 15 16 16
0 | 0 1 4 8 11 12 13 15 16 16
4 | 4 3 2 2 3 6 11 17 20 20
4 | 8 6 3 2 3 6 11 17 22 24
0 | 8 7 6 6 5 4 5 7 8 8
-4 | 12 12 13 14 12 9 7 7 10 12
-4 | 16 17 19 21 19 14 10 9 10 14
0 | 16 17 20 23 22 15 11 11 10 10
| 0 inf inf inf inf inf inf inf inf inf
0 | inf 1 4 8 11 12 13 15 16 16
4 | inf 4 2 2 3 6 11 17 20 20
4 | inf 7 3 2 3 6 11 17 22 24
0 | inf 8 6 6 5 4 5 7 8 8
-4 | inf 13 13 14 12 9 7 7 10 12
-4 | inf 18 20 21 19 14 10 9 10 14
0 | inf 19 21 24 22 15 11 11 10 10
</pre>
</div>
</div>
......@@ -12720,14 +12725,14 @@ $$ \mathrm{argmin} \ \{ d(x[i-1], y[j]), d(x[i], y[j-1]), d(x[i-1], j-1]) \} $$
<span class="n">path</span> <span class="o">=</span> <span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">)]</span>
<span class="k">while</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">j</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">minval</span> <span class="o">=</span> <span class="n">numpy</span><span class="o">.</span><span class="n">inf</span>
<span class="k">if</span> <span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">minval</span><span class="p">:</span>
<span class="n">minval</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="p">]</span>
<span class="k">if</span> <span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">minval</span><span class="p">:</span>
<span class="n">minval</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span>
<span class="n">step</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">)</span>
<span class="k">if</span> <span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">minval</span><span class="p">:</span>
<span class="n">minval</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="n">minval</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="n">step</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="k">if</span> <span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">minval</span><span class="p">:</span>
<span class="n">minval</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="n">minval</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="n">step</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">path</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">step</span><span class="p">)</span>
<span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">step</span>
......@@ -12765,7 +12770,6 @@ $$ \mathrm{argmin} \ \{ d(x[i-1], y[j]), d(x[i], y[j-1]), d(x[i-1], j-1]) \} $$
<div class="output_text output_subarea output_execute_result">
<pre>[(0, 0),
(1, 0),
(1, 1),
(2, 2),
(2, 3),
......@@ -12850,7 +12854,7 @@ $$ \mathrm{argmin} \ \{ d(x[i-1], y[j]), d(x[i], y[j-1]), d(x[i-1], j-1]) \} $$
<div class="prompt input_prompt">In&nbsp;[17]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">table</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">table</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">]</span>
</pre></div>
</div>
......
......@@ -45,7 +45,7 @@
"\n",
"Given two sequences, $x[n], n \\in \\{0, ..., N_x - 1\\}$, and $y[n], n \\in \\{0, ..., N_y - 1\\}$, DTW produces a set of index coordinate pairs $\\{ (i, j) ... \\}$ such that $x[i]$ and $y[j]$ are similar.\n",
"\n",
"We will use the same approach described in the notebooks [Dynamic Programming](dp.html) and [Longest Common Subsequence](lcs.html)."
"We will use the same dynamic programming approach described in the notebooks [Dynamic Programming](dp.html) and [Longest Common Subsequence](lcs.html)."
]
},
{
......@@ -84,7 +84,7 @@
{
"data": {
"text/plain": [
"<matplotlib.legend.Legend at 0x1175965d0>"
"<matplotlib.legend.Legend at 0x108828210>"
]
},
"execution_count": 3,
......@@ -95,7 +95,7 @@
"data": {
"image/png": "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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x1174f4210>"
"<matplotlib.figure.Figure at 0x10edab390>"
]
},
"metadata": {},
......@@ -283,6 +283,13 @@
"scipy.spatial.distance.cosine([1, 0], [-1, 0])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For more distance metrics, see [`scipy.spatial.distance`](https://docs.scipy.org/doc/scipy/reference/spatial.distance.html)."
]
},
{
"cell_type": "markdown",
"metadata": {},
......@@ -340,23 +347,19 @@
"def dtw_table(x, y):\n",
" nx = len(x)\n",
" ny = len(y)\n",
" table = [[0 for _ in range(ny+1)] for _ in range(nx+1)]\n",
" table = numpy.zeros((nx+1, ny+1))\n",
" \n",
" # Compute left column separately, i.e. j=0.\n",
" for i in range(1, nx+1):\n",
" d = scipy.spatial.distance.euclidean(x[i-1], 0)\n",
" table[i][0] = d + table[i-1][0]\n",
" table[1:, 0] = numpy.inf\n",
" \n",
" # Compute top row separately, i.e. i=0.\n",
" for j in range(1, ny+1):\n",
" d = scipy.spatial.distance.euclidean(0, y[j-1])\n",
" table[0][j] = d + table[0][j-1]\n",
" table[0, 1:] = numpy.inf\n",
" \n",
" # Fill in the rest.\n",
" for i in range(1, nx+1):\n",
" for j in range(1, ny+1):\n",
" d = scipy.spatial.distance.euclidean(x[i-1], y[j-1])\n",
" table[i][j] = d + min(table[i-1][j], table[i][j-1], table[i-1][j-1])\n",
" table[i, j] = d + min(table[i-1, j], table[i, j-1], table[i-1, j-1])\n",
" return table"
]
},
......@@ -389,14 +392,14 @@
"text": [
" 1 3 4 3 1 -1 -2 -1 0\n",
" +----------------------------------------\n",
" | 0 1 4 8 11 12 13 15 16 16\n",
" 0 | 0 1 4 8 11 12 13 15 16 16\n",
" 4 | 4 3 2 2 3 6 11 17 20 20\n",
" 4 | 8 6 3 2 3 6 11 17 22 24\n",
" 0 | 8 7 6 6 5 4 5 7 8 8\n",
" -4 | 12 12 13 14 12 9 7 7 10 12\n",
" -4 | 16 17 19 21 19 14 10 9 10 14\n",
" 0 | 16 17 20 23 22 15 11 11 10 10\n"
" | 0 inf inf inf inf inf inf inf inf inf\n",
" 0 | inf 1 4 8 11 12 13 15 16 16\n",
" 4 | inf 4 2 2 3 6 11 17 20 20\n",
" 4 | inf 7 3 2 3 6 11 17 22 24\n",
" 0 | inf 8 6 6 5 4 5 7 8 8\n",
" -4 | inf 13 13 14 12 9 7 7 10 12\n",
" -4 | inf 18 20 21 19 14 10 9 10 14\n",
" 0 | inf 19 21 24 22 15 11 11 10 10\n"
]
}
],
......@@ -408,7 +411,7 @@
" z0 = ''\n",
" else:\n",
" z0 = x[i-1]\n",
" print ('%4s |' % z0) + ''.join('%4d' % z for z in row)"
" print ('%4s |' % z0) + ''.join('%4.0f' % z for z in row)"
]
},
{
......@@ -453,14 +456,14 @@
" path = [(i, j)]\n",
" while i > 0 or j > 0:\n",
" minval = numpy.inf\n",
" if table[i-1][j] < minval:\n",
" minval = table[i-1][j]\n",
" if table[i-1, j] < minval:\n",
" minval = table[i-1, j]\n",
" step = (i-1, j)\n",
" if table[i][j-1] < minval:\n",
" minval = table[i][j-1]\n",
" minval = table[i, j-1]\n",
" step = (i, j-1)\n",
" if table[i-1][j-1] < minval:\n",
" minval = table[i-1][j-1]\n",
" minval = table[i-1, j-1]\n",
" step = (i-1, j-1)\n",
" path.insert(0, step)\n",
" i, j = step\n",
......@@ -476,7 +479,6 @@
"data": {
"text/plain": [
"[(0, 0),\n",
" (1, 0),\n",
" (1, 1),\n",
" (2, 2),\n",
" (2, 3),\n",
......@@ -558,7 +560,7 @@
}
],
"source": [
"table[-1][-1]"
"table[-1, -1]"
]
},
{
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment