基于Python的近红外光谱数据预处理与特征筛选——以哈密瓜品质检测为例

基于Python的近红外光谱数据预处理与特征筛选——以哈密瓜品质检测为例

目录

  • 一、引言
  • 二、研究背景
  • 三、数据集
  • 四、预处理算法
    • (1)原始光谱读取
    • (2)趋势校正(Detrending, DT)
    • (3)标准正态变换(Standard Normal Variate, SNV)
    • (4)多元散射校正(Multiplicative Scatter Correction, MSC)
    • (5)卷积平滑(Savitzky-Golay smoothing, SG)
    • (6)一阶导数(First Derivative, FD)
    • (7)光谱预处理结果
  • 五、特征筛选算法
    • (1)竞争自适应重加权(Competitive Adaptive Reweighted Sampling, CARS)
    • (2)无信息变量消除算法(Uninformative Variables Elimination,UVE)
    • (3)协同区间偏最小二乘算法(Synergisticinterval Partial Least Squares, SiPLS)
    • (4)基于最优预处理方法下的特征筛选结果
  • 六、结论

一、引言

在果蔬内部品质无损检测中,近红外光谱技术(Near-Infrared Spectroscopy, NIRS)因其快速、无损和高效的特点,被广泛用于预测水果的可溶性固形物含量(SSC)、干物质及其他理化指标。然而,受采集条件、样品形态及光学噪声影响,原始光谱往往存在基线漂移、散射效应和噪声干扰等问题,导致模型精度下降。
因此,在建模前需要对光谱进行预处理以消除系统误差,并结合特征波段筛选算法提取有效信息,从而提升模型的稳健性和泛化能力。博主将分享1篇发表在《农业工程学报》(EI)的“哈密瓜可溶性固形物便携式光谱检测装置及通用模型”,以哈密瓜近红外光谱数据为例,介绍如何通过Python实现常见的光谱预处理算法与特征筛选方法,帮助读者快速掌握光谱建模的前期数据处理流程。

论文原文:https://doi.org/10.11975/j.issn.1002-6819.202504261.

欢迎大家交流、引用和分享,博文如需转载请注明来源。

二、研究背景

哈密瓜作为新疆代表性优质甜瓜,其可溶性固形物含量(SSC)是衡量品质和商品价值的重要指标。利用近红外漫透射光谱技术对哈密瓜糖度进行无损检测,可实现快速质量分级与现场检测。然而,由于哈密瓜果皮较厚、内部结构复杂,光谱信号容易受到散射效应、基线漂移以及噪声干扰等因素影响,导致原始光谱中存在大量冗余与无效信息。
为提高模型的稳健性与预测精度,建模前通常需要进行光谱预处理与特征波段筛选。常见的预处理算法包括趋势校正(DT)、标准正态变换(SNV)、多元散射校正(MSC)、卷积平滑(SG)及一阶导数(FD)等,用于消除噪声与光散射影响;而在特征筛选阶段,常采用竞争自适应重加权算法(CARS)、无信息变量消除算法(UVE)及协同区间偏最小二乘算法(SiPLS)等方法,以提取与糖度变化最相关的波长区间,从而为后续模型的构建奠定基础。

三、数据集

本研究使用海洋光学公司生产的QE Pro-FL型号光谱仪采集哈密瓜光谱数据。
部分数据集:通过网盘分享的文件:哈密瓜光谱数据.csv和wave.csv文件。
链接: https://pan.baidu.com/s/1wl1vlf5wLzKT_ME_sNAhPQ 提取码: 2vdu

四、预处理算法

在近红外光谱数据建模过程中,原始光谱往往受到光散射、仪器漂移、噪声和样品表面不均匀性等因素的影响,这会导致光谱信号波动大、信噪比低,从而影响后续模型的稳定性和预测精度。因此,在建模前需要对光谱数据进行合理的预处理。常用的预处理有以下几种。

(1)原始光谱读取

