基于蓝牙信号的2输出坐标预测神经网络改造及预测方法问询
解决你的2输出回归神经网络问题 & Predict方法实现
问题拆解
你现在面临两个核心问题:
- 把现有网络改造成输出x、y坐标的回归网络(因为坐标是连续值,属于回归任务,不是分类)
- 正确实现
predict方法来验证模型的预测结果
先梳理下你当前代码里的几个关键问题:
- 权重/偏置定义错误:直接在
tf.matmul里写w1 = [self.num_input, 256]是无效的,必须用tf.Variable定义可训练参数 - 损失函数选错了:
softmax_cross_entropy_with_logits_v2是给分类任务用的,回归任务该用均方误差(MSE) - 输出层不需要softmax:回归任务输出连续值,用线性激活即可
修正后的完整代码
下面是调整后的可运行代码,我标注了关键修改点:
import tensorflow as tf import numpy as np class Network: def __init__(self, input_data, labels, learning_rate=0.001, batch_size=32): self.input = input_data self.labels = labels self.num_input = input_data.shape[1] self.num_output = labels.shape[1] # 自动适配2输出,因为你的labels是[N,2]格式 self.learning_rate = learning_rate self.batch_size = batch_size self.numpy_input = np.array(input_data) self.numpy_labels = np.array(labels) # 1. 定义输入输出占位符 self.X = tf.placeholder("float", [None, self.num_input]) self.Y = tf.placeholder("float", [None, self.num_output]) # 2. 工具函数:初始化可训练的权重和偏置(关键修正) def weight_variable(shape): return tf.Variable(tf.random_normal(shape, stddev=0.01)) def bias_variable(shape): return tf.Variable(tf.constant(0.1, shape=shape)) # 定义各层参数,这里保留你提到的5层结构(示例简化为2层,你可以自行扩展) w1 = weight_variable([self.num_input, 256]) b1 = bias_variable([256]) w2 = weight_variable([256, 128]) b2 = bias_variable([128]) w3 = weight_variable([128, 64]) b3 = bias_variable([64]) w4 = weight_variable([64, 32]) b4 = bias_variable([32]) w5 = weight_variable([32, 128]) b5 = bias_variable([128]) w_last = weight_variable([128, self.num_output]) b_last = bias_variable([self.num_output]) # 3. 构建网络层,隐藏层用relu激活 self.layer_1 = tf.nn.relu(tf.add(tf.matmul(self.X, w1), b1)) self.layer_2 = tf.nn.relu(tf.add(tf.matmul(self.layer_1, w2), b2)) self.layer_3 = tf.nn.relu(tf.add(tf.matmul(self.layer_2, w3), b3)) self.layer_4 = tf.nn.relu(tf.add(tf.matmul(self.layer_3, w4), b4)) self.layer_5 = tf.nn.relu(tf.add(tf.matmul(self.layer_4, w5), b5)) # 输出层:回归任务用线性激活,不需要softmax self.lastLayer = tf.add(tf.matmul(self.layer_5, w_last), b_last) # 4. 损失函数替换为均方误差(适配回归任务) self.loss_op = tf.reduce_mean(tf.square(self.lastLayer - self.Y)) self.optimizer = tf.train.AdamOptimizer(learning_rate=self.learning_rate) self.train_op = self.optimizer.minimize(self.loss_op) # 会话持久化:避免训练结束后会话关闭无法预测 self.sess = tf.Session() self.sess.run(tf.global_variables_initializer()) def random_batch(self, x, y, batch_size): # 随机批量采样的辅助方法 idx = np.random.choice(len(x), batch_size, replace=False) return x[idx], y[idx] def train(self, epochs=500): for step in range(1, epochs+1): batch_x, batch_y = self.random_batch(self.numpy_input, self.numpy_labels, self.batch_size) _, loss = self.sess.run([self.train_op, self.loss_op], feed_dict={self.X: batch_x, self.Y: batch_y}) # 每100步打印损失,监控训练进度 if step % 100 == 0: print(f"Step {step}, 当前损失: {loss:.4f}") def predict(self, test_input): # 实现预测逻辑:输入测试数据,返回[N,2]的坐标预测结果 prediction = self.sess.run(self.lastLayer, feed_dict={self.X: test_input}) return prediction # ------------------- 测试用例 ------------------- if __name__ == "__main__": # 模拟你的输入和标签数据 train_input = np.array([[50,35,21],[40,36,25],[20,5,-5],[35,28,18],[45,32,22]]) train_labels = np.array([[10,2], [10,2], [4,0], [8,3], [11,1]]) # 初始化网络并训练 model = Network(train_input, train_labels) model.train(epochs=500) # 测试预测 test_input = np.array([[42,30,19], [22,8,-3]]) predictions = model.predict(test_input) # 打印结果 for i in range(len(predictions)): print(f"测试输入: {test_input[i]}, 预测坐标: ({predictions[i][0]:.2f}, {predictions[i][1]:.2f})")
关键修改说明
- 参数初始化修正:用
tf.Variable定义可训练的权重和偏置,这是TensorFlow构建可训练模型的标准方式,原来的写法会导致参数无法被优化。 - 损失函数替换:把分类用的交叉熵损失换成回归任务的均方误差,因为坐标是连续值,分类损失完全不适用。
- 输出层调整:回归任务不需要激活函数,直接输出原始计算结果即可。
- 会话管理优化:把会话创建移到
__init__中,避免训练结束后会话关闭导致无法预测。 - Predict方法实现:通过
sess.run(self.lastLayer, feed_dict={self.X: test_input})获取预测结果,返回的是[N,2]数组,每个元素对应x、y坐标。
额外建议
- 数据量要足够:当前示例数据太少,实际训练需要更多样本才能让模型学到信号强度和坐标的映射关系。
- 数据预处理:建议对输入的信号强度做归一化(比如缩放到0-1区间),能大幅提升模型收敛速度。
- 网络结构调优:可以尝试调整隐藏层数量、神经元个数,或者更换激活函数(比如LeakyReLU)来优化性能。
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

