Несоответствие в вычислении — Python и numpy

#python #python-3.x #numpy

#python #python-3.x #numpy

Вопрос:

Код, который я пытаюсь запустить, является:

 import numpy as np
x = [np.array([[          0,     0.66111,       0.325,    0.061111,    0.070833]],        dtype=np.float32), np.array([     2.6026], dtype=np.float32), np.array([    -84.806], dtype=np.float32)]
ratio, w, h, pad  = (1.0, 1.0) ,640 ,426 ,(0.0, 107.0)

labels = x.copy()
print('labels before computation', labels[0])
print(ratio[0] * w * (x[0][:, 1]   x[0][:, 3] / 2)   pad[0])
print(ratio[1] * h * (x[0][:, 2]   x[0][:, 4] / 2)   pad[1])
labels[0][:, 1] = ratio[0] * w * (x[0][:, 1] - x[0][:, 3] / 2)   pad[0]  
labels[0][:, 2] = ratio[1] * h * (x[0][:, 2] - x[0][:, 4] / 2)   pad[1]  
labels[0][:, 3] = ratio[0] * w * (x[0][:, 1]   x[0][:, 3] / 2)   pad[0]
labels[0][:, 4] = ratio[1] * h * (x[0][:, 2]   x[0][:, 4] / 2)   pad[1]
print('labels after computation', labels[0])
 

Результат:

 labels before computation [[0.       0.66111  0.325    0.061111 0.070833]]
[442.6659]
[260.5374]
labels after computation [[0.0000000e 00 4.0355487e 02 2.3036258e 02 2.5829467e 05 9.8256547e 04]]
 

Значения, напечатанные 2-м и 3-м операторами, верны. Но, когда я пытаюсь присвоить значения, выведенные одним и тем же вычислением, меткам [0] [:, 3] и меткам [0] [:, 4] соответственно, присваиваются некоторые ненужные значения.

Если я удалю операции присваивания в строках 9 и 10 и выполню приведенный ниже код, результат будет нормальным.

 import numpy as np

x = [np.array([[          0,     0.66111,       0.325,    0.061111,    0.070833]], dtype=np.float32), np.array([     2.6026], dtype=np.float32), np.array([    -84.806], dtype=np.float32)]
ratio, w, h, pad  = (1.0, 1.0) ,640 ,426 ,(0.0, 107.0)

labels = x.copy()
print('labels before computation', labels[0])
print(ratio[0] * w * (x[0][:, 1]   x[0][:, 3] / 2)   pad[0])
print(ratio[1] * h * (x[0][:, 2]   x[0][:, 4] / 2)   pad[1])
labels[0][:, 3] = ratio[0] * w * (x[0][:, 1]   x[0][:, 3] / 2)   pad[0]
labels[0][:, 4] = ratio[1] * h * (x[0][:, 2]   x[0][:, 4] / 2)   pad[1]
print('labels after computation', labels[0])
 

Вывод:

 labels before computation [[0.       0.66111  0.325    0.061111 0.070833]]
[442.6659]
[260.5374]
labels after computation [[0.000000e 00 6.611100e-01 3.250000e-01 4.426659e 02 2.605374e 02]]
 

Может кто-нибудь, пожалуйста, объяснить причину несоответствия?

Моя среда:
версия Python: 3.6.9
Версия Numpy: 1.19.4

Спасибо!

Ответ №1:

С

 labels = x.copy()
 

вы создаете только поверхностную копию x , элементами которой являются массивы, следовательно, изменяя labels[0][:, 1] и labels[0][:, 2] изменяя одни и те же поля в x

Проверьте также документы copy функции:

Обратите внимание, что np.copy является мелкой копией и не будет копировать элементы объекта в массивах. Это в основном важно для массивов, содержащих объекты Python. Новый массив будет содержать тот же объект, что может привести к неожиданностям, если этот объект может быть изменен (является изменяемым):

и решение:

Чтобы гарантировать, что все элементы в массиве объектов скопированы, используйте copy.deepcopy:

В вашем случае:

 import numpy as np
x = [np.array([[          0,     0.66111,       0.325,    0.061111,    0.070833]],        dtype=np.float32), np.array([     2.6026], dtype=np.float32), np.array([    -84.806], dtype=np.float32)]
ratio, w, h, pad  = (1.0, 1.0) ,640 ,426 ,(0.0, 107.0)
import copy
labels = copy.deepcopy(x)
print('labels before computation', labels[0])
print(ratio[0] * w * (x[0][:, 1]   x[0][:, 3] / 2)   pad[0])
print(ratio[1] * h * (x[0][:, 2]   x[0][:, 4] / 2)   pad[1])
labels[0][:, 1] = ratio[0] * w * (x[0][:, 1] - x[0][:, 3] / 2)   pad[0]
labels[0][:, 2] = ratio[1] * h * (x[0][:, 2] - x[0][:, 4] / 2)   pad[1]
labels[0][:, 3] = ratio[0] * w * (x[0][:, 1]   x[0][:, 3] / 2)   pad[0]
labels[0][:, 4] = ratio[1] * h * (x[0][:, 2]   x[0][:, 4] / 2)   pad[1]
print('labels after computation', labels[0])
 

Вывод:

 labels before computation [[0.       0.66111  0.325    0.061111 0.070833]]
[442.66592]
[260.537429]
labels after computation [[  0.       403.55488  230.362571 442.66592  260.537429]]