# 原始近红外光谱数据读取与可视化import pandas as pd import numpy as np import matplotlib.pyplot as plt # 设置matplotlib中文显示 plt.rcParams['font.sans-serif']=['SimSun']# 使用宋体 plt.rcParams['axes.unicode_minus']=False# 正常显示负号# 读取数据 X = np.loadtxt('D:/桌面/哈密瓜光谱数据.csv', delimiter=',')# 读取原始光谱数据 wave = np.loadtxt('D:/桌面/wave.csv', delimiter=',')# 读取波长信息# 绘制原始光谱曲线 plt.figure(figsize=(8,5))for spectrum in X: plt.plot(wave, spectrum, linewidth=0.8) plt.title('原始光谱曲线') plt.xlabel('波长 Wavelength (nm)') plt.ylabel('光照强度 Intensity') plt.tight_layout() plt.show()

(2)趋势校正(Detrending, DT)

趋势校正通过去除光谱中的低频漂移或基线变化,使光谱曲线的整体趋势平滑化,从而降低基线漂移对建模的干扰。该方法在处理光谱端点漂移或样品厚度变化引起的光谱偏移时尤为有效。

# 趋势校正from scipy.signal import detrend # 定义去趋势函数defdetrending(input_data): detrended_spectra = detrend(input_data, axis=1)return detrended_spectra # 对所有光谱数据进行去趋势处理 x_dentrended = detrending(X) data5 = x_dentrended.T # 绘制去趋势后的光谱曲线 plt.figure() plt.plot(wave, data5, linewidth=0.8) plt.title('经去趋势变换的光谱曲线') plt.ylabel('光照强度Intensity') plt.xlabel('波长 Wavelength/nm') plt.show()

(3)标准正态变换(Standard Normal Variate, SNV)

SNV是对每个样本的光谱进行均值中心化和标准化处理,将样本的均值归零、标准差归一,从而消除因样品散射或粒径差异造成的光谱强度变化。SNV可以显著提高光谱的可比性,使数据更适合建立回归模型。

# 光谱标准正态变换(SNV)defsnv(data):"""标准正态变换(Standard Normal Variate, SNV)""" mean = np.mean(data, axis=1, keepdims=True) std = np.std(data, axis=1, keepdims=True)return(data - mean)/ std # 对光谱数据进行SNV变换 x_snv = snv(X)# 绘制变换后的光谱曲线 plt.figure(figsize=(8,5)) plt.plot(wave, x_snv.T, linewidth=0.8) plt.title('经SNV变换的光谱曲线') plt.xlabel('波长 Wavelength (nm)') plt.ylabel(光照强度 Intensity') plt.tight_layout() plt.show()

(4)多元散射校正(Multiplicative Scatter Correction, MSC)

MSC通过将每个样本光谱与参考光谱(通常为均值光谱)线性拟合,消除光谱中的散射效应和基线偏移。该方法对样品间因厚度或折射率差异引起的光谱散射非常有效,可以提升模型对样品间差异的鲁棒性。

# 多元散射校正(MSC)defmsc(data, reference=None):"""多元散射校正(Multiplicative Scatter Correction, MSC)"""if reference isNone: reference = np.mean(data, axis=0) corrected = np.zeros_like(data)for i inrange(data.shape[0]): slope, intercept = np.polyfit(reference, data[i,:],1) corrected[i,:]=(data[i,:]- intercept)/ slope return corrected # 对光谱数据进行MSC变换 x_msc = msc(X)# 绘制MSC处理后的光谱曲线 plt.figure(figsize=(8,5)) plt.plot(wave, x_msc.T, linewidth=0.8) plt.title('经MSC变换的光谱曲线') plt.xlabel('波长 Wavelength (nm)') plt.ylabel('光照强度 Intensity') plt.tight_layout() plt.show()

(5)卷积平滑(Savitzky-Golay smoothing, SG)

SG平滑通过局部多项式拟合对光谱进行平滑处理,可以有效去除随机噪声,同时保留光谱的峰形信息。该方法常用于高噪声光谱数据的处理,尤其适合在波长密度较高的情况下增强信号的连续性。

