归一化(Normalization)是一种常见的数据预处理方法,用于将数据按比例缩放到某个特定的范围,以便于不同量纲或数量级的数据能够进行比较或综合分析。
将数据线性地缩放到一个指定的区间,通常是 [0, 1] 或 [-1, 1]。
公式如下(以 [0, 1] 为例):
如果要缩放到 [-1, 1],可以使用:
优点:
简单直观 保留原始数据分布形状 缺点:
对异常值敏感(极小值或极大值会影响整体缩放效果)
public static double[] minMaxNormalize(double[] data, double newMin, double newMax) {
double min = Arrays.stream(data).min().getAsDouble();
double max = Arrays.stream(data).max().getAsDouble();
return Arrays.stream(data).map(v -> (v - min) / (max - min) * (newMax - newMin) + newMin).toArray();
}
虽然这不是严格意义上的“归一化”,但常被混用此术语。
公式:
其中,μ 是均值,σ 是标准差。
特点:
数据中心变为 0,标准差为 1 不限制范围在 [-1, 1],但如果数据近似正态分布,大多数值会在这个范围内 优点:
对异常值更鲁棒(相比 Min-Max) 适用于数据分布不均匀或存在极端值的情况
public static double[] zScoreNormalize(double[] data) {
double mean = Arrays.stream(data).average().orElse(0.0);
double std = Math.sqrt(Arrays.stream(data).map(v -> v - mean).map(v -> v * v).sum() / data.length);
return Arrays.stream(data).map(v -> (v - mean) / std).toArray();
}
通过移动小数点位置来进行归一化。
公式:
其中
是使得
的最小幂次。
public static double[] decimalScalingNormalize(double[] data) {
double maxAbsValue = Arrays.stream(data).map(Math::abs).max().getAsDouble();
int j = (int) Math.ceil(Math.log10(maxAbsValue));
return Arrays.stream(data).map(v -> v / Math.pow(10, j)).toArray();
}
假设有一组数据:
原始数据:[10, 20, 30, 40, 50]
我们想把它归一化到 [-1, 1] 范围:
最小值 min = 10 最大值 max = 50
代入公式:
计算结果:
x=10 → x' = -1
x=20 → x' = -0.5
x=30 → x' = 0
x=40 → x' = 0.5
x=50 → x' = 1
import java.util.Arrays;
public class NormalizationExample {
public static double[] normalizeToMinusOneToOne(double[] data) {
if (data == null || data.length == 0) return new double[0];
double min = Arrays.stream(data).min().getAsDouble();
double max = Arrays.stream(data).max().getAsDouble();
double[] normalized = new double[data.length];
for (int i = 0; i < data.length; i++) {
normalized[i] = 2 * (data[i] - min) / (max - min) - 1;
}
return normalized;
}
public static void main(String[] args) {
double[] data = {10, 20, 30, 40, 50};
System.out.println("原始数据: " + Arrays.toString(data));
double[] normalizedData = normalizeToMinusOneToOne(data);
System.out.println("归一化后: " + Arrays.toString(normalizedData));
}
}
在深度学习中,通常要求输入特征在 [-1, 1] 或 [0, 1] 范围内。例如,在卷积神经网络(CNN)处理图像时,像素值一般被归一化为 [0, 1] 或 [-1, 1]。
音频幅度通常被归一化到 [-1, 1],这样便于数字信号处理和避免溢出。
在 3D 游戏引擎中,顶点坐标有时会被归一化到 [-1, 1] 的视口空间,便于渲染。
不同的归一化方法适用于不同类型的数据集和应用场景。例如,如果数据分布接近正态分布,Z-Score标准化可能是更好的选择;而对于有明确上下界的数值,如图像像素值,最小-最大归一化可能更合适。
这些方法都有助于提高模型的性能,减少某些算法对输入规模敏感的问题。在实际应用中,选择合适的归一化方法需要根据具体的数据特征和业务需求来决定。