資深博導:我以為資料預處理是常識,直到遇到自己的學生

算法金「全网同名」發表於2024-06-26

大俠幸會,在下全網同名「演算法金」 0 基礎轉 AI 上岸,多個演算法賽 Top 「日更萬日,讓更多人享受智慧樂趣」

在光譜學領域,資料預處理是不可或缺的一環。

本文將基於 NIR soil 近紅外光譜資料,運用 Python 語言進行資料處理,並透過圖表直觀反映預處理帶來的變化。(資料集:後臺回覆 [ NIR soil ] 獲取 )

常用的光譜資料預處理技術包括:

  1. MSC(多元散射校正)
  2. SNV(標準正規化變換)
  3. 光譜微分
  4. 基線校正
  5. 去趨勢

一、MSC(多元散射校正)

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler

# 讀取資料
nirsoil_df = pd.read_csv(path)

# 提取光譜資料
spectra = nirsoil_df.filter(like='spc.')

# 進行MSC預處理
def msc(input_data):
    # 計算參考光譜(均值光譜)
    ref_spectrum = np.mean(input_data, axis=0)
    # 初始化校正後的光譜資料矩陣
    corrected_spectra = np.zeros_like(input_data)

    for i in range(input_data.shape[0]):
        fit = np.polyfit(ref_spectrum, input_data[i, :], 1, full=True)
        corrected_spectra[i, :] = (input_data[i, :] - fit[0][1]) / fit[0][0]

    return corrected_spectra

# 應用MSC
msc_spectra = msc(spectra.values)

# 視覺化對比
plt.figure(figsize=(12, 6))

# 原始光譜
plt.subplot(1, 2, 1)
plt.plot(spectra.values.T, color='blue', alpha=0.1)
plt.title('Original Spectra')
plt.xlabel('Wavelength Index')
plt.ylabel('Reflectance')

# MSC校正後的光譜
plt.subplot(1, 2, 2)
plt.plot(msc_spectra.T, color='red', alpha=0.1)
plt.title('MSC Corrected Spectra')
plt.xlabel('Wavelength Index')
plt.ylabel('Reflectance')

plt.tight_layout()


在輸出的圖片中,左側顯示的是原始光譜資料,右側顯示的是經過MSC(多元散射校正)處理後的光譜資料。

原始光譜(左側圖)

  • 顏色和形狀:每條藍色的線代表一個樣本的光譜資料,顏色淺且分佈較散。
  • 特點:可以觀察到光譜資料在某些波長處的反射率(Reflectance)存在一定的波動,這可能是由於散射效應和基線漂移引起的。

MSC校正後的光譜(右側圖)

  • 顏色和形狀:每條紅色的線代表一個樣本的校正後的光譜資料,顏色淺且分佈較集中。
  • 特點:校正後的光譜資料在各個波長處的反射率(Reflectance)更加一致,減少了由散射效應和基線漂移引起的變化。整體曲線更加平滑,差異性減少。

總結

  • 變化:經過MSC處理後,光譜資料在整體上變得更加一致和平滑,減少了不必要的噪音和變動,使得資料更適合後續的分析和建模。
  • 意義:MSC處理透過消除光譜資料中的散射效應和基線漂移,提高了資料的質量,增強了不同樣本之間的可比性。

防失聯,進免費知識星球交流。演算法知識直達星球:https://t.zsxq.com/ckSu3

更多內容,見免費知識星球

二、SNV(標準正規化變換)

# 提取光譜資料
spectra = nirsoil_df.filter(like='spc.')

# 進行SNV預處理
def snv(input_data):
    # 每個樣本減去其均值,然後除以其標準差
    corrected_spectra = (input_data - np.mean(input_data, axis=1, keepdims=True)) / np.std(input_data, axis=1, keepdims=True)
    return corrected_spectra

# 應用SNV
snv_spectra = snv(spectra.values)

# 視覺化對比
plt.figure(figsize=(12, 6))

# 原始光譜
plt.subplot(1, 2, 1)
plt.plot(spectra.values.T, color='blue', alpha=0.1)
plt.title('Original Spectra')
plt.xlabel('Wavelength Index')
plt.ylabel('Reflectance')

# SNV校正後的光譜
plt.subplot(1, 2, 2)
plt.plot(snv_spectra.T, color='green', alpha=0.1)
plt.title('SNV Corrected Spectra')
plt.xlabel('Wavelength Index')
plt.ylabel('Reflectance')

plt.tight_layout()
plt.show()

在輸出的圖片中,左側顯示的是原始光譜資料,右側顯示的是經過SNV(標準正規化變換)處理後的光譜資料。

