数据已归一化但模型损失值极高(14位),如何解决?
房屋价格预测模型高损失与偏差问题解决方案
我有500条房屋数据集,已将所有特征转换为数值型(原CSV包含mainroad、guestroom、furnishingstatus等类别型特征,已通过映射转为0/1或0/1/2的数值),共12个特征用于预测房屋价格。运行模型时出现14位的极高损失值,尽管对数据做了归一化处理但毫无效果,预测结果偏差达百倍。相关代码如下:
import numpy as np from tensorflow.keras.layers import Input, Dense from tensorflow.keras.models import Model import pandas as pd from sklearn.preprocessing import StandardScaler, MinMaxScaler data = pd.read_csv('Housing.csv') valdata = pd.read_csv('val.csv') mapping1 = {'yes': 1, 'no': 0} mapping2 = {'furnished': 2, 'semi-furnished': 1, "unfurnished": 0} cols_to_convert = ['mainroad', 'guestroom', "basement", "hotwaterheating", "airconditioning", "prefarea"] for col in cols_to_convert: data[col] = data[col].map(mapping1) valdata[col] = valdata[col].map(mapping1) data["furnishingstatus"] = data["furnishingstatus"].map(mapping2) valdata["furnishingstatus"] = valdata["furnishingstatus"].map(mapping2) x_train = np.array(data.drop("price", axis=1)) y_train = np.array(data["price"]) scaler = MinMaxScaler() x_train = scaler.fit_transform(x_train) scaler = StandardScaler() x_train = scaler.fit_transform(x_train) input_shape = x_train[0].shape inputs = Input(shape=input_shape) # Define layers dense1 = Dense(8, activation='relu')(inputs) dense2 = Dense(1, activation='linear')(dense1) model = Model(inputs=inputs, outputs=dense2) model.compile(loss='mean_squared_error', optimizer='adam') model.fit(x_train, y_train, epochs=100, validation_split=0.2) x_new = np.array([[7420, 4, 2, 3, 1, 0, 0, 0, 1, 2, 1, 2]]) y_new = model.predict(x_new) print(y_new)
核心问题拆解
- 目标变量未做缩放:房价本身数值量级大(如几十万级),直接用原始值计算MSE会导致损失值爆炸,这是核心原因。
- 特征重复缩放:连续使用
MinMaxScaler和StandardScaler对特征做两次缩放,打乱了特征原有分布,反而干扰模型学习。 - 测试数据未匹配训练集缩放规则:预测时直接输入原始特征值,未用训练集拟合的scaler做转换,输入分布不一致导致预测偏差。
- 模型结构过于简单:仅用8个神经元的单层隐藏层,拟合能力不足,无法捕捉特征与房价的复杂关联。
具体修复步骤
- 对目标变量做标准化处理
用StandardScaler对房价标签进行缩放,训练后再逆转换回原始单位,避免MSE数值过大。 - 移除重复的特征缩放操作
选择一种缩放方式即可,推荐用StandardScaler处理特征,更适配回归任务的分布特性。 - 统一测试数据的缩放规则
预测时必须用训练集拟合好的scaler转换输入特征,保证分布一致性。 - 优化模型结构
增加隐藏层或神经元数量,提升模型拟合能力,比如添加一层16神经元的Dense层。 - 调整训练参数
增加训练轮数,加入EarlyStopping回调函数,防止过拟合同时保证模型充分训练。
完整修正代码
import numpy as np from tensorflow.keras.layers import Input, Dense from tensorflow.keras.models import Model from tensorflow.keras.callbacks import EarlyStopping import pandas as pd from sklearn.preprocessing import StandardScaler # 加载数据 data = pd.read_csv('Housing.csv') valdata = pd.read_csv('val.csv') # 类别特征转数值 mapping1 = {'yes': 1, 'no': 0} mapping2 = {'furnished': 2, 'semi-furnished': 1, "unfurnished": 0} cols_to_convert = ['mainroad', 'guestroom', "basement", "hotwaterheating", "airconditioning", "prefarea"] for col in cols_to_convert: data[col] = data[col].map(mapping1) valdata[col] = valdata[col].map(mapping1) data["furnishingstatus"] = data["furnishingstatus"].map(mapping2) valdata["furnishingstatus"] = valdata["furnishingstatus"].map(mapping2) # 划分特征与目标变量,目标变量转二维数组适配scaler x_train = np.array(data.drop("price", axis=1)) y_train = np.array(data["price"]).reshape(-1, 1) # 特征标准化(仅执行一次) x_scaler = StandardScaler() x_train_scaled = x_scaler.fit_transform(x_train) # 目标变量标准化 y_scaler = StandardScaler() y_train_scaled = y_scaler.fit_transform(y_train) # 构建优化后的模型 input_shape = x_train_scaled[0].shape inputs = Input(shape=input_shape) dense1 = Dense(16, activation='relu')(inputs) dense2 = Dense(8, activation='relu')(dense1) outputs = Dense(1, activation='linear')(dense2) model = Model(inputs=inputs, outputs=outputs) model.compile(loss='mean_squared_error', optimizer='adam') # 加入EarlyStopping防止过拟合 early_stop = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True) # 训练模型 model.fit(x_train_scaled, y_train_scaled, epochs=300, validation_split=0.2, callbacks=[early_stop]) # 测试数据处理:用训练集的scaler转换 x_new = np.array([[7420, 4, 2, 3, 1, 0, 0, 0, 1, 2, 1, 2]]) x_new_scaled = x_scaler.transform(x_new) # 预测并逆转换回原始房价单位 y_new_scaled = model.predict(x_new_scaled) y_new = y_scaler.inverse_transform(y_new_scaled) print("预测房价:", y_new)
验证建议
- 训练过程中观察损失曲线,若验证损失连续多轮不再下降则停止训练,避免过拟合。
- 对比逆转换后的预测值与实际房价,检查偏差是否大幅降低。
- 可尝试调整模型层数、神经元数量或学习率(如
optimizer=Adam(learning_rate=0.001)),进一步优化效果。
内容的提问来源于stack exchange,提问作者user20856357
相关产品推荐
相关产品推荐

