matlab数据归一化(补充)

原址:http://www.matlabsky.com/forum.php?mod=viewthread&tid=9468

Yaksa版主对MATLAB中的归一化问题进行了详细的讲解和分析,下面我们对这议题进一步深入。再议归一化问题


[train_scale,test_scale,ps] = scaleForSVM(train_data,test_data,ymin,ymax)

输入:
train_data:训练集
test_data:测试集
ymin:归一化范围下限(可不输入,默认为0)
ymax:归一化范围上限(可不输入,默认为1)

输出:
train_scale:归一化后的训练集
test_scale:归一化后的测试集
ps:归一化映射

测试代码:
train_data = [1 12;3 4;7 8]
test_data = [9 10;6 2]

[train_scale,test_scale,ps] = scaleForSVM(train_data,test_data,0,1)
运行结果:
  1. train_data =
  2.      1    12
  3.      3     4
  4.      7     8
  5. test_data =
  6.      9    10
  7.      6     2
  8. train_scale =
  9.          0    1.0000
  10.     0.2500    0.2000
  11.     0.7500    0.6000
  12. test_scale =
  13.     1.0000    0.8000
  14.     0.6250         0
  15. ps =
  16.       name: 'mapminmax'
  17.      xrows: 2
  18.       xmax: [2x1 double]
  19.       xmin: [2x1 double]
  20.     xrange: [2x1 double]
  21.      yrows: 2
  22.       ymax: 1
  23.       ymin: 0
  24. yrange: 1
复制代码
说明:归一化并不是必须采用的预处理方法。 但一旦采用了,这个步骤就十分重要,因为这是使用SVM的第一步骤,原始数据从这里将会被变化,若处理不当会使后面的分类或回归效果不佳。 原始数据到底该怎么进行归一化,我想到的是以下的几个问题:
(1)是对每一个样本进行进行归一化(按行归一化)还是对每一个维度进行归一化(按列归一化)?
(2)是将训练集和测试集分别归一化还是放在一起形成一个大矩阵一起进行归一化?


对于上面的我个人的理解和给出的解决办法是:
(1)对每一个维度进行归一化
理由:对于每个样本,由于它的每一个维度的量纲不同,若对每一个样本进行归一化且在量纲数量级差别悬殊时会使样本中较低数量级的属性变为0,会使原始信息过多丧失。比如:
  1. sample =
  2.     1    2    0.5    100000
  3.     5    7    0.4    200000
复制代码
若按行对每一个样本进行[0,1]归一化(按行归一化),则结果为:
  1. sample_scale =
  2.     0.0000    0.0000         0    1.0000
  3.     0.0000    0.0000         0    1.0000
复制代码
你会看到由于数量级的差别,对于每一样本的前三维的数据都被归一化为0,这样其实是不合理,会使原始数据的信息过多丢失。但若采用对每一维度进行归一化,就不会大范围发生这种情况,因为对于同一维度,量纲级别是相同的。对每一维度进行[0,1]归一化(按列归一化),结果为:
  1. sample_scale =
  2.      0     0     1     0
  3.      1     1     0     1
复制代码
(2)将训练集和测试集放在一起,一起进行归一化。

用测试代码中的例子
  1. train_data =
  2.      1    12
  3.      3     4
  4.      7     8
  5. test_data =
  6.      9    10
  7.      6     2
复制代码
若先将训练集进行归一化(按每一维度进行),然后把这个归一化映射记录下来,当有测试集时再用这个归一化映射对测试集进行归一化,对训练集进行归一化时对于第一维度归一化映射记录的最大值是7,这就接受一个假设是所有数据的第一维度的最大值不能超过7,但我们看到新的测试集拿来的时候它的第一维度的值不一定非得小于7,测试数据中的测试集的第一维度的最大值为9>7。即若分别归一化会产生这种不合理的现象。将训练集和测试集放在一起归一化就可以避免这种情况,统一归一化时每一维度的最大值和最小值是从训练集和测试集中寻找。

关于这个问题,我和论坛的一些朋友曾一起详细讨论过,有的朋友说这样做不合理,因为这样做的话测试集间接参与的SVM模型的建立,他们的意思是SVM的整体思路是用训练集建立SVM模型,然后用这个模型来预测测试集;或者说得更明白一点就是用训练集建立一个固定的SVM模型,然后每来一个测试集,就可以用这个固定SVM模型来进行预测。对此,我个人的给出的解释和理解是,我们处理的问题是面向数据的,当有新的测试集来的时候,若我们能建立一个更加适合这个测试集的SVM模型来预测,这样岂不是更好,即将原始训练集和新来的测试集放在一起统一归一化,这样得到的SVM模型更加适合当前的测试集,当又有新的测试集来的时候,我们再将这个新的测试集和原始的训练集放在重新归一化,再进行后续的SVM步骤,建立SVM模型。