# 光谱卷积平滑(Savitzky-Golay, SG)from scipy.signal import savgol_filter defsg(data, window_length=15, polyorder=2):"""Savitzky-Golay卷积平滑""" smoothed = np.zeros_like(data)for i inrange(data.shape[0]): smoothed[i,:]= savgol_filter(data[i,:], window_length, polyorder, mode='nearest')return smoothed # 对光谱数据进行SG平滑 x_sg = sg(X)# 绘制SG平滑后的光谱曲线 plt.figure(figsize=(8,5)) plt.plot(wave, x_sg.T, linewidth=0.8) plt.title('经SG平滑后的光谱曲线') plt.xlabel('波长 Wavelength (nm)') plt.ylabel('光照强度 Intensity') plt.tight_layout() plt.show()

(6)一阶导数(First Derivative, FD)

一阶导数通过对光谱数据求差分,强化光谱中波峰和波谷的信息,削弱光谱基线漂移和散射影响。该方法常用于突出吸收峰位置和形状特征,从而提高建模对特征波段的敏感性。

# 一阶导数(First Derivative, FD)defspectral_derivative(data, order=1):"""计算光谱数据的一阶或二阶导数""" derivative = np.diff(data, n=order, axis=1)# 为保持样本数一致,在末尾补零列 derivative = np.hstack([derivative, np.zeros((derivative.shape[0],1))])return derivative # 对光谱数据进行一阶导数变换 x_1d = spectral_derivative(X, order=1)# 绘制一阶导数光谱曲线 plt.figure(figsize=(8,5)) plt.plot(wave[:-1], x_1d[:,:-1].T, linewidth=0.8) plt.title('经FD变换的光谱曲线') plt.xlabel('波长 Wavelength (nm)') plt.ylabel('光照强度 Intensity') plt.tight_layout() plt.show()

(7)光谱预处理结果

哈密瓜原始光谱及经多种预处理方法后的光谱可视化结果如下图所示。

在这里插入图片描述

五、特征筛选算法

为了减少光谱端点的噪声干扰并增强有效信号的稳定性,对采集的光谱数据进行了波段截取,仅保留500 ~ 1050 nm区域,再对光谱进行预处理,将预处理后的光谱作为分析对象,从而提高特征提取的可靠性。

(1)竞争自适应重加权(Competitive Adaptive Reweighted Sampling, CARS)

CARS通过多次迭代抽样、PLS回归系数权重评估和指数衰减策略,自动选择与目标变量关系最强的波段。该方法能够有效剔除冗余波段,降低数据维度,同时保持预测性能。

from sklearn.cross_decomposition import PLSRegression from sklearn.model_selection import cross_val_score defCARS(X, y, iteration=50, n_comps=8, cv=10, n_features=100, random_state=42):"""竞争自适应重加权抽样算法 (CARS)""" np.random.seed(random_state) N, D = X.shape prob =0.8 a = np.power((D /2),(1/(iteration -1))) k =(np.log(D /2))/(iteration -1) r =[round(a * np.exp(-(k * i))* D)for i inrange(1, iteration +1)] weights = np.zeros(D)for i inrange(iteration): idCal = np.random.choice(N, size=int(prob * N), replace=False) idW = np.random.choice(D, size=r[i], replace=False) pls = PLSRegression(n_components=min(n_comps,len(idW))) pls.fit(X[idCal][:, idW], y[idCal]) abs_coef = np.abs(pls.coef_).ravel() weights[idW]+= abs_coef / np.sum(abs_coef) selected = np.argsort(weights)[-n_features:]return selected X = X_raw y = Y wave = np.array(wave).ravel()# 确保波长为一维数组 n_comps =8 n_features_list =[275,276,277,278,279] best_r2, best_features =-np.inf,Nonefor n_feat in n_features_list: selected_idx = CARS(X, y, iteration=50, n_comps=n_comps, cv=10, n_features=n_feat) X_sel = X[:, selected_idx] pls = PLSRegression(n_components=min(n_comps, n_feat)) r2 = cross_val_score(pls, X_sel, y, cv=10, scoring="r2").mean()print(f"特征数: {n_feat}, 交叉验证R²: {r2:.4f}")if r2 > best_r2: best_r2, best_features = r2, selected_idx # 输出结果 selected_wavelengths = wave[best_features] X_selected = X[:, best_features]print(f"最佳特征数: {len(best_features)}, 最佳R²: {best_r2:.4f}")print("最佳特征波长 (nm):", selected_wavelengths)

(2)无信息变量消除算法(Uninformative Variables Elimination,UVE)

