为何np.shape未返回维度元组,反而输出完整列表?
为什么np.shape输出整个列表而非维度?
我在编写简单神经网络的反向传播函数时,为了调试最后一层偏置项偏导数的索引错误,插入了print(np.shape(dz[len(dz)-1]))语句,想对比变量维度与预期是否一致。但实际输出不是整数维度列表,而是整个长列表的内容:
array([None, None,
list([-178817.32020913006, 115656.44251148969, -410256.53703781555, -44727.1419577356, ...])
反向传播函数代码
def neural_network_backward(X,Y,Z,W,b,z,a): da=[0 for i in range(len(a))] dz=[0 for i in range(len(z))] dW=[0 for i in range(len(W))] db=[0 for i in range(len(b))] da[len(da)-1]=[(-Z[k]/a[len(a)-1][k]*len(Z))+((1-Z[k])/(1-a[len(a)-1][k])*len(Z)) for k in range(len(Z))] dz[len(dz)-1]=[[(Z[k]-a[len(a)-1][k])/len(Z) for k in range(len(Z))],[(a[len(a)-1][k]-Z[k])/len(Z) for k in range(len(Z))]] dW[len(dW)-1]=np.matmul(dz[len(dz)-1],np.transpose(a[len(a)-2])) print(np.shape(dz[len(dz)-1])) db[len(db)-1]=[[np.sum([dz[len(dz)-1][i][j] for i in range(np.shape(dz[len(dz)-1])[1])])] for j in range(len(b[len(b)-1]))] return da,dz,dW,db
变量说明
- X、Y:输入数值列表,长度40000
- Z:类别标签列表(元素为0或1),长度40000
- W:权重列表,每个元素为数值矩阵,长度等于网络层数
- b:偏置项列表,每个元素为列向量,长度等于网络层数
- z:存储各层非线性函数输入值的列表
- a:存储各层非线性函数输出值的列表
X、Y、Z、W、b为给定值,z和a由前向传播函数生成。
前向传播函数代码
def neural_network_forward(X,Y,W,b): depth=len(W) z=[] a=[] for i in range(depth): weights=np.array(W[i]) biases=np.array([[b[i][j] for k in range(len(X))] for j in range(len(b[i]))]) if i==0: inputs=np.array([X,Y]) z.append(np.matmul(weights,inputs)+biases) else: inputs=a[len(a)-1] z.append(np.matmul(weights,inputs)+biases) if i<depth-1: a.append([[np.amax(z[len(z)-1][j][k],0) for k in range(len(X))] for j in range(len(z[len(z)-1]))]) else: z_final=[[z[len(z)-1][j][k] for k in range(len(X))] for j in range(2)] a.append([np.exp(z_final[1][k])/(np.exp(z_final[0][k])+np.exp(z_final[1][k])) for k in range(len(X))]) loga_final=[z_final[1][k]-logadd([z_final[0][k],z_final[1][k]]) for k in range(len(X))] return z,a,loga_final
问题原因与解决办法
核心原因
dz[len(dz)-1]是纯Python嵌套列表,而非numpy数组。numpy的np.shape函数处理纯Python列表时,若列表结构不规则(或未转为数组),不会返回标准的维度元组,反而会输出包含list/array的混合结构,看起来像是直接输出了列表内容。
看反向传播代码里的赋值:
dz[len(dz)-1]=[[(Z[k]-a[len(a)-1][k])/len(Z) for k in range(len(Z))],[(a[len(a)-1][k]-Z[k])/len(Z) for k in range(len(Z))]]
这里直接生成了嵌套Python列表,没有转为numpy数组。
解决办法
- 将dz最后一层转为numpy数组:
修改赋值语句,用np.array()包裹列表生成式:
dz[len(dz)-1] = np.array([[(Z[k]-a[len(a)-1][k])/len(Z) for k in range(len(Z))],[(a[len(a)-1][k]-Z[k])/len(Z) for k in range(len(Z))]])
之后再调用np.shape(dz[-1])就会返回标准维度元组,比如(2, 40000)。
简化索引写法:
代码中大量使用的len(dz)-1可以直接用-1替代,即dz[-1]表示列表最后一个元素,更简洁且不易出错。统一用numpy数组处理张量:
神经网络运算推荐全程使用numpy数组,避免混合Python列表和numpy数组,减少维度解析和运算错误。
内容的提问来源于stack exchange,提问作者J.D.
相关产品推荐
相关产品推荐

