Linear projection matrix by solving the procrustes problem

626 views Asked by At

I have two matrices:

target = np.array([[1, 1, 1, 1, 1],
               [2, 2, 2, 2, 2],
               [3, 3, 3, 3, 3]])

source = np.array([[11, 11, 11, 11, 11],
               [22, 22, 22, 22, 22],
               [33, 33, 33, 33, 33]])

and I want to create a transformation matrix to project the source matrix to the target one.

I found that Scipy library provides a function to do it:

from scipy.spatial import procrustes
mtx1, mtx2, disparity = procrustes(target, source)

based on the documentation, it says that:

enter image description here

Thus, mtx2 is the projected matrix.

What if I have another data and I want to project them to the target matrix using the "learned transformation matrix" that Scipy used to project the source matrix to the target one?

How can I do it using Scipy?

1

There are 1 answers

4
seralouk On BEST ANSWER

You need to modify the function in order to return the transformation matrix (R).

The source code after removing the comments looks like:

def procrustes(data1, data2):
    mtx1 = np.array(data1, dtype=np.double, copy=True)
    mtx2 = np.array(data2, dtype=np.double, copy=True)

    if mtx1.ndim != 2 or mtx2.ndim != 2:
        raise ValueError("Input matrices must be two-dimensional")
    if mtx1.shape != mtx2.shape:
        raise ValueError("Input matrices must be of same shape")
    if mtx1.size == 0:
        raise ValueError("Input matrices must be >0 rows and >0 cols")

    # translate all the data to the origin
    mtx1 -= np.mean(mtx1, 0)
    mtx2 -= np.mean(mtx2, 0)

    norm1 = np.linalg.norm(mtx1)
    norm2 = np.linalg.norm(mtx2)

    if norm1 == 0 or norm2 == 0:
        raise ValueError("Input matrices must contain >1 unique points")

    # change scaling of data (in rows) such that trace(mtx*mtx') = 1
    mtx1 /= norm1
    mtx2 /= norm2

    # transform mtx2 to minimize disparity
    R, s = orthogonal_procrustes(mtx1, mtx2)
    mtx2 = np.dot(mtx2, R.T) * s    # HERE, the projected mtx2 is estimated.

    # measure the dissimilarity between the two datasets
    disparity = np.sum(np.square(mtx1 - mtx2))

    return mtx1, mtx2, disparity, R

Source: https://github.com/scipy/scipy/blob/v1.3.0/scipy/spatial/_procrustes.py#L17-L132