UVE利用PLS模型系数稳定性对光谱波段进行评估,剔除对目标变量贡献小或不稳定的波段。通过减少无信息变量,可以显著提高模型的稳定性和预测精度。

defUVE(X, y, iteration=50, n_comps=8, cv=3):"""无信息变量消除算法 (UVE)""" N, D = X.shape pls = PLSRegression(n_components=n_comps) pls.fit(X, y) original_coefs = np.abs(pls.coef_).ravel() stability_scores = np.zeros(D)for i inrange(D): X_reduced = np.delete(X, i, axis=1) pls_cv = PLSRegression(n_components=n_comps) cv_scores = cross_val_score(pls_cv, X_reduced, y, cv=cv, scoring='neg_mean_squared_error') stability_scores[i]= np.mean(np.abs(cv_scores)) informative_scores = stability_scores * original_coefs threshold = np.median(informative_scores) informative_vars = np.where(informative_scores >= threshold)[0]return informative_vars W_best = UVE(X, Y) selected_wavelengths = wave[W_best] X_selected = X[:, W_best]print("选择的特征波长:", selected_wavelengths)print("提取后的光谱数据形状:", X_selected.shape)

(3)协同区间偏最小二乘算法(Synergisticinterval Partial Least Squares, SiPLS)

SiPLS将光谱划分为多个连续区间,通过交叉验证评估各区间的贡献,选择表现最佳的波段组合进行建模。该方法不仅能够提取高信息量波段,还可以捕捉不同波段间的协同效应,提高模型预测性能。

defSiPLS(X, Y, interval_length=10):""" 协同区间偏最小二乘算法 (SiPLS) :param X: 光谱数据 (样本数 x 波长数) :param Y: 目标变量 :param interval_length: 每个区间的波长长度 :return: 区间评分和每个区间选择的波长索引 """ n_intervals = X.shape[1]// interval_length scores =[] selected_indices =[]for i inrange(n_intervals): start = i * interval_length end = start + interval_length pls = PLSRegression(n_components=2) score =-np.mean(cross_val_score(pls, X[:, start:end], Y, cv=5, scoring='neg_mean_squared_error')) scores.append(score) selected_indices.append(start)# 保存每个区间的起始波长索引return np.array(scores), np.array(selected_indices, dtype=int) scores, W_best = SiPLS(X, Y) selected_wavelengths = wave[W_best] X_selected = X[:, W_best]print("选择的特征波长:", selected_wavelengths)print("提取后的光谱数据形状:", X_selected.shape)

(4)基于最优预处理方法下的特征筛选结果

为了构建高性能的预测模型,我们对原始数据集进行了一系列最优预处理操作。在此基础上,我们采用了竞争自适应重加权、无信息变量消除算法以及协同区间偏最小二乘算法对其进行特征筛选,筛选的特征波段如下图所示。

在这里插入图片描述


通过上述特征筛选算法,可以将多波段光谱数据转化为关键波段子集,降低建模复杂度,同时提升预测的准确性和稳健性。

六、结论

本文以哈密瓜近红外光谱数据为例,详细介绍了常用的光谱数据处理和特征波段选择方法。具体包括光谱预处理算法:趋势校正(DT)、标准正态变换(SNV)、多元散射校正(MSC)、卷积平滑(SG)以及一阶导数(FD);以及特征筛选算法:竞争自适应重加权抽样(CARS)、无信息变量消除(UVE)和协同区间偏最小二乘(SiPLS)。
通过Python代码实现这些处理步骤,可以有效降低光谱中的噪声和基线漂移,增强信号的稳定性,同时剔除冗余波段,减少多重共线性干扰。这些操作为后续的建模工作(PLS回归、支持向量回归SVR或1D-CNN神经网络)提供了高质量、可靠的输入特征,提高了模型的预测精度和鲁棒性。
此外,这套方法不仅适用于哈密瓜可溶性固形物(SSC)检测,也可以轻松推广到苹果、葡萄、梨、柚子等其他果蔬的品质检测任务中。无论是快速无损检测、产地分级,还是农产品理化指标预测,这些方法都能提供可操作、可复现的技术支持。
总的来说,本文展示的光谱预处理和特征筛选流程,构建了一条从原始光谱采集到关键波段提取的完整路径,既适合科研实验,也能为实际果蔬智能检测和质量控制提供参考,具有较高的应用价值和推广潜力。
如果大家觉得本文对大家的学习和研究有所帮助,请大家关注、点赞和收藏,欢迎转发。谢谢大家!

