1

I'm running the following code in python:

w= np.random.rand(3) 
w_old=np.zeros((3,))

while (np.linalg.norm(w - w_old)) / np.linalg.norm(w) > 1e-5:

    w_old=w

    print w
    print w_old

    w[0]-=eta*dE1i
    w[1]-=eta*dE2i
    w[2]-=eta*dE3i

    print w
    print w_old

The results for the prints are :

[ 0.22877423  0.59402658  0.16657174]

[ 0.22877423  0.59402658  0.16657174]

and

[ 0.21625852  0.5573612   0.123111  ]

[ 0.21625852  0.5573612   0.123111  ]

I'm wondering why the value of w_old has been changed? Shouldn't it be updated after going back to the beginning of the while loop? How can I fix this?

1
  • 4
    Every change to w also affects w_old. The equals assignment isn't doing what you think it does Commented Aug 18, 2017 at 0:18

3 Answers 3

2

Just using

w_old = w

doesn't copy w, using = just tells python that you want another name for whatever is stored in w. So every in-place change to w will also change w_old. There is a really nice blog post about it in case you want more details Ned Batchelder: "Facts and myths about Python names and values"

You can explicitly copy a numpy array, for example, using the copy method:

w_old = w.copy()
Sign up to request clarification or add additional context in comments.

Comments

1

Just to clear things up, variables are independent so:

a=5
b=a

will work just fine if you change either a or b. But lists and dictionaries cannot be copied the same way, so:

a=[1,2]
b=a
a[0]=100
print(b[0])

will give you 100 because now a and b are the same thing with two names. So as suggested before use

w_old = w.copy()

instead so w_old is a new list and not just another name for the old one.

1 Comment

Even they are just integers: assignment won't copy them. The difference is just that: There is no way you can change an integer in-place so you never "notice" that it's the same object (except when you use is).
0

Just to conclude the answers above, according to python documentation

Assignment statements in Python do not copy objects, they create bindings between a target and an object.

So, the solution is

For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other.

So using copy() we can rewrite the code as

import numpy as np

w= np.random.rand(3)
w_old=np.zeros((3,))

while (np.linalg.norm(w - w_old)) / np.linalg.norm(w) > 1e-5:

    w_old=w.copy()

    print(w)
    print(w_old)

    w[0]-=0.01
    w[1]-=0.01
    w[2]-=0.01

    print(w)
    print(w_old)

and get

[0.79666571 0.82305671 0.41167625]
[0.79666571 0.82305671 0.41167625]

and

[0.78666571 0.81305671 0.40167625]
[0.79666571 0.82305671 0.41167625]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.