梯度下降代码中列表append重复插入同一元素的原因排查
问题分析与解决思路
你遇到的问题本质是可变对象的引用传递导致的——当你把x追加到X列表时,并没有保存x当前的数值副本,而是保存了指向x这个对象的引用。之后每次循环里修改x的值时,列表X里所有指向x的引用都会同步更新,最终导致所有元素都变成最后一次迭代的x值。
具体原因拆解
你的代码里,初始x = [1,1]是一个列表,后续循环中x -= alpha * J会直接原地修改这个列表(如果J是numpy数组,执行减法后x会被隐式转换为numpy数组,但依然是可变对象)。X.append(x)只是把这个可变对象的"地址"存在了列表里,而非当前的数值快照。
解决办法:保存x的副本而非引用
只需要在追加到X时,创建x的副本即可,具体有两种方式:
方式1:如果x是列表,使用list.copy()方法
X.append(x.copy())
方式2:如果x被转换为numpy数组,使用np.copy()或.copy()方法
X.append(np.copy(x)) # 或者 X.append(x.copy())
修改后的完整代码示例
import numpy as np C = np.array([10 ** ((i-1)/(2-1)) for i in range(2)]) C = C * np.identity(2) x = np.array([1, 1]) # 建议直接初始化为numpy数组,避免隐式转换 J = (C.T + C) @ x theta = 1e-5 alpha = 0.1 X = [] while np.linalg.norm(alpha * J, ord=2) >= theta: # 这里sum可以去掉,norm本身就是标量 J = (C.T + C) @ x x -= alpha * J X.append(x.copy()) # 关键:保存副本 print("x = ", x) print("X[i] = ", np.array(X))
验证效果
修改后,X里的每个元素都会是对应迭代步骤的x值,不会再全部同步为最新值。比如第一次迭代后X是[[0.98 0.8 ]],第二次迭代后会变成[[0.98 0.8 ], [0.9604 0.64 ]],以此类推。
另外提个小优化:你的循环条件里np.sum(np.linalg.norm(...))是多余的,因为np.linalg.norm返回的已经是标量,直接用np.linalg.norm(alpha * J, ord=2) >= theta即可。
内容的提问来源于stack exchange,提问作者Sophie
相关产品推荐
相关产品推荐

