为何用于EURUSD预测的神经网络输出错误/无意义结果?
排查神经网络输出单一类别问题
首先,模型每次训练后都将所有测试数据归为同一类别,这通常是数据预处理、标签格式、训练参数或模型初始化方面的问题导致的,结合你的外汇预测任务和代码,咱们逐一分析并给出解决办法:
1. 优先解决:输入数据未做标准化/平稳化处理
金融时间序列(比如EURUSD的价格)是具有趋势性的非平稳数据,且数值范围较大,直接输入模型会导致梯度消失或爆炸,让模型无法学习到有效特征。你当前的代码里没有任何数据预处理步骤,这很可能是核心问题:
解决方法:
- 转换为收益率数据:用价格的收益率代替原始价格,比如每个时刻的收益率 = (当前价格 / 上一时刻价格) - 1,这样数据会更平稳,模型更容易捕捉波动规律。
- 归一化/标准化:对每个样本的960个输入值进行标准化(减去均值,除以标准差)或归一化到[0,1]区间,确保输入数据的量级一致。
示例代码(在加载数据后添加):
import numpy as np # 转换原始价格为收益率序列 def convert_to_returns(data): returns = [] for sample in data: # 计算单样本内的收益率,首个位置补0 ret = [sample[i]/sample[i-1] - 1 for i in range(1, len(sample))] ret.insert(0, 0) returns.append(ret) return returns input_data_x = convert_to_returns(input_data_x) # 对数据做标准化处理 x_np = np.array(input_data_x) mean = np.mean(x_np, axis=0) std = np.std(x_np, axis=0) # 避免除以0的情况 std[std == 0] = 1e-8 input_data_x = (x_np - mean) / std
2. 检查标签格式是否匹配损失函数
你使用的tf.nn.softmax_cross_entropy_with_logits要求标签是one-hot编码格式(比如类别0对应[1,0,0],类别1对应[0,1,0],类别2对应[0,0,1])。如果你的input_data_y是整数形式的标签(比如0、1、2),这个损失函数就无法正确计算,会导致模型学习异常。
解决方法:
- 若标签是整数格式,改用
tf.nn.sparse_softmax_cross_entropy_with_logits,修改损失函数代码:
# 假设input_data_y是整数标签(直接传入Y即可) loss_op = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits( logits=logits, labels=Y))
- 若标签不是one-hot编码,也可以提前将整数标签转换为one-hot格式。
3. 调整训练参数,优化训练稳定性
你的训练参数可能导致模型收敛不稳定,每次落到不同的局部最优(全预测某一类):
- 学习率过高:Adam优化器的默认学习率是0.001,你设置的0.005可能太大,导致梯度更新幅度过大,模型无法稳定学习。建议先降到0.001,甚至0.0001试试。
- 训练轮次不足:10个epoch可能太少,模型还没来得及学习到区分三类的特征,建议增加到50或100个epoch,观察loss是否持续下降。
- batch_size过小:batch_size=10会导致梯度噪声很大,模型更新不稳定,可以尝试增大到32或64。
4. 改进权重初始化方式
你使用tf.random_normal初始化权重,默认标准差为1,对于输入维度960的隐藏层来说,初始权重值可能过大,导致ReLU激活后大量神经元输出为0(饱和),模型无法有效传递梯度。
解决方法:
改用更适合ReLU的He初始化,偏置初始化为0更稳妥:
weights = { 'h1': tf.Variable(tf.keras.initializers.HeNormal()([n_input, n_hidden_1])), 'out': tf.Variable(tf.keras.initializers.HeNormal()([n_hidden_1, n_classes])) } biases = { 'b1': tf.Variable(tf.zeros([n_hidden_1])), 'out': tf.Variable(tf.zeros([n_classes])) }
5. 添加正则化,防止过拟合(可选)
虽然你的训练集类别均衡,但模型可能出现过拟合或者过度自信的情况,可以添加Dropout层或L2正则化:
# 修改模型定义,加入Dropout def multilayer_perceptron(x, keep_prob): layer_1 = tf.add(tf.matmul(x, weights['h1']), biases['b1']) layer_1 = tf.nn.relu(layer_1) layer_1 = tf.nn.dropout(layer_1, keep_prob=keep_prob) # 添加Dropout层 out_layer = tf.matmul(layer_1, weights['out']) + biases['out'] return out_layer # 定义占位符 keep_prob = tf.placeholder(tf.float32) logits = multilayer_perceptron(X, keep_prob) # 训练时传入keep_prob=0.5,测试时传入1.0 _, c = sess.run([train_op, loss_op], feed_dict={X: batch_x, Y: batch_y, keep_prob: 0.5}) accuracy.eval({X: input_data_x[total_batch*batch_size :], Y: input_data_y[total_batch*batch_size :], keep_prob: 1.0})
最后建议的调试步骤
- 先处理数据标准化/收益率转换,这是最可能解决问题的一步;
- 检查标签格式是否匹配损失函数;
- 调整学习率和训练轮次,观察训练过程中loss的变化,如果loss一直居高不下或波动剧烈,说明参数设置有问题;
- 改进权重初始化,再测试模型输出。
内容的提问来源于stack exchange,提问作者Rocco
相关产品推荐
相关产品推荐

