Использование numpy и lstsq для решения 3-х мерной системы
Я пытаюсь преобразовать координаты реального мира x, y, z в мои собственные координаты виртуального мира x, y, z. Поскольку при получении координат реального мира есть шум, мне нужно использовать метод наименьших квадратов. У меня есть 3 переменные в качестве входных данных: r_x, r_y, r_z, и мне нужно иметь 3 переменных вывода v_x, v_y, v_z. Я знаю, что мне нужна только матрица A, поэтому [r_x, r_y, r_z] A = [v_x, v_y, v_z].
Вот мой код:
>>> import numpy as np
>>> x = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> y = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> A = np.vstack([x, np.ones(len(x))]).T
>>> c, resid, rank, sigma =np.linalg.lstsq(A,y)
>>> c,m = c[0:3], c[-1]
>>> x1 = np.array([1,2,3])
>>> np.dot(x1,c) + m
array([ 1.94736842, 2.31578947, 2.68421053])
Как видно, ответ неверный, так как исходная система имеет уникальное решение, а результат наименьших квадратов - очень плохое приближение. Кто-нибудь знает, что я делаю не так?
1 ответ
Основная проблема заключается в том, что ранг ваших входных данных не был достаточным для точной инверсии вашего A
матрица. Учтите следующее:
Тестовый код:
import numpy as np
def build_a(x_data):
return np.column_stack((x_data, np.ones(len(x_data))))
def lstsq(x_data, y_data):
return np.linalg.lstsq(build_a(x_data), y_data)
def show_rank(x_data):
print(lstsq(x_data, x_data)[2])
show_rank([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
show_rank([[1, 2, 3], [4, 6, 6], [7, 8, 9]])
show_rank([[1, 2, 3], [4, 6, 6], [7, 7, 9]])
show_rank([[1, 2, 3], [4, 6, 6], [7, 7, 9], [7, 8, 10]])
show_rank(np.random.rand(10, 3))
Матрица рангов:
2
3
3
4
4
Эта проблема заключается в том, что [1, 2, 3] и [4, 5, 6] находятся на одном и том же векторе и не предоставляют больше информации, поэтому путем небольшого смешения пар ранг можно увеличить. Но нам нужен ранг 4, так как мы также получаем смещения, поэтому нам нужно как минимум 4 выборки, чтобы получить матрицу 4 ранга.
пример
x = np.array([[1, 2, 3], [4, 5, 16], [17, 8, 9], [7, 8, 19]])
C, resid, rank, sigma = lstsq(x, x + 1)
c, m = C[0:3], C[-1]
x1 = np.array([1, 2, 4])
print(np.dot(x1, c) + m)
print(rank)
Результаты:
[ 2. 3. 5.]
4