Python调用sigmoid后weighted_sum被意外修改的原因咨询
异常问题底层原因
这个现象的触发逻辑非常明确:NumPy 数组采用引用传递,且编写的 sigmoid 函数存在原地修改传入数组的行为,整个流程的连锁反应如下:
- 在
feed_forward中通过np.add、np.dot生成的weighted_sum是一个 NumPy 数组实例,把它作为参数传给sigmoid时,Python 传递的是这个数组的内存地址引用,不是数组里存的数值拷贝。 - 编写的
sigmoid函数内部,通过双层循环逐位给传入的input_matrix重新赋值:input_matrix[i,j] = 1 / (1 + math.exp(-(input_matrix[i,j]))),这类对数组元素的直接赋值属于原地修改内存内容,全程没有生成新的数组对象。 - 等 sigmoid 跑完,原本存着加权和数值(也就是预期的0)的那块内存,已经被覆盖成了 sigmoid 算出来的结果(0.5)。而
feed_forward里的weighted_sum变量从始至终都指向这块被改过的内存,activation接收到的返回值也是这块内存的引用。最后返回的列表里两个元素本质上是同一个数组,打印出来的值当然完全一样,原本的加权和早就被冲掉了。
为什么重算 weighted_sum 就能输出正常结果
在 sigmoid 执行完之后重新跑一遍 weighted_sum = np.add(np.dot(W_L_1,A_L_0), B_L_1),会在内存里新开一块独立的、没被 sigmoid 改过的数组空间,这时候 weighted_sum 指向的新数组和被 sigmoid 改过的 activation 完全没有内存关联,自然就能输出正确的0值。但这种方法要重复做一遍矩阵点积和加法,属于冗余计算,在数据量大的时候性能损耗非常明显。
更高效的修复方案
- 最直接的改法是在
sigmoid函数开头加一行拷贝逻辑:input_matrix = input_matrix.copy()。后续循环修改的是这个拷贝出来的独立数组,完全不会影响外面传进来的原始weighted_sum,从根源上切断两个变量的内存关联。 - 直接把双层循环的 sigmoid 实现换成 NumPy 原生的向量化运算:
return 1 / (1 + np.exp(-input_matrix))。这类 NumPy 内置运算默认会生成全新的数组存结果,根本不会出现原地修改原数组的问题,而且运算速度比双层 Python 循环快几十上百倍。
内容的提问来源于stack exchange,提问作者Joth
相关产品推荐
相关产品推荐

