向量压缩方法全解析:从线性插值到小波压缩
目录
一、线性插值压缩(Linear Interpolation Compression)
二、对数线性插值压缩(Log-linear Interpolation Compression)
三、等间距采样(Uniform Sampling)
四、等比例采样(Value-Based Sampling)
五、三次样条插值 + 重采样(Cubic Spline Interpolation + Resampling)
六、主成分分析(PCA)
七、小波压缩(Wavelet Compression)
总结对比表
在信号处理、数据压缩与嵌入式系统中,常常面临这样一个问题:如何将一个长度很长的向量压缩成较短的形式?我们希望压缩后的向量仍然能够代表原始数据的主要特征,同时减少存储和计算成本。本文将系统讲解六种常见的向量压缩方法,包括其原理、适用场景、详细数学解释和完整的 C++ 实现。
一、线性插值压缩(Linear Interpolation Compression)
原理解释
将原始向量在索引维度上等间距采样。如果压缩目标是长度为 mm,而原始向量长度为 nn,则采样点位置为:
对应位置上的值通过线性插值得到:
其中 。
C++ 实现
std::vector<double> linearCompress(const std::vector<double>& vec, int targetLen) {std::vector<double> result;int originalLen = vec.size();for (int i = 0; i < targetLen; ++i) {double pos = i * (originalLen - 1.0) / (targetLen - 1.0);int left = (int)std::floor(pos);int right = std::min(left + 1, originalLen - 1);double t = pos - left;double val = (1 - t) * vec[left] + t * vec[right];result.push_back(val);}return result;
}
二、对数线性插值压缩(Log-linear Interpolation Compression)
原理解释
当向量数据以指数增长时,在对数尺度上均匀采样能更好地保留信息结构。我们将索引映射到 空间后再进行插值。
设原始索引 ,转换后变为:
然后等间距地选取对数空间的 mm 个采样点,再进行线性插值。
C++ 实现
std::vector<double> logLinearCompress(const std::vector<double>& vec, int targetLen) {std::vector<double> result;int n = vec.size();std::vector<double> logX(n);for (int i = 0; i < n; ++i)logX[i] = std::log(i + 1);double minLog = logX.front();double maxLog = logX.back();for (int i = 0; i < targetLen; ++i) {double x = minLog + i * (maxLog - minLog) / (targetLen - 1);int j = 0;while (j < n - 1 && logX[j + 1] < x) ++j;int k = std::min(j + 1, n - 1);double t = (x - logX[j]) / (logX[k] - logX[j]);double val = (1 - t) * vec[j] + t * vec[k];result.push_back(val);}return result;
}
三、等间距采样(Uniform Sampling)
原理解释
直接在索引空间取等距离下标并提取对应值:
C++ 实现
std::vector<double> uniformSampling(const std::vector<double>& vec, int targetLen) {std::vector<double> result;int n = vec.size();for (int i = 0; i < targetLen; ++i) {int idx = i * n / targetLen;idx = std::min(idx, n - 1);result.push_back(vec[idx]);}return result;
}
四、等比例采样(Value-Based Sampling)
原理解释
根据原始向量值的最小值与最大值计算等比采样位置。设 ,则目标值:
然后使用最近邻或插值查找对应的原始向量值。
C++ 实现
std::vector<double> valueBasedSampling(const std::vector<double>& vec, int targetLen) {std::vector<double> result;double minV = *std::min_element(vec.begin(), vec.end());double maxV = *std::max_element(vec.begin(), vec.end());for (int i = 0; i < targetLen; ++i) {double r = (double)i / (targetLen - 1);double val = minV * std::pow(maxV / minV, r);auto it = std::lower_bound(vec.begin(), vec.end(), val);if (it == vec.end()) result.push_back(vec.back());else result.push_back(*it);}return result;
}
五、三次样条插值 + 重采样(Cubic Spline Interpolation + Resampling)
原理解释
构造原始向量的样条函数 S(x),再在目标等间距点上进行评估:
实现建议
使用现成 C++ 插值库(如 eigen
, alglib
, spline.h
)来生成样条函数并进行插值。这一部分我会单独开一篇文章来详述。
六、主成分分析(PCA)
原理解释
若你有多个高维向量样本,将其构成矩阵 X∈RN×DX \in \mathbb{R}^{N \times D},则:
-
对每一列做中心化(减去均值)
-
计算协方差矩阵
-
进行特征值分解,取前 k 个最大特征值对应的特征向量构成矩阵
-
降维
实现建议
可使用 Eigen C++ 或调用 Python sklearn.decomposition.PCA
实现。这一部分我会单独开一篇文章来详述。
七、小波压缩(Wavelet Compression)
原理解释
将向量用离散小波变换(DWT)分解为频域系数,再保留低频主成分系数(如 Daubechies、Haar 小波)重构信号。
实现建议
使用如 libwavelet
, pywt
等库进行 DWT 变换与压缩。
总结对比表
方法 | 插值 | 支持单向量 | 数学复杂度 | 优点 | 缺点 |
---|---|---|---|---|---|
线性插值 | ✅ | ✅ | 低 | 快速通用 | 无法建模曲线 |
对数插值 | ✅ | ✅ | 中 | 保留指数结构 | 敏感于开头数据稀疏 |
等间距采样 | ❌ | ✅ | 低 | 简单暴力 | 丢失关键信息 |
等比例采样 | ❌ | ✅ | 中 | 适应幅度变化 | 精度低,需排序 |
样条插值 | ✅ | ✅ | 高 | 平滑逼近 | 实现较复杂 |
PCA | ❌ | ❌ | 高 | 数学最优压缩 | 仅支持多样本 |
小波压缩 | ❌ | ✅ | 高 | 去噪效果好 | 实现依赖库 |
如果你面对的是:
-
单调上升数据:试试 log-linear 或 value-based
-
多个向量降维压缩:用 PCA
-
曲线平滑近似:用三次样条
-
噪声信号压缩:推荐小波压缩
你可以根据目标应用场景和压缩精度需求,灵活组合这些方法。
后续我们将进一步分析这些方法的误差分析、压缩率与重建效果。欢迎收藏、点赞、转发本博客,让更多朋友掌握高质量的数据压缩方法!