以上归一化问题是见仁见智的,您可以保留自己的意见,以上是我个人的见解,事实证明将训练集和测试集放在一起归一化的效果绝对要比分别归一化的效果要好很多。您可以自行验证测试,用事实说话。
<think>好的,用户的问题是关于光谱数据归一化和平滑处理的方法或工具。首先我需要理解用户的需求。他们可能是在进行近红外光谱分析,比如在化学、材料科学或者生物医学领域,需要预处理数据以提高后续建模的准确性。用户提到了归一化和平滑处理,这两个都是常见的数据预处理步骤。 根据系统指令,我需要先回顾相关的引用内容。引用[1]提到近红外光谱处理流程包括数据预处理,比如归一化和波长选择,以及建模。引用[4]详细讨论了归一化的优点和方法,比如Batch Normalization,但光谱数据可能更多使用其他归一化方法,比如标准正态变换(SNV)或多元散射校正(MSC)。这些方法可能在引用中没有直接提到,但结合领域知识,我需要补充这些常见的光谱归一化技术。 平滑处理方面,常用的方法包括Savitzky-Golay滤波、移动平均、小波变换等。这些方法可以帮助减少噪声,提高信噪比。引用[3]提到深度学习在数据处理中的去噪效果,但用户可能更关注传统方法,所以需要分开讨论。 接下来,我需要整理可用的工具或库。Python中的scipy库有Savitzky-Golay滤波的实现,numpy和scikit-learn可以用于归一化处理。R语言中的prospectr包和pls库也常用。商业软件如MATLAB的PLS Toolbox和OPUS可能更用户友好,适合非编程人员。 用户可能需要具体的代码示例,比如使用Python的SNV归一化和Savitzky-Golay平滑。同时,要注意引用相关的内容,比如引用[4]关于归一化的优点,可以指出归一化如何减少内部协变量偏移,提升模型性能。 需要确保回答结构清晰,分步骤介绍方法和工具,提供代码示例,并列出相关问题。还要检查是否所有数学表达式用了正确的LaTeX格式,比如$公式$,独立公式用$$...$$。 最后,生成相关问题,帮助用户深入探索,比如不同归一化方法的比较或处理后的效果评估。确保回答真实可靠,参考了现有文献和常用工具,同时结合用户提供的引用内容。</think>### 光谱数据处理方法及工具 #### 一、归一化方法 1. **标准正态变换(SNV)** 通过每个样本的均值和标准差进行标准化: $$ x_{norm} = \frac{x - \mu}{\sigma} $$ 适用于消除光散射和基线漂移[^1]。 2. **多元散射校正(MSC)** 利用参考光谱(通常为平均光谱)修正样本间的散射差异,公式为: $$ x_{msc} = \frac{x - a}{b} $$ 其中$a$和$b$通过线性回归计算。 3. **最大-最小值归一化** 将光谱数据缩放到$[0,1]$区间: $$ x_{norm} = \frac{x - x_{min}}{x_{max} - x_{min}} $$ 适用于消除量纲差异[^4]。 4. **矢量归一化(Vector Normalization)** 对光谱向量进行L2范数归一化: $$ x_{norm} = \frac{x}{\|x\|_2} $$ --- #### 二、平滑方法 1. **Savitzky-Golay滤波** 基于局部多项式拟合的光滑方法,可同时计算导数。Python实现: ```python from scipy.signal import savgol_filter smoothed = savgol_filter(spectrum, window_length=11, polyorder=2) ``` 2. **移动平均法** 通过滑动窗口计算均值: $$ y_i = \frac{1}{2k+1}\sum_{j=-k}^{k} x_{i+j} $$ 简单但可能导致峰形展宽。 3. **小波去噪** 使用离散小波变换(如symlet小波)分解信号后阈值处理: ```python import pywt coeffs = pywt.wavedec(spectrum, 'sym5', level=3) threshold = np.std(coeffs[-3]) * np.sqrt(2*np.log(len(spectrum))) coeffs[1:] = [pywt.threshold(c, threshold) for c in coeffs[1:]] reconstructed = pywt.waverec(coeffs, 'sym5') ``` --- #### 三、工具与库推荐 | 工具类型 | 推荐方案 | 特点说明 | |----------------|-----------------------------------|-----------------------------------| | **Python库** | `scipy.signal`(平滑) | 包含Savitzky-Golay等经典算法 | | | `sklearn.preprocessing`(归一化)| 提供MinMaxScaler等标准化类 | | **R语言包** | `prospectr`包 | 专为光谱设计的MSC、SNV等功能 | | | `pls`库 | 包含光谱预处理与建模一体化工具 | | **商业软件** | MATLAB PLS Toolbox | 图形化界面,包含OPUS格式支持 | | | OPUS(Bruker) | 仪器配套的专业光谱处理软件 | --- #### 四、完整处理示例(Python) ```python import numpy as np from sklearn.preprocessing import StandardScaler # SNV归一化 def snv(input_data): output = np.zeros_like(input_data) for i in range(input_data.shape[0]): avg = np.mean(input_data[i,:]) std = np.std(input_data[i,:]) output[i,:] = (input_data[i,:] - avg)/std return output # 应用流程 raw_spectra = np.loadtxt('spectra.csv') norm_spectra = snv(raw_spectra) # 自定义SNV smoothed = savgol_filter(norm_spectra, 15, 3) # 窗口15点,3次多项式 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值