I have the following code:
C = np.array([10 ** ((i-1)/(2-1)) for i in range(2)])
C = C *np.identity(2)
x = [1, 1]
J = (C.T + C) @ x
theta = 1e-5
alpha = 0.1
X = []
while np.sum(np.linalg.norm(alpha * J, ord=2)) >= theta:
J = (C.T + C) @ x
x -= alpha * J
X.append(x)
print("x = ", x)
print("X[i] = ", np.array(X))
Like you see, I want to perform a basic gradient descent, but this doesn’t matter right now.
The problem is the output (e.g):
x = [0.98 0.8 ]
X[i] = [[0.98 0.8 ]]
x = [0.9604 0.64 ]
X[i] = [[0.9604 0.64 ]
[0.9604 0.64 ]]
x = [0.941192 0.512 ]
X[i] = [[0.941192 0.512 ]
[0.941192 0.512 ]
[0.941192 0.512 ]]
x = [0.92236816 0.4096 ]
X[i] = [[0.92236816 0.4096 ]
[0.92236816 0.4096 ]
[0.92236816 0.4096 ]
[0.92236816 0.4096 ]]
x = [0.9039208 0.32768 ]
X[i] = [[0.9039208 0.32768 ]
[0.9039208 0.32768 ]
[0.9039208 0.32768 ]
[0.9039208 0.32768 ]
[0.9039208 0.32768 ]]
x = [0.88584238 0.262144 ]
X[i] = [[0.88584238 0.262144 ]
[0.88584238 0.262144 ]
[0.88584238 0.262144 ]
[0.88584238 0.262144 ]
[0.88584238 0.262144 ]
[0.88584238 0.262144 ]]
There is something wrong with the append function and I can’t find the reason, do you have an Idee?
>Solution :
Python is not a value-based language, but rather a reference-based language. If I write l.append(x) then I add a reference to object x to the list l. If I then later modify x, this changes l. It often takes a while to run into this problem because a lot of objects a Python beginner interacts with are immutable. But not all!
>>> x = [1, 1]
>>> l = [x]
>>> l
[[1, 1]]
>>> x[0] = 2
>>> l
[[2, 1]]
Now confusingly, x -= alpha * J is not the same as x = x - alpha * J. The former modifies x in-place, whereas the latter creates a new object.
To prevent this issue entirely I’d suggest adding a copy of x to the list:
X.append(np.copy(x))