使用Accord.NET构建波士顿房价回归神经网络的技术咨询
波士顿房价回归问题Accord.NET代码答疑
问题概述
我是一名新手学生,想要尝试构建神经网络解决波士顿房价(Boston Housing)数据集的回归问题,但对Accord.NET中适用的函数及网络设置不太理解。以下是我编写的代码,请帮忙检查数据预处理、训练数据提交是否正确,以及应该选择何种激活函数?
我希望得到medv的预测值。目前代码中似乎所有层(包括输出层)都使用了LinearFunction,在Python的Keras中可以为每层设置不同的激活函数,请问在Accord.NET中该如何实现?
抱歉,我的代码还很粗糙,我刚开始学习...
用户提供的代码:
System.Globalization.CultureInfo customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone(); customCulture.NumberFormat.NumberDecimalSeparator = "."; System.Threading.Thread.CurrentThread.CurrentCulture = customCulture; string Boston_FileName = @"Boston.csv"; DataTable tab = new CsvReader(Boston_FileName, true).ToTable(); medv = tab.Columns["medv"].ToArray(); medv_train = medv.Get(0, 404);//80% medv_test = medv.Get(404, 506);//20% double[][] out_medv = medv.ToJagged(); double[][] out_medv_train = medv_train.ToJagged(); double[][] out_medv_test = medv_test.ToJagged(); tab.Columns.Remove("medv"); int signs = tab.Columns.Count; double[][] in_x = tab.ToJagged(); double[][] in_train = in_x.Get(0, 404); //80% double[][] in_test = in_x.Get(404, 506);//20% to_standart( in_train, in_test); ActivationNetwork netw = new ActivationNetwork( new LinearFunction(), 13, 13, 1); netw.Randomize(); var teacher = new BackPropagationLearning(netw); for (int epoch = 0; epoch < 100; epoch++) { var error = teacher.RunEpoch(in_train, out_medv_train); WriteLine($"Эпоха {epoch} ошибка {error}"); } int count= 0, correct= 0; for (int i = 0; i < in_test.Length; i++) { var prediction = netw.Compute(in_test[i]); double outputResult = prediction.First(); WriteLine($" {outputResult}"); } ReadLine();
一、数据预处理与训练数据拆分检查
- 拆分逻辑正确性:波士顿数据集共506条样本,按80%/20%拆分训练集(404条)和测试集(102条)的比例合理,代码中
Get(0,404)和Get(404,506)的调用符合预期。 - 标准化操作注意点:
to_standart函数必须仅基于训练集的均值和标准差转换测试集,避免数据泄露。如果你的函数是用训练集统计量统一处理两组数据,逻辑正确;如果是分别计算两组数据的统计量,需要修改。 - 目标变量处理:回归问题中目标变量
medv无需分类编码,直接转为二维数组的操作符合Accord.NET的输入要求,是正确的。
二、训练代码的问题修正
- 学习率与动量设置:
BackPropagationLearning默认学习率偏低,建议手动配置加速收敛:var teacher = new BackPropagationLearning(netw) { LearningRate = 0.01, Momentum = 0.9 // 添加动量缓解震荡,加速收敛 }; - 迭代次数调整:100次迭代不足以让神经网络充分学习,建议增加到1000次以上,或添加早停机制(当连续多轮训练误差下降阈值低于设定值时停止)。
- 测试集误差评估:当前仅输出训练误差,建议添加测试集均方误差(MSE)计算,直观评估模型泛化能力:
// 计算测试集MSE double testMse = 0; for (int i = 0; i < in_test.Length; i++) { var prediction = netw.Compute(in_test[i]); testMse += Math.Pow(prediction[0] - out_medv_test[i][0], 2); } testMse /= in_test.Length; WriteLine($"测试集均方误差: {testMse:F4}");
三、激活函数选择与分层设置
1. 激活函数选择建议
- 隐藏层:回归问题的隐藏层需要非线性激活函数来学习复杂特征映射,推荐选择:
RectifierFunction()(ReLU):输出范围(0,+∞),缓解梯度消失问题,收敛速度快TanHFunction():输出范围(-1,1),梯度消失问题比Sigmoid轻微SigmoidFunction():输出范围(0,1),适合已归一化的数据场景
- 输出层:回归问题需要预测连续值,输出层必须用
LinearFunction,你当前的设置是正确的。
2. Accord.NET分层设置不同激活函数
ActivationNetwork默认给所有层用同一个激活函数,要实现分层设置,需手动创建ActivationLayer并添加到网络中,示例如下:
// 手动构建网络,支持分层配置激活函数 var netw = new ActivationNetwork(inputCount: 13); // 添加隐藏层:13个神经元,使用ReLU激活 netw.Layers.Add(new ActivationLayer(13, new RectifierFunction())); // 可选:添加第二层隐藏层,比如10个神经元用Tanh激活 // netw.Layers.Add(new ActivationLayer(10, new TanHFunction())); // 添加输出层:1个神经元,使用线性激活 netw.Layers.Add(new ActivationLayer(1, new LinearFunction())); // 初始化网络权重 netw.Randomize();
四、其他优化建议
- 权重初始化优化:替换默认的
Randomize(),使用高斯初始化让初始权重更合理:new GaussianWeightsInitializer().Initialize(netw); - 训练集洗牌:训练前打乱训练集样本顺序,避免模型学习到样本顺序的无关规律:
// 同时打乱输入和目标变量,保证对应关系 in_train.Shuffle(out_medv_train);
内容的提问来源于stack exchange,提问作者Urka Serem
相关产品推荐
相关产品推荐

