用Python神经网络做预测,训练出来的权值和阈值都是nan值,误差越训练越大,求解?
论文题目选的这方面,自己也的确没有基础,参考了别人的代码,结果就悲剧了 = =
代码和数据,在这里: http://bbs.csdn.net/topics/392171719
请大家帮忙看看,感激不尽!
用Python神经网络做预测,训练出来的权值和阈值都是nan值,误差越训练越大,求解?
梯度爆炸了吧
这问题我遇到过,八成是梯度爆炸了。NaN值出现通常是因为计算过程中数值溢出,比如激活函数输入值太大导致指数运算溢出。
给你个能跑的解决方案:
import numpy as np
class NeuralNetwork:
def __init__(self, input_size, hidden_size, output_size):
# 初始化权重 - 使用Xavier初始化防止梯度爆炸
self.W1 = np.random.randn(input_size, hidden_size) * np.sqrt(2.0 / input_size)
self.b1 = np.zeros((1, hidden_size))
self.W2 = np.random.randn(hidden_size, output_size) * np.sqrt(2.0 / hidden_size)
self.b2 = np.zeros((1, output_size))
def relu(self, x):
return np.maximum(0, x)
def forward(self, X):
# 前向传播
self.z1 = np.dot(X, self.W1) + self.b1
self.a1 = self.relu(self.z1)
self.z2 = np.dot(self.a1, self.W2) + self.b2
return self.z2 # 回归问题用线性输出
def train(self, X, y, learning_rate=0.001, epochs=1000):
m = X.shape[0]
for epoch in range(epochs):
# 前向传播
output = self.forward(X)
# 计算损失 - 用MSE
loss = np.mean((output - y) ** 2)
# 反向传播
d_output = 2 * (output - y) / m
# 梯度裁剪 - 防止梯度爆炸的关键
d_output = np.clip(d_output, -1, 1)
dW2 = np.dot(self.a1.T, d_output)
db2 = np.sum(d_output, axis=0, keepdims=True)
d_a1 = np.dot(d_output, self.W2.T)
d_a1[self.a1 <= 0] = 0 # ReLU导数
dW1 = np.dot(X.T, d_a1)
db1 = np.sum(d_a1, axis=0, keepdims=True)
# 更新参数
self.W1 -= learning_rate * dW1
self.b1 -= learning_rate * db1
self.W2 -= learning_rate * dW2
self.b2 -= learning_rate * db2
if epoch % 100 == 0:
print(f"Epoch {epoch}, Loss: {loss:.6f}")
return self.W1, self.b1, self.W2, self.b2
# 使用示例
if __name__ == "__main__":
# 生成示例数据
np.random.seed(42)
X = np.random.randn(100, 3)
y = np.random.randn(100, 1)
# 数据标准化 - 很重要!
X = (X - np.mean(X, axis=0)) / np.std(X, axis=0)
y = (y - np.mean(y)) / np.std(y)
# 创建和训练网络
nn = NeuralNetwork(input_size=3, hidden_size=5, output_size=1)
weights = nn.train(X, y, learning_rate=0.01, epochs=1000)
print("\n训练完成,权重非NaN验证:")
for name, param in zip(['W1', 'b1', 'W2', 'b2'], weights):
print(f"{name}: 包含NaN值 - {np.any(np.isnan(param))}")
核心就三件事:权重用Xavier初始化、数据必须标准化、梯度记得裁剪。学习率从0.01开始试,大了容易炸。
标准化数据,初始化权重,裁剪梯度。
搜索了一下,梯度爆炸好像是深度神经网络才会出现的,我这个才一个隐层也会炸吗?= =,请问具体怎么解决呢?
只试过 tensorflow 的,楼主提供代码哪里写了梯度下降,我并没有看懂,是 dw 那几行么。。。还有这种是不应该用 dummy variable ??把属性拓展到列,是哪个属性就在哪一列标 1。还发现一个问题是楼主应该想训练出那个表上各个属性的权重吧?为啥输入层就俩 w,俩 b
python 的话,有 nan 值可能是因为你数据本来就有 nan,然后在做矩阵计算的时候传染得所有数都变成了 nan
昨天新学了个词 过拟合?
梯度爆炸了。
有没有随机初始化到一个小值啊,有没有矩阵求解时候低秩啊,信息太少不好诊断
numpy 的 nan 会传播的,检查一下开始有没有 nan 吧
我看 BP 算法中,对偏置项 b 的更新 db 貌似不应该乘以矩阵吧。直接用 delta 就行了。
更新权重的时候,为什么要用+=?
还有,你那不是归一化,只能算 CategoricalEncode
我也是菜鸟,我看原 bolg 的代码对输入和输出都做了归一化,你的输出没有归一化导致求出的 loss 太大吧
我建议你用正经的框架写,比如 TensorFlow,而不是 NumPy 手撸,不然浪费你我的时间。
原因是这样的,你作为初学者,写出来的代码,无论是命名方式还是结构性都太差了(和违反 Neural Network 业内的 Best Practice ),懂的人看你的代码就好像 C++ 的老手看初学者仿照谭浩强的教材写出来的代码那么痛苦。
https://www.tensorflow.org
学习率太大了。
这种数据应该先用 statsmodels 或 sklearn 中的模型试试看。这里有 boston 房价的例子:
http://cs.smith.edu/dftwiki/index.php/Tutorial:_Playing_with_the_Boston_Housing_Data
对于分类数据你需要进行 one hot 编码,例如 http://blog.csdn.net/bitcarmanlee/article/details/51472816


