матричный ранг 1 означает, что все строки равны нулю или одинаковы с точностью до масштабирования, и то же самое верно для столбцов.Они также имеют масштабирование, равное двум факторам.Поэтому вы можете восстановить их, используя что-то вроде
I,J = np.unravel_index(np.abs(kernel).argmax(), kernel.shape)
f1 = np.nansum(kernel / (kernel[None,:,J]@kernel),1,keepdims=True)
f2 = np.nansum(kernel / (kernel@kernel[I,:,None]),0,keepdims=True)
scaling = np.sqrt(np.abs(kernel).sum()/np.abs(f1*f2).sum())
f1 *= scaling * np.sign(f1[I,0]) * np.sign(kernel[I,J])
f2 *= scaling * np.sign(f2[0,J])
Обратите внимание, что большая часть сложности связана с моей попыткой собрать как можно больше данных.Проще, но я бы предположил, что численно не совсем стабильный метод будет
I,J = np.unravel_index(np.abs(kernel).argmax(), kernel.shape)
f1 = kernel[:,J,None]
f2 = kernel[None,I,:] / kernel[I,J]
Конечно, ваш метод также работает, когда вы правильно настроили индексирование:
k1 = u[:,0,None] * np.sqrt(s[0])
k2 = v[None,0,:] * np.sqrt(s[0])
np.allclose(kernel, k1*k2)
# True