特征缩放后测试集部分列变为NaN 无缺失值时的问题如何解决
问题根因
- 直接触发NaN的原因是测试集部分特征列的标准差为0:如果测试集某一列所有元素取值完全相同,计算得到的标准差为0,除以0会直接输出NaN。你尝试的
nanmean、nanstd仅能处理计算源数据中存在NaN的场景,对除零导致的NaN没有效果。 - 归一化逻辑存在根本性错误:特征标准化的正确规则是仅在训练集上计算所有特征的均值、标准差,测试集必须直接复用训练集的统计参数做缩放,不能单独对测试集重新计算均值、标准差,否则既会产生数据泄露问题,也会放大测试集单特征方差为0的异常。
- 代码逻辑存在隐藏缺陷:你当前使用的
np.mean、np.nanstd没有指定axis=0参数,若输入的X是「样本数×特征数」的二维数组,代码会计算整个数组的全局均值、全局标准差,而非按每个特征单独计算统计量,和函数注释描述的功能不符。
修复方案
步骤1:修复除零问题
计算标准差时添加极小值偏移1e-8,该值足够小不会影响归一化结果,同时可以避免除零错误。
步骤2:修正归一化使用流程
拆分训练集、测试集的处理逻辑,测试集直接复用训练集计算得到的均值和标准差,不单独计算自身的统计量。
步骤3:补全axis参数
给均值、标准差的计算指定axis=0,保证按列(每个特征单独)计算统计量,符合特征归一化的常规需求。
修正后代码
import numpy as np def featureNormalize(X, mu=None, sigma=None): ''' 输入特征矩阵,返回归一化后的值、每个特征的均值、标准差 测试集处理时可直接传入训练集得到的mu和sigma,避免重复计算 ''' # 训练集场景:从当前数据计算统计量 if mu is None: mu = np.nanmean(X, axis=0, dtype = 'float32') if sigma is None: # 加极小值避免除以0 sigma = np.nanstd(X, axis=0, dtype = 'float32') + 1e-8 X_norm = (X - mu) / sigma return X_norm, mu, sigma
正确调用方式
# 训练集处理:计算得到训练集的均值和标准差 X_train_norm, train_mu, train_sigma = featureNormalize(X_train) # 测试集处理:直接复用训练集的统计参数 X_test_norm, _, _ = featureNormalize(X_test, mu=train_mu, sigma=train_sigma)
内容的提问来源于stack exchange,提问作者Krutch Dd
相关产品推荐
相关产品推荐