原始光譜(左側圖)

  • 顏色和形狀:每條藍色的線代表一個樣本的光譜資料,顏色淺且分佈較散。
  • 特點:可以觀察到光譜資料在某些波長處的反射率(Reflectance)存在一定的波動,這可能是由於樣本間的差異和噪聲引起的。

SNV校正後的光譜(右側圖)

  • 顏色和形狀:每條綠色的線代表一個樣本的校正後的光譜資料,顏色淺且分佈較集中。
  • 特點:校正後的光譜資料在各個波長處的反射率(Reflectance)變得更加一致,樣本間的差異和噪聲顯著減少。每條曲線的均值為零,標準差為一,使得所有光譜都在同一個尺度上。

總結

  • 變化:經過SNV處理後,光譜資料的均值被中心化為零,標準差被標準化為一,減少了由於不同樣本間的散射效應和噪聲帶來的影響。
  • 意義:SNV處理透過對每個樣本的光譜資料進行均值中心化和標準化,消除了樣本間的散射效應,提高了資料的一致性和可比性,使得資料更適合後續的分析和建模。

三、光譜微分

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 讀取資料
# nirsoil_df = pd.read_csv('path_to_your_csv.csv')

# 提取光譜資料
spectra = nirsoil_df.filter(like='spc.')

# 進行光譜微分處理
def spectral_derivative(input_data, order=1):
    if order == 1:
        derivative_spectra = np.diff(input_data, n=1, axis=1)
    elif order == 2:
        derivative_spectra = np.diff(input_data, n=2, axis=1)
    else:
        raise ValueError("Only first and second order derivatives are supported.")
    return derivative_spectra

# 一階微分
first_derivative = spectral_derivative(spectra.values, order=1)

# 二階微分
second_derivative = spectral_derivative(spectra.values, order=2)

# 視覺化對比
plt.figure(figsize=(12, 6))

# 一階和二階微分
plt.plot(first_derivative[0, :], label='1st Derivative', color='black')
plt.plot(second_derivative[0, :], label='2nd Derivative', color='red')

plt.title('Spectral Derivatives')
plt.xlabel('Wavelength Index')
plt.ylabel('Reflectance')
plt.legend()
plt.grid(True)
plt.show()

在輸出的圖片中,我們同時展示了一階微分和二階微分處理後的光譜資料。

一階微分(黑色線)

  • 特點:一階微分曲線展示了光譜資料在各個波長處的變化率。它突出了光譜曲線的斜率變化,強調了光譜資料中快速變化的區域。
  • 用途:一階微分處理可以減少基線漂移的影響,並增強光譜中微弱的特徵和變化。這對於區分類似的光譜樣本非常有用。

二階微分(紅色線)

  • 特點:二階微分曲線展示了光譜資料的曲率變化率。它進一步強調了光譜曲線的區域性最大值和最小值,突出了更細微的變化。
  • 用途:二階微分處理可以進一步減少基線漂移和噪聲的影響,並提供更多關於光譜中細節特徵的資訊。這對於精細分析光譜資料中的細節特徵非常有用。

總結

  • 變化:一階和二階微分處理後,光譜資料的變化率和曲率變化率被突出展示,增強了光譜中細節特徵的可見性,減少了基線漂移和噪聲的影響。
  • 意義:導數處理透過強調光譜資料的變化率和曲率變化率,提供了更清晰的特徵和模式,有助於後續的分析和建模。

抱個拳,送個禮

點選 ↑ 領取

四、基線校正

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.sparse import diags
from scipy.sparse.linalg import spsolve

# 讀取資料
# nirsoil_df = pd.read_csv('path_to_your_csv.csv')

# 提取光譜資料
spectra = nirsoil_df.filter(like='spc.')

# 進行AsLS基線校正
def baseline_als(y, lam=1e5, p=0.01, niter=10):
    L = len(y)
    D = diags([1, -2, 1], [0, -1, -2], shape=(L, L-2))
    D = lam * D.dot(D.T)
    w = np.ones(L)
    for i in range(niter):
        W = diags(w, 0, shape=(L, L))
        Z = W + D
        z = spsolve(Z, w*y)
        w = p * (y > z) + (1-p) * (y < z)
    return z

def baseline_correction(input_data):
    corrected_spectra = np.zeros_like(input_data)
    for i in range(input_data.shape[0]):
        baseline_values = baseline_als(input_data[i, :])
        corrected_spectra[i, :] = input_data[i, :] - baseline_values
    return corrected_spectra

# 應用基線校正
corrected_spectra = baseline_correction(spectra.values)

# 視覺化對比
plt.figure(figsize=(12, 6))

