You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编写神经网络代码时出现不一致的Python错误求助

问题

这是之前提问的后续,我在编写并运行神经网络代码时持续遇到非一致性错误:同一代码运行时会出现不同报错。部分原因可归为随机函数导致的数据变化,但并非全部——用np.save保存数据后关闭Python,再重新用np.load加载,错误可能消失。

可复现代码

import numpy as np
import random

def generate_data(n,var0,var1):
    data=[]
    for i in range(n):
        z=np.random.binomial(1,0.5)
        if z==0:
            x,y=np.random.multivariate_normal(mean=[0,0],cov=[[1,var0],[var0,1]])
        elif z==1:
            x,y=np.random.multivariate_normal(mean=[1,1],cov=[[1,var1],[var1,1]])
        data.append([x,y,z])
    return data

def cross_validation(data):
    n=len(data)
    copy=list(data)
    random.shuffle(copy)
    part0=copy[0:int(n/5)]
    part1=copy[int(n/5):int(2*n/5)]
    part2=copy[int(2*n/5):int(3*n/5)]
    part3=copy[int(3*n/5):int(4*n/5)]
    part4=copy[int(4*n/5):n]
    partitioned_copy=[part0,part1,part2,part3,part4]
    folds=[]
    for i in range(5):
        training_set=[]
        for j in range(5):
            if j!=i:
                for point in partitioned_copy[j]:
                    training_set.append(point)
        testing_set=partitioned_copy[i]
        folds.append([training_set,testing_set])
    return folds

# 对数域下的加减运算函数
def logadd(x):
    n=np.max([int(num) for num in x])
    y=[num-n for num in x]
    ey=np.exp(y)
    return n+np.log(np.sum(ey))

def logsubtract(a,b):
    n=np.max([int(a),int(b)])
    return n+np.log(np.exp(a-n)-np.exp(b-n))

def initialize_network(layer_sizes):
    W=[]
    b=[]
    for i in range(len(layer_sizes)):
        if i==0:
            W.append(np.random.randn(layer_sizes[i],2))
        else:
            W.append(np.random.randn(layer_sizes[i],layer_sizes[i-1]))
        b.append(np.zeros(layer_sizes[i]))
    return W,b

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(np.shape(z[len(z)-1])[0])])
        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

def neural_network_backward(X,Y,Z,W,b,z,a):
    depth=len(W)
    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]))
    db[len(db)-1]=[[np.sum([dz[len(dz)-1][i][j] for j in range(np.shape(dz[len(dz)-1])[1])])] for i in range(np.shape(dz[len(dz)-1])[0])]
    for i in reversed(range(depth-1)):
        da[i]=np.matmul(np.transpose(W[i+1]),dz[i+1])
        dz[i]=np.empty([np.shape(z[i])[0],len(X)])
        for j in range(np.shape(z[i])[0]):
            for k in range(len(X)):
                if z[i][j][k]>0:
                    dz[i][j][k]=da[i][j][k]
                elif z[i][j][k]<0:
                    dz[i][j][k]=0
        if i>0:
            dW[i]=np.matmul(dz[i],np.transpose(a[i-1]))
        elif i==0:
            dW[i]=np.matmul(dz[i],np.transpose(np.array([X,Y])))
        db[i]=[[np.sum([dz[i][j][k] for k in range(np.shape(dz[i])[1])])] for j in range(np.shape(dz[i])[0])]
    return da,dz,dW,db

def cost(X,Y,Z,W,b,loga_final):
    total_loss=0
    def loss(loga,z):
        return -(z*loga+(1-z)*logsubtract(0,loga))
    for k in range(len(Z)):
        total_loss+=loss(loga_final[k],Z[k])/len(Z)
    return total_loss

def gradient_descent(X,Y,Z,W_start,b_start,learning_rate):
    cost_history=[]
    forward=neural_network_forward(X,Y,W_start,b_start)
    previous_cost=np.inf
    current_cost=cost(X,Y,Z,W_start,b_start,forward[2])
    cost_history.append(current_cost)
    a=forward[1]
    z=forward[0]
    W=W_start
    b=b_start
    while previous_cost-current_cost>=0.001:
        backward=neural_network_backward(X,Y,Z,W_start,b_start,forward[0],forward[1])
        backward02=learning_rate*backward[0][2]
        break
    return backward02
# 原函数还有更多逻辑,这里只保留会出错的部分并直接break

def neural_network(folds):
    basic_accuracies = []
    correct_predictions = 0  # 临时定义避免未定义错误
    for i in range(1):
    # 测试用只跑1折,实际应该是range(5)
        training_set=folds[i][0]
        testing_set=folds[i][1]
        X=[training_set[k][0] for k in range(len(training_set))]
        Y=[training_set[k][1] for k in range(len(training_set))]
        Z=[training_set[k][2] for k in range(len(training_set))]
        basic_accuracies.append(correct_predictions/len(testing_set))
        W,b=initialize_network([3,5,2])
    return X,Y,Z,W,b
# 原函数还有更多逻辑,这里只保留到能获取参数变量的部分

grid_values=[0.1*i for i in range(-9,-8)]
# 测试用只取一个值
        
progress=0
for var0 in grid_values:
    for var1 in grid_values:
        print(progress)
        data=generate_data(50000,var0,var1)
        X=[data[i][0] for i in range(len(data))]
        Y=[data[i][1] for i in range(len(data))]
        Z=[data[i][2] for i in range(len(data))]
        folds=cross_validation(data)
        X,Y,Z,W,b=neural_network(folds)
        backward02=gradient_descent(X,Y,Z,W,b,0.01)
        progress+=1

出现的两种错误

  • UnboundLocalError: local variable 'backward02' referenced before assignment(指向return backward02行)
  • TypeError: can't multiply sequence by non-int of type 'float'(指向backward02=learning_rate*backward[0][2]行)

我无法理解第一个错误:while循环理应执行一次后break,会在return前给backward02赋值。对于第二个错误,删除乘以learning_rate的操作后错误消失;查看变量发现backward[0][2]是浮点列表,但直接乘浮点数会报错,然而用np.save保存后关闭Python再重新加载,就能正常乘0.01。


问题原因分析

1. UnboundLocalError的原因

当previous_cost - current_cost < 0.001时,while循环条件不满足,循环体完全不会执行,此时backward02从未被赋值,直接return就会触发这个错误。

触发这个情况的核心原因是:初始损失计算可能出现异常值。比如loga_final中如果出现nan或inf,会导致current_cost变成nan,此时np.inf - nan的结果还是nan,而nan >= 0.001的判断结果为False,循环直接跳过。

2. TypeError的原因

backward[0][2]是Python原生列表,Python规则里列表只能和整数相乘(实现列表重复的效果),和浮点数相乘就会触发类型错误。

保存再加载后能正常运行的原因:np.save会自动将列表转为numpy数组,加载后得到的是numpy数组,而numpy数组支持和浮点数做元素级乘法,因此不会报错。

额外潜在问题

代码里还有几处未定义变量的错误,比如原neural_network函数里的basic_accuracies和correct_predictions未提前定义,这也会导致运行时错误,建议优先修复这类基础问题。


内容的提问来源于stack exchange,提问作者J.D.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 10:29:56