PhiloRobotist
PhiloRobotist

Reputation: 337

Inconsistency in a calculation - Python & numpy

The code I'm trying to run is:

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])

The output is:

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]]

The values printed by the 2nd & 3rd statements are correct. But, when I'm trying to assign the values outputted by the same computation to labels[0][:, 3] & labels[0][:, 4] respectively, some junk values are being assigned.

If I remove assignment ops in lines 9 & 10 & run the below code, the output is normal.

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])

Output:

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]]

Can someone plz explain the reason behind inconsistency?

My environment:
Python version: 3.6.9
Numpy version: 1.19.4

Thanks!

Upvotes: 2

Views: 97

Answers (1)

FlyingTeller
FlyingTeller

Reputation: 20482

With

labels = x.copy()

you only create a shallow copy of x, which has arrays as its elements, hence changing labels[0][:, 1] and labels[0][:, 2] changes the same fields in x

Check also the docs of the copy function:

Note that np.copy is a shallow copy and will not copy object elements within arrays. This is mainly important for arrays containing Python objects. The new array will contain the same object which may lead to surprises if that object can be modified (is mutable):

and the solution:

To ensure all elements within an object array are copied, use copy.deepcopy:

In your case:

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])

Output:

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]]

Upvotes: 2

Related Questions