Неверный результат в ранге матрицы

У меня странная проблема с использованием numpy.linalg.matrix_rank(),
У меня есть матрица A, которая имеет три столбца и>100 строк. А состоит из 0 и 1. Когда я использую numpy.linalg.matrix_rank(A) я получил answer=3, что правильно.
Но когда я добавляю новый столбец с такой же длиной к A (теперь A имеет четыре столбца), и использую numpy.linalg.matrix_rank(A) я получил answer=1 что не имеет смысла. Числа в новом столбце указаны в тысячах. Все данные типа float32.

Кто-нибудь знает, где проблема? Спасибо!

Вот случайный пример. Это массив 40*3 А.

array([[ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 0., 0., 1.], [ 1., 0., 1.], [ 1., 1., 1.]], dtype=float32)

numpy.linalg.matrix_rank (A) равен 3.

Теперь я добавил четвертый столбец, и А теперь:

array([[  6.42096562e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  2.15370996e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  1.28050068e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  3.20350176e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  4.26681055e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  1.55057520e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  6.82897266e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  5.29479727e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  2.54858457e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  9.82017109e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  4.03392627e+03,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  2.24184062e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  6.90389688e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  2.75718145e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  6.67467109e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  4.78061758e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  1.52730410e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  9.13073359e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  1.51932471e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  9.27319297e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  7.41743359e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  7.98595469e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  3.40574414e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  3.12823730e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  5.66580273e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  4.53152070e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  9.84440938e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  7.13604375e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  3.59290312e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  8.91415820e+03,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  5.73751992e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  3.96208867e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  2.06492324e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  1.50155918e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  6.47758789e+02,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  9.27601094e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  9.77911621e+03,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  5.01128320e+04,   0.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  7.21259922e+04,   1.00000000e+00,   0.00000000e+00,
      1.00000000e+00],
   [  6.10147461e+03,   1.00000000e+00,   1.00000000e+00,
      1.00000000e+00]], dtype=float32)

numpy.linalg.matrix_rank (A) равен 2. Возможно ли это?

1 ответ

Решение

"... который не имеет смысла." На самом деле, если вы знаете, как matrix_rank оценивает ранг, это имеет смысл. matrix_rank просто подсчитывает число особых значений матрицы, которые не являются приблизительно 0. Сингулярное значение считается 0, если оно мало относительно наибольшего сингулярного значения. Когда вы добавляете четвертый столбец, содержащий числа "в тысячах", вы добавляете большое единственное значение. Три исходных единичных значения являются небольшими по сравнению с новым большим, поэтому они считаются 0 и не учитываются в рейтинге.

Вот пример. A является массивом 0 и 1. B создается путем добавления столбца, содержащего 100000 к A:

In [217]: np.random.seed(123)

In [218]: A = np.random.randint(0, 2, size=(100, 3)).astype(np.float32)

In [219]: B = np.hstack((A, 100000*np.ones((A.shape[0], 1)))).astype(np.float32)

Как и ожидалось, A имеет ранг 3:

In [220]: np.linalg.matrix_rank(A)
Out[220]: 3

Вот единственные значения A:

In [221]: np.linalg.svd(A)[1]
Out[221]: array([ 9.98757744,  5.41796255,  4.88814735], dtype=float32)

Как ваш пример, B имеет ранг 1:

In [222]: np.linalg.matrix_rank(B)
Out[222]: 1

Мы это видим B имеет одно единственное значение, которое намного больше, чем три других. Разница в величине достаточно, что matrix_rank считает меньшие единичные значения примерно 0:

In [223]: np.linalg.svd(B)[1]
Out[223]: 
array([  1.00000000e+06,   5.45980692e+00,   4.90207911e+00,
         4.59457588e+00], dtype=float32)

Обратите внимание, что matrix_rank принимает во внимание тип данных. Если B преобразуется в 64-битную с плавающей запятой, ранг вычисляется matrix_rank это 4:

In [226]: np.linalg.matrix_rank(B.astype(np.float64))
Out[226]: 4
Другие вопросы по тегам