基于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

[科研实践] VS Code (Copilot) + Overleaf (使用 Overleaf Workshop 插件)

[科研实践] VS Code (Copilot) + Overleaf (使用 Overleaf Workshop 插件)

科研圈写文档常用 Latex 环境,尤其是 Overleaf 它自带的 AI 润色工具 Writefull 太难用了。如果能用本地的 CoPilot / Cursor 结合 Overleaf,那肯定超高效! 于是我们找到了 VS Code 里的 Overleaf Workshop 插件。这里已经安装好了,没装过的同学可以直接点击 “安装” 安装后左边会出现 Overleaf Workshop 的图标: 点击右边的“+”: Overleaf 官网需要登录,这里我们通过 cookie 调用已登录账号的 API: 回到主界面,右键点击 “检查”: 打开检查工具后,找到 “网络”(Network)窗口,搜索 “/project” /project 如果首次加载没内容,刷新页面就能看到

TRAE vs Qoder vs Cursor vs GitHub Copilot:谁才是真正的“AI 工程师”?

引言:工具选择 = 成本 + 效率 + 风险 的综合权衡 2026 年,AI 编程工具已从“玩具”走向“生产主力”。但面对 TRAE、Qoder、Cursor、GitHub Copilot 等选项,开发者不仅要问: * 它能写 Rust 吗?支持中文需求吗? * 更要问:一个月多少钱?团队用得起吗?代码安全有保障吗? 本文将从 五大核心维度 深度剖析四大主流 AI IDE: 1. 核心理念与自主性 2. 多语言与跨生态支持能力 3. 工程化与交付闭环能力 4. 中文本地化与业务适配 5. 收费模式、定价策略与企业成本 帮你做出技术可行、经济合理、风险可控的决策。 一、核心理念:

Claude, Cursor, Aider, Copilot,AI编程助手该选哪个?

2026年,AI编程工具已经非常成熟了。市面上这么多AI编程工具,哪个最好用? 本文选取了当前最具代表性的六款工具:Claude Code、Aider、Cursor、GitHub Copilot、MetaGPT 以及 OpenHands,从技术特性、优缺点及部署门槛进行客观对比。 Claude Code Anthropic 于2025年推出了 Claude Code,这是一款基于命令行的编程智能体工具。它不同于网页版的对话框,而是直接运行在终端中,能够深度理解本地项目结构。最出名的 AI 编程助手,很贵,但一分钱一分货,不得不说它很好用。 通过终端直接通过自然语言操作。它不仅能写代码,还能自主运行测试、解释复杂的架构、甚至执行终端命令来修复错误。其背后依托的是推理能力极强的 Claude 3.5/3.7 Sonnet 模型。 优势: * 推理能力极强:在处理复杂的逻辑重构和长代码理解上,目前处于行业顶尖水平。 * 自主性:

别再搞混了!Copilot Chat 和 Microsoft 365 Copilot 详细对比

虽然名字听起来相似 —— Microsoft 365 Copilot 和 Microsoft 365 Copilot Chat —— 但它们在多个方面存在重要区别。更关键的是,它们是相辅相成、缺一不可的。 📌 什么是 Microsoft 365 Copilot Chat? Microsoft 365 Copilot Chat(简称 Copilot Chat),主要基于网页内容生成回答。 而 Microsoft 365 Copilot 则不仅基于网页内容,还结合了用户自身的数据(如邮件、会议、文件等)。 自 2025年1月15日 起,Copilot Chat 已对所有组织全面开放。 即使是订阅了 Microsoft 365 Business Basic 的客户,也能安全地使用 Copilot Chat。