TensorFlow.js训练太阳能发电量预测模型的维度错误问题
问题:TensorFlow.js线性模型预测太阳能发电量维度匹配错误
场景说明
需要搭建TensorFlow.js模型,基于单日逐小时云量占比、温度数据,预测当日逐小时太阳能发电量。
现有数据集
现有3组共2天的实测数据,所有数组子数组长度均为24,对应01:00起每小时的采样值:
- 发电量(单位:kWh)
- 云量占比
- 温度
const production = [["0.00","0.00","0.00","0.00","0.00","0.03","0.20","0.42","0.85","1.51","1.58","1.46","1.68","1.68","0.51","0.24","0.14","0.05","0.00","0.00","0.00","0.00","0.00","0.00"],["0.00","0.00","0.00","0.00","0.00","0.01","0.12","0.29","0.81","1.42","1.62","2.09","2.26","1.77","0.44","0.20","0.11","0.04","0.00","0.00","0.00","0.00","0.00","0.00"]] const clouds = [["0.90","0.90","0.90","0.90","0.80","0.75","0.75","0.75","0.72","0.27","0.34","0.58","0.35","0.20","0.20","0.20","0.20","0.17","0.20","0.20","0.20","0.20","0.20","0.01"],["0.74","0.20","0.22","0.39","0.79","0.75","0.75","0.75","0.50","0.40","0.40","0.40","0.40","0.40","0.26","0.30","0.20","0.20","0.20","0.33","0.77","0.90","0.90","0.90"]] const temp = [["15.50","15.22","14.65","14.35","13.84","14.46","15.97","17.08","18.30","19.51","20.39","21.00","21.60","21.94","21.94","21.63","20.89","19.32","17.58","16.40","15.63","14.86","14.16","13.64"],["14.98","14.97","14.89","14.51","14.47","15.14","15.83","16.69","17.89","19.10","20.06","20.84","21.46","21.91","21.58","20.99","19.75","18.06","16.75","15.74","15.49","15.26","15.29","15.45"]]
预期模型逻辑
场景符合线性关系,参考公式:[production] = a + b*[clouds] + c*[temp],输入某日24小时的云量、温度数组,输出对应24小时的发电量数组。
当前问题
代码运行报错,报错信息为输入张量数量和模型预期不匹配,推测是张量维度设置错误。
现有代码
模型类代码
import * as tf from '@tensorflow/tfjs'; /** * 线性模型类 */ export default class LinearModel { /** * 训练模型 */ async trainModel(temp, clouds, production){ const layers = tf.layers.dense({ units: 24, // 输出空间维度 inputShape: [24], // 单参数输入 }); const lossAndOptimizer = { loss: 'meanSquaredError', optimizer: 'sgd', // 随机梯度下降 }; this.linearModel = tf.sequential(); this.linearModel.add(layers); // 添加层 this.linearModel.compile(lossAndOptimizer); // 开始模型训练 await this.linearModel.fit( [tf.tensor2d(temp), tf.tensor2d(clouds)], tf.tensor2d(production), ); } }
调用代码
const model = new LinearModel() await model.trainModel(temp, clouds, production)
报错日志
ValueError: Error when checking model input: the Array of Tensors that you are passing to your model is not the size the model expected. Expected to see 1 Tensor(s), but instead got the following list of Tensor(s): Tensor [['13.14', '12.70', '12.09', ..., '16.22', '16.11', '15.96'], ['15.82', '15.84', '15.73', ..., '15.34', '14.31', '13.30'], 其余日志省略
解决思路
核心错误原因
你使用的tf.sequential()是顺序模型,仅支持单输入单输出结构,但你在fit方法中传入了温度、云量两个输入张量,和模型预期的1个输入不匹配,因此直接报错。
调整方案
1. 输入数据合并
不要分开传入温度和云量两个张量,先把每个样本(单天)的温度、云量数据拼接成一个特征向量:每个单天样本原本有2个长度为24的特征数组,拼接后变成1个长度为48的特征数组,最终训练集的张量维度为[样本数, 48],你的样本量为2,对应维度[2,48]。
2. 模型输入维度调整
把全连接层的inputShape参数改为[48],对应拼接后的单特征向量长度。
3. 数据类型转换
你现有数据集的所有值都是字符串格式,转张量前需要先转换为数值类型,否则模型训练会出错。
修改后核心代码示例
async trainModel(temp, clouds, production){ // 1. 字符串转数值 const tempNum = temp.map(day => day.map(val => Number(val))) const cloudsNum = clouds.map(day => day.map(val => Number(val))) const productionNum = production.map(day => day.map(val => Number(val))) // 2. 拼接每个样本的温度、云量特征 const inputFeatures = tempNum.map((dayTemp, idx) => { return [...dayTemp, ...cloudsNum[idx]] }) const layers = tf.layers.dense({ units: 24, inputShape: [48], // 匹配拼接后24+24的特征长度 }); const lossAndOptimizer = { loss: 'meanSquaredError', optimizer: tf.train.sgd(0.001), // 建议调低学习率避免不收敛 }; this.linearModel = tf.sequential(); this.linearModel.add(layers); this.linearModel.compile(lossAndOptimizer); // 3. 传入合并后的单输入张量 await this.linearModel.fit( tf.tensor2d(inputFeatures), tf.tensor2d(productionNum), { epochs: 100 } // 增加训练轮次,默认1轮训练效果极差 ); }
预测阶段处理
后续预测时,需要把待预测日的24小时温度、24小时云量拼接成长度为48的数组,转成形状为[1,48]的张量输入模型,输出即为长度为24的逐小时发电量数组。
内容的提问来源于stack exchange,提问作者Hans Cornelis
相关产品推荐
相关产品推荐