# 原始光譜
plt.subplot(1, 2, 1)
plt.plot(spectra.values.T, color='blue', alpha=0.1)
plt.title('Original Spectra')
plt.xlabel('Wavelength Index')
plt.ylabel('Reflectance')

# 基線校正後的光譜
plt.subplot(1, 2, 2)
plt.plot(corrected_spectra.T, color='green', alpha=0.1)
plt.title('Baseline Corrected Spectra')
plt.xlabel('Wavelength Index')
plt.ylabel('Reflectance')

plt.tight_layout()
plt.show()

在輸出的圖片中,左側顯示的是原始光譜資料,右側顯示的是經過基線校正處理後的光譜資料。

原始光譜(左側圖)

  • 顏色和形狀:每條藍色的線代表一個樣本的光譜資料,顏色淺且分佈較散。
  • 特點:可以觀察到光譜資料在各個波長處的反射率(Reflectance)存在一定的基線漂移和噪聲,這可能是由測量誤差和環境因素引起的。

基線校正後的光譜(右側圖)

  • 顏色和形狀:每條綠色的線代表一個樣本的校正後的光譜資料,顏色淺且分佈較集中。
  • 特點:校正後的光譜資料在各個波長處的反射率(Reflectance)變得更加一致,基線漂移被去除,噪聲顯著減少。曲線的整體趨勢更加平滑和穩定。

總結

  • 變化:經過基線校正處理後,光譜資料的基線漂移被有效去除,減少了由測量誤差和環境因素帶來的影響,使得光譜資料更加清晰和穩定。
  • 意義:基線校正處理透過去除光譜資料中的基線漂移,提高了資料的質量和一致性,便於後續的分析和建模。

防失聯,進免費知識星球交流。演算法知識直達星球:https://t.zsxq.com/ckSu3

免費知識星球,歡迎加入交流

五、去趨勢

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import detrend

# # 讀取資料
# nirsoil_df = pd.read_csv('path_to_your_csv.csv')

# 提取光譜資料
spectra = nirsoil_df.filter(like='spc.')

# 進行去趨勢處理
def detrending(input_data):
    detrended_spectra = detrend(input_data, axis=1)
    return detrended_spectra

# 應用去趨勢處理
detrended_spectra = detrending(spectra.values)

# 視覺化對比
plt.figure(figsize=(12, 6))

# 原始光譜
plt.subplot(1, 2, 1)
plt.plot(spectra.values.T, color='blue', alpha=0.1)
plt.title('Original Spectra')
plt.xlabel('Wavelength Index')
plt.ylabel('Reflectance')

# 去趨勢後的光譜
plt.subplot(1, 2, 2)
plt.plot(detrended_spectra.T, color='brown', alpha=0.1)
plt.title('Detrended Spectra')
plt.xlabel('Wavelength Index')
plt.ylabel('Reflectance')

plt.tight_layout()
plt.show()

在輸出的圖片中,左側顯示的是原始光譜資料,右側顯示的是經過去趨勢處理後的光譜資料。

原始光譜(左側圖)

  • 顏色和形狀:每條藍色的線代表一個樣本的光譜資料,顏色淺且分佈較散。
  • 特點:光譜資料在各個波長處的反射率(Reflectance)存在一定的趨勢,這些趨勢可能是由實驗條件、測量誤差等因素引起的。

去趨勢後的光譜(右側圖)

  • 顏色和形狀:每條棕色的線代表一個樣本的去趨勢處理後的光譜資料,顏色淺且分佈較集中。
  • 特點:去趨勢處理後,光譜資料中各個波長處的趨勢被去除,資料更加平穩和一致,減少了由實驗條件、測量誤差等因素帶來的系統性偏差。

總結

  • 變化:經過去趨勢處理後,光譜資料中的系統性趨勢被去除,光譜曲線更加平穩和一致,減少了外部因素帶來的系統性偏差。
  • 意義:去趨勢處理透過去除光譜資料中的系統性趨勢,提高了資料的質量和一致性,使得光譜資料更適合後續的分析和建模。

更多內容,見微*公號往期文章: 審稿人:拜託,請把模型時間序列去趨勢!!

[ 抱個拳,總個結 ]

- 科研為國分憂,創新與民造福 -

日更時間緊任務急,難免有疏漏之處,還請大俠海涵 內容僅供學習交流之用,部分素材來自網路,侵聯刪

[ 演算法金,碎碎念 ]

全網同名,日更萬日,讓更多人享受智慧樂趣

如果覺得內容有價值,煩請大俠多多 分享、在看、點贊,助力演算法金又猛又持久、很黃很 BL 的日更下去;

同時邀請大俠 關注、星標 演算法金,圍觀日更萬日,助你功力大增、笑傲江湖

相關文章