机器学习特征预处理之标准化/归一化

发布时间:2026/7/20 13:25:35
机器学习特征预处理之标准化/归一化 示例核心逻辑支持4种缩放方法z-score标准化、最小-最大归一化、鲁棒缩放、最大绝对值缩放训练-测试分离在训练集上拟合参数然后用相同参数转换测试集避免数据泄露指定列处理只对num_cols指定的数值列进行转换import pandas as pd from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler, MaxAbsScaler def normalize(X_train, X_test, num_cols, methodzscore, copyTrue, return_scalerFalse): 标准化/归一化数值列 Parameters: ----------- X_train, X_test : pd.DataFrame 训练集和测试集 num_cols : list 需要处理的数值列名列表 method : str zscore, minmax, robust, maxabs copy : bool 是否返回副本避免修改原数据 return_scaler : bool 是否返回训练好的scaler对象 Returns: -------- X_train, X_test : pd.DataFrame 处理后的数据 scaler : object (optional) 训练好的scaler # 参数验证 if not isinstance(X_train, pd.DataFrame) or not isinstance(X_test, pd.DataFrame): raise TypeError(X_train and X_test must be pandas DataFrames) valid_methods {zscore, minmax, robust, maxabs} if method not in valid_methods: raise ValueError(fmethod must be one of {valid_methods}, got {method}) if not num_cols: return (X_train.copy(), X_test.copy()) if copy else (X_train, X_test) # 列存在性验证 missing_cols set(num_cols) - set(X_train.columns) if missing_cols: raise ValueError(fMissing columns in training data: {missing_cols}) # 拷贝数据 if copy: X_train X_train.copy() X_test X_test.copy() # 选择scaler scaler_map { zscore: StandardScaler(), minmax: MinMaxScaler(), robust: RobustScaler(), maxabs: MaxAbsScaler() } scaler scaler_map[method] # 检查缺失值 if X_train[num_cols].isnull().any().any(): print(Warning: Missing values detected in training data.) # 拟合并转换 X_train[num_cols] scaler.fit_transform(X_train[num_cols]) X_test[num_cols] scaler.transform(X_test[num_cols]) if return_scaler: return X_train, X_test, scaler return X_train, X_test调用示例import pandas as pd import numpy as np from sklearn.model_selection import train_test_split # 创建示例数据集 np.random.seed(42) data pd.DataFrame({ age: np.random.randint(18, 65, 100), salary: np.random.randint(30000, 150000, 100), experience: np.random.randint(0, 40, 100), score: np.random.uniform(60, 100, 100), city: np.random.choice([北京, 上海, 深圳], 100), # 分类变量 target: np.random.randint(0, 2, 100) }) # 划分训练集和测试集 X data.drop(target, axis1) y data[target] X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42 ) print(训练集形状:, X_train.shape) print(测试集形状:, X_test.shape) print(\n原始数据预览:) print(X_train.head()) # 定义需要标准化的数值列 num_cols [age, salary, experience, score] # 调用函数 X_train_norm, X_test_norm normalize(X_train, X_test, num_cols, methodzscore) print(Z-score标准化后:) print(X_train_norm.head()) print(f\n均值: {X_train_norm[age].mean():.2f}) # 应接近0 print(f标准差: {X_train_norm[age].std():.2f}) # 应接近1四种缩放方式对比1. Z-score标准化 (StandardScaler)数学原理zx−μσzσx−μ​其中 μμ 是均值σσ 是标准差特点输出范围理论上无界通常约在 [-3, 3] 之间中心化均值为0标准差为1分布形状保持原始分布形状代码示例import numpy as np import pandas as pd from sklearn.preprocessing import StandardScaler # 示例数据 data np.array([10, 20, 30, 40, 50, 1000]).reshape(-1, 1) # 注意有异常值 scaler StandardScaler() scaled scaler.fit_transform(data) print(Z-score标准化结果:) print(f原始: {data.flatten()}) print(f标准化后: {scaled.flatten()}) print(f均值: {scaled.mean():.4f}) # 约等于0 print(f标准差: {scaled.std():.4f}) # 等于1适用场景✅最适合线性模型线性回归、逻辑回归、SVM神经网络避免梯度消失/爆炸K-means聚类、PCA等依赖距离的算法特征量纲差异大时❌不适合数据有较多异常值会被极度放大需要严格限制输出范围时2. 最小-最大归一化 (MinMaxScaler)数学原理xnormx−xminxmax−xminxnorm​xmax​−xmin​x−xmin​​特点输出范围严格在 [0, 1] 之间受异常值影响极大一个异常值可压缩所有正常数据保持相对大小数据间的比例关系保持不变代码示例from sklearn.preprocessing import MinMaxScaler data np.array([10, 20, 30, 40, 50, 1000]).reshape(-1, 1) scaler MinMaxScaler() scaled scaler.fit_transform(data) print(Min-Max归一化结果:) print(f原始: {data.flatten()}) print(f归一化后: {scaled.flatten()}) print(f最小值: {scaled.min():.4f}) # 0 print(f最大值: {scaled.max():.4f}) # 1 # 特殊用法指定范围 [a, b] scaler_range MinMaxScaler(feature_range(-1, 1)) scaled_range scaler_range.fit_transform(data) print(f\n缩放到[-1,1]: {scaled_range.flatten()})适用场景✅最适合图像像素值处理0-255 → 0-1神经网络激活函数如sigmoid需要0-1输入需要边界约束的优化问题特征有明确边界如百分比数据❌不适合数据有明显异常值数据分布不对称会拉伸稀疏区域3. 鲁棒缩放 (RobustScaler)数学原理xrobustx−Q2Q3−Q1xrobust​Q3​−Q1​x−Q2​​其中 Q1Q1​ 是下四分位数25%Q2Q2​ 是中位数50%Q3Q3​ 是上四分位数75%特点使用中位数和IQR对异常值不敏感稳健性极端值影响较小输出范围受数据分布影响无固定边界代码示例from sklearn.preprocessing import RobustScaler # 对比三种方法对异常值的敏感度 data_normal np.array([10, 20, 30, 40, 50]).reshape(-1, 1) data_outlier np.array([10, 20, 30, 40, 50, 1000]).reshape(-1, 1) # 无异常值时的表现 scaler_robust RobustScaler() scaled_normal scaler_robust.fit_transform(data_normal) print(正常数据无异常值:) print(f原始: {data_normal.flatten()}) print(fRobust: {scaled_normal.flatten()}) print(f中位数: {scaled_normal.mean():.4f}) # 有异常值时的表现 scaler_robust2 RobustScaler() scaled_outlier scaler_robust2.fit_transform(data_outlier) print(\n含异常值数据:) print(f原始: {data_outlier.flatten()}) print(fRobust: {scaled_outlier.flatten()}) # 对比Z-score的敏感性 scaler_std StandardScaler() scaled_std scaler_std.fit_transform(data_outlier) print(fZ-score: {scaled_std.flatten()}) print(注意: Z-score中异常值被极大放大!)适用场景✅最适合数据包含明显的异常值财务数据、传感器数据数据分布非正态偏态分布业务指标如收入分布常见长尾分布需要稳健统计的场景❌不适合数据量很小分位数估计不稳定需要严格边界约束的场景4. 最大绝对值缩放 (MaxAbsScaler)数学原理xmaxabsx∣x∣maxxmaxabs​∣x∣max​x​其中 ∣x∣max∣x∣max​ 是最大绝对值特点保持正负号保留数据的符号信息输出范围[-1, 1] 之间稀疏性保持不破坏稀疏数据结构0值保持为0对称处理正负值对称缩放代码示例from sklearn.preprocessing import MaxAbsScaler # 包含正负值的数据 data np.array([-100, -50, 0, 25, 50, 200]).reshape(-1, 1) scaler MaxAbsScaler() scaled scaler.fit_transform(data) print(MaxAbs缩放结果:) print(f原始: {data.flatten()}) print(f缩放后: {scaled.flatten()}) print(f最大绝对值: {scaler.max_abs_}) # 200 print(f范围: [{scaled.min():.2f}, {scaled.max():.2f}]) # 稀疏矩阵示例 from scipy.sparse import csr_matrix sparse_data csr_matrix([[0, 0, 5], [0, 3, 0], [0, 0, 0]]) scaler_sparse MaxAbsScaler() sparse_scaled scaler_sparse.fit_transform(sparse_data) print(\n稀疏矩阵处理:) print(f原始非零值: [5, 3]) print(f缩放后非零值: {sparse_scaled.data}) print(注意: 0值保持为0适合稀疏数据)适用场景✅最适合稀疏数据文本向量、One-Hot编码已经有中心化的数据需要保持0值不变需要保持符号信息❌不适合数据不对称正负值分布不均有极端异常值