Read more

【Part 3 Unity VR眼镜端播放器开发与优化】第四节|高分辨率VR全景视频播放性能优化

【Part 3 Unity VR眼镜端播放器开发与优化】第四节|高分辨率VR全景视频播放性能优化

文章目录 * 《VR 360°全景视频开发》专栏 * Part 3|Unity VR眼镜端播放器开发与优化 * 第一节|基于Unity的360°全景视频播放实现方案 * 第二节|VR眼镜端的开发适配与交互设计 * 第三节|Unity VR手势交互开发与深度优化 * 第四节|高分辨率VR全景视频播放性能优化 * 一、挑战分析与目标设定 * 1.1 主要瓶颈 * 1.2 目标设定 * 二、硬解与软解方案选型 * 2.1 平台解码能力检测 * 2.2 推荐策略 * 三、视野裁剪与分块播放 * 3.1 原理说明 * 3.2 实现流程图 * 3.3 伪代码 * 四、动态降级与多码率自适应 * 4.1

再谈Xilinx FPGA开发的Vivado流和Vitis流

前景提要:FPGA加速计算生态系统:从Vivado到Vitis AI的全面解析 在 AMD (Xilinx) 最新的 Vitis 统一软件平台架构下,FPGA 的开发被清晰地划分为两个世界。理解这两个世界的区别,是看懂现代 FPGA 论文和技术文档的关键。 逻辑一:自底向上的“硬件构建”逻辑 (Vivado Flow) ——“我是芯片设计师,我在造一台电脑。” 这是经典的、传统的 FPGA 开发方式。 1. 核心思维 * 关注点:时钟周期、复位信号、状态机翻转、AXI 总线位宽、时序收敛 (Timing Closure)。 * 目标:生成一个 .bit 文件(Bitstream),控制 FPGA 上的每一个查找表 (LUT) 和触发器 (FF)

OpenClaw配置飞书机器人完整指南

OpenClaw配置飞书机器人完整指南 使用openclaw channels add配置飞书机器人需完成插件安装→飞书应用创建→通道配置→事件订阅→发布应用五个核心步骤,以下是可直接执行的详细流程。 文章目录 * OpenClaw配置飞书机器人完整指南 * 一、前置准备 * 二、通道配置(openclaw channels add) * 方法1:交互式向导配置(推荐) * 方法2:非交互式命令配置(适合脚本) * 方法3:手动编辑配置文件 * 三、事件订阅与发布(关键步骤) * 四、测试与验证 * 五、常见问题排查 一、前置准备 1. 飞书开放平台创建应用(获取凭证) 1. 访问飞书开放平台:https://open.feishu.cn/app 2. 创建企业自建应用,填写名称(如"

ESP-Drone开源飞控:从零打造智能无人机的终极教程

ESP-Drone开源飞控:从零打造智能无人机的终极教程 【免费下载链接】esp-droneMini Drone/Quadcopter Firmware for ESP32 and ESP32-S Series SoCs. 项目地址: https://gitcode.com/gh_mirrors/es/esp-drone 想要亲手打造一架属于自己的智能无人机吗?ESP-Drone开源飞控项目为你打开了通往无人机世界的大门。这款基于ESP32芯片的开源方案,让每个人都能以极低成本实现飞行梦想。本文将带你从项目特色到实战应用,全方位了解这个令人兴奋的开源项目。 🚀 项目亮点:为什么选择ESP-Drone? ESP-Drone最大的魅力在于其完全开源的特性。从硬件设计文件到软件源代码,所有内容都透明公开,让你能够深度定制每一处细节。 核心优势对比: * 成本效益:相比商业无人机,硬件成本降低60%以上 * 灵活扩展:模块化设计支持摄像头、GPS等多种外设 * 技术门槛:完善的文档和社区支持,新手也能快速上手 ESP-Drone V1.2硬件布局 - 展示紧凑的电路设计