Skip to content

Commit 0ee74c9

Browse files
committed
modify dtw_merge
1 parent 5e04516 commit 0ee74c9

3 files changed

Lines changed: 71 additions & 18 deletions

File tree

diffsptk/functional.py

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -572,36 +572,27 @@ def dtw(
572572
)
573573

574574

575-
def dtw_merge(x: Tensor, y: Tensor, indices: Tensor) -> tuple[Tensor, Tensor]:
576-
"""Align two vector sequences according to the given path.
575+
def dtw_merge(x: Tensor, y: Tensor, indices: Tensor) -> Tensor:
576+
"""Merge two sequences according to the given indices.
577577
578578
Parameters
579579
----------
580-
x : Tensor [shape=(T1, ...)]
580+
x : Tensor [shape=(T1, D) or (T1,)]
581581
The query vector sequence.
582582
583-
y : Tensor [shape=(T2, ...)]
583+
y : Tensor [shape=(T2, D) or (T2,)]
584584
The reference vector sequence.
585585
586586
indices : Tensor [shape=(T, 2)]
587-
The indices of the path.
587+
The indices of the viterbi path.
588588
589589
Returns
590590
-------
591-
x_align : Tensor [shape=(T, ...)]
592-
The aligned query vector sequence.
593-
594-
y_align : Tensor [shape=(T, ...)]
595-
The aligned reference vector sequence.
591+
z : Tensor [shape=(T, 2D) or (T, 2)]
592+
The merged vector sequence.
596593
597594
"""
598-
if x.dim() != y.dim():
599-
raise ValueError("x and y must have the same number of dimensions.")
600-
if indices.dim() != 2 or indices.size(-1) != 2:
601-
raise ValueError("The shape of indices must be (T, 2).")
602-
x_align = x[indices[:, 0]]
603-
y_align = y[indices[:, 1]]
604-
return x_align, y_align
595+
return nn.DynamicTimeWarping.merge(x=x, y=y, indices=indices)
605596

606597

607598
def entropy(p: Tensor, out_format: str = "nat") -> Tensor:

diffsptk/modules/dtw.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,3 +327,55 @@ def _forward(
327327
if return_indices:
328328
return distance, indices
329329
return distance
330+
331+
@staticmethod
332+
def merge(
333+
x: torch.Tensor,
334+
y: torch.Tensor,
335+
indices: torch.Tensor,
336+
) -> torch.Tensor:
337+
"""Merge two sequences according to the given indices.
338+
339+
Parameters
340+
----------
341+
x : Tensor [shape=(T1, D) or (T1,)]
342+
The query vector sequence.
343+
344+
y : Tensor [shape=(T2, D) or (T2,)]
345+
The reference vector sequence.
346+
347+
indices : Tensor [shape=(T, 2)]
348+
The indices of the viterbi path.
349+
350+
Returns
351+
-------
352+
z : Tensor [shape=(T, 2D) or (T, 2)]
353+
The merged vector sequence.
354+
355+
Examples
356+
--------
357+
>>> import diffsptk
358+
>>> dtw = diffsptk.DynamicTimeWarping(p=1)
359+
>>> x = torch.tensor([1., 3., 6., 9.])
360+
>>> y = torch.tensor([2., 3., 8., 8.])
361+
>>> _, indices = dtw(x, y, return_indices=True)
362+
>>> z = dtw.merge(x, y, indices[0])
363+
>>> z
364+
tensor([[1., 2.],
365+
[3., 3.],
366+
[6., 8.],
367+
[9., 8.],
368+
[9., 8.]])
369+
370+
"""
371+
if x.dim() != y.dim():
372+
raise ValueError("x and y must have the same number of dimensions.")
373+
if indices.dim() != 2 or indices.size(-1) != 2:
374+
raise ValueError("The shape of indices must be (T, 2).")
375+
x_expanded = x[indices[:, 0]]
376+
y_expanded = y[indices[:, 1]]
377+
if x.dim() == 1:
378+
z = torch.stack([x_expanded, y_expanded], dim=-1)
379+
else:
380+
z = torch.cat([x_expanded, y_expanded], dim=-1)
381+
return z

tests/test_dtw.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def _dtw(x, y):
4545
assert np.allclose(output_distance, target_distance), (
4646
f"Output: {output_distance}\nTarget: {target_distance}"
4747
)
48-
return torch.cat(diffsptk.functional.dtw_merge(x, y, indices[0]), dim=-1)
48+
return diffsptk.functional.dtw_merge(x, y, indices[0])
4949

5050
U.check_compatibility(
5151
device,
@@ -75,3 +75,13 @@ def test_various_shape(T=10):
7575
[(1, T, 1), (1, T, 1)],
7676
],
7777
)
78+
79+
indices = torch.stack([torch.arange(T), torch.arange(T)], dim=-1)
80+
dtw_merge = lambda x, y: diffsptk.functional.dtw_merge(x, y, indices)
81+
U.check_various_shape(
82+
dtw_merge,
83+
[
84+
[(T,), (T,)],
85+
[(T, 1), (T, 1)],
86+
],
87+
)

0 commit comments

Comments
 (0)