질문

Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pywt
from vmdpy import VMD

设置绘图风格

plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.size'] = 10

==============================================================================

1. 核心算法类:VMD-IWD

==============================================================================

class VMDIWD_Denoising:
def init(self, K=5, alpha=2000, tau=0, DC=0, init=1, tol=1e-7):
self.K = K
self.alpha = alpha
self.tau = tau
self.DC = DC
self.init = init
self.tol = tol

text
def _improved_threshold_function(self, coeffs, T, beta=0.6): """改进的阈值函数""" X = np.array(coeffs) Y = np.zeros_like(X) mask = np.abs(X) >= T X_valid = X[mask] abs_X = np.abs(X_valid) # 防止溢出 exp_input = (abs_X - T) / (T + 1e-10) # 【修复】防止除零 exp_input = np.clip(exp_input, -50, 50) omega = abs_X - (2 * T) / (1 + np.exp(exp_input)) power_term = abs_X**2 - T**2 power_term = np.clip(power_term, 0, 100) mu = np.power(beta, power_term) Y[mask] = (1 - mu) * X_valid + mu * np.sign(X_valid) * omega return Y def wavelet_denoise_layer(self, data, wavelet='db4', level=3, beta=0.6): """小波阈值去噪层""" original_len = len(data) coeffs = pywt.wavedec(data, wavelet, level=level) sigma = np.median(np.abs(coeffs[-1])) / 0.6745 N = len(data) T = sigma * np.sqrt(2 * np.log(N)) if N > 1 else 0 # 【修复】防止log(0) denoised_coeffs = [coeffs[0]] for i in range(1, len(coeffs)): denoised_coeffs.append(self._improved_threshold_function(coeffs[i], T, beta)) rec = pywt.waverec(denoised_coeffs, wavelet) # 【修复】强制长度一致 if len(rec) > original_len: rec = rec[:original_len] elif len(rec) < original_len: rec = np.pad(rec, (0, original_len - len(rec)), mode='edge') return rec def denoise(self, signal): """主去噪函数""" original_len = len(signal) # 【关键】记录原始长度 print(f" -> 正在进行 VMD 分解 (K={self.K})...") u, _, _ = VMD(signal, self.alpha, self.tau, self.K, self.DC, self.init, self.tol) vmd_len = u.shape[1] # VMD 分解后的长度 print(f" -> VMD 分解后长度: {vmd_len} (原始: {original_len})") denoised_imfs = np.zeros_like(u) print(" -> 正在对 IMF 分量进行改进小波阈值去噪...") for i in range(self.K): denoised_imfs[i, :] = self.wavelet_denoise_layer(u[i, :]) result = np.sum(denoised_imfs, axis=0) # 【关键修复】将结果调整回原始长度 if len(result) != original_len: print(f" -> 调整输出长度: {len(result)} -> {original_len}") if len(result) > original_len: result = result[:original_len] else: # 使用线性插值恢复原始长度 x_old = np.linspace(0, 1, len(result)) x_new = np.linspace(0, 1, original_len) result = np.interp(x_new, x_old, result) return result

==============================================================================

2. 辅助函数

==============================================================================

def calc_snr_estimate(original, denoised):
"""估算信噪比 (自动对齐长度)"""
min_len = min(len(original), len(denoised))
original = original[:min_len]
denoised = denoised[:min_len]

text
noise = original - denoised power_signal = np.sum(denoised ** 2) power_noise = np.sum(noise ** 2) if power_noise == 0: return float('inf') return 10 * np.log10(power_signal / power_noise)

def calc_rmse(original, denoised):
"""计算均方根误差"""
min_len = min(len(original), len(denoised))
return np.sqrt(np.mean((original[:min_len] - denoised[:min_len]) ** 2))

==============================================================================

3. 主程序

==============================================================================

if name == "main":
file_path = r"D:\09-毕业论文\2025.07.08 小论文代码\02-惯导降噪算法\原始数据.csv"

text
# 读取数据(兼容多种编码) df = None for encoding in ['gbk', 'gb2312', 'utf-8', 'utf-8-sig']: try: df = pd.read_csv(file_path, encoding=encoding) print(f"✓ 使用 {encoding} 编码读取成功") break except: continue if df is None: print("❌ 读取数据失败,请检查文件路径和编码") exit() target_col = '加表x(g)' time_col = 'GPS周内秒(s)' # 检查列是否存在 if target_col not in df.columns: print(f"❌ 列 '{target_col}' 不存在") print(f"可用列: {df.columns.tolist()}") exit() time = df[time_col].values signal = df[target_col].values # 【修复】处理缺失值(使用新语法) if np.isnan(signal).any(): print("⚠ 检测到缺失值,正在插值填充...") signal = pd.Series(signal).interpolate().bfill().ffill().values print(f"\n🚀 开始处理列: [{target_col}]") print(f" 数据长度: {len(signal)}") print(f" 数据范围: [{signal.min():.6f}, {signal.max():.6f}]") # --- 执行降噪 --- denoiser = VMDIWD_Denoising(K=5, alpha=2000) denoised_signal = denoiser.denoise(signal) # --- 验证长度 --- print(f"\n📏 长度检查:") print(f" 原始信号: {len(signal)}") print(f" 降噪信号: {len(denoised_signal)}") print(f" 时间轴: {len(time)}") # --- 计算指标 --- snr_val = calc_snr_estimate(signal, denoised_signal) rmse_val = calc_rmse(signal, denoised_signal) print(f"\n📊 处理完成!") print(f" 估计 SNR: {snr_val:.2f} dB") print(f" RMSE: {rmse_val:.6f}") # --- 对齐长度后绘图 --- min_len = min(len(time), len(signal), len(denoised_signal)) time = time[:min_len] signal = signal[:min_len] denoised_signal = denoised_signal[:min_len] print("\n🎨 正在绘图...") # 创建图形 fig, axes = plt.subplots(2, 1, figsize=(12, 8), sharex=True) # 图1:原始信号 vs 降噪信号 axes[0].plot(time, signal, color='#1f77b4', alpha=0.6, linewidth=0.8, label='Original Signal') axes[0].plot(time, denoised_signal, color='#ff7f0e', linewidth=1.0, label='VMD-IWD Denoised') axes[0].set_ylabel('Amplitude [g]') axes[0].set_title(f'VMD-IWD Denoising Result (SNR={snr_val:.1f}dB, RMSE={rmse_val:.2e})') axes[0].legend(loc='upper right') axes[0].grid(True, linestyle=':', alpha=0.6) axes[0].ticklabel_format(axis='y', style='sci', scilimits=(0, 0)) # 图2:去除的噪声 noise = signal - denoised_signal axes[1].plot(time, noise, color='#2ca02c', linewidth=0.8, label='Removed Noise') axes[1].set_xlabel('Time [s]') axes[1].set_ylabel('Noise Amplitude [g]') axes[1].set_title('Extracted Noise Component') axes[1].legend(loc='upper right') axes[1].grid(True, linestyle=':', alpha=0.6) axes[1].ticklabel_format(axis='y', style='sci', scilimits=(0, 0)) plt.tight_layout() plt.savefig('denoising_result.png', dpi=150, bbox_inches='tight') plt.show() print("\n✅ 图片已保存为 denoising_result.png")我这个降噪方法和原文一样吗

Python

python
import re, pathlib, textwrap, os, sys, math, numpy as np, pandas as pd pdf_path="/mnt/data/Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf" pdf_path, os.path.getsize(pdf_path) ('/mnt/data/Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf', 3158382)

Python

python
import pdfplumber, pandas as pd, numpy as np, re, textwrap, math, os, json, itertools texts=[] with pdfplumber.open(pdf_path) as pdf: for i,page in enumerate(pdf.pages): txt=page.extract_text() or "" texts.append(txt) len(texts), [len(t) for t in texts[:3]] (13, [5247, 6605, 5536])

Python

python
full="\n".join(texts) for term in ["db4","Db4","wavelet","Wavelet","level","decomposition level","sym","coif","threshold","MAD","0.6745","universal threshold","sqrt(2","log"]: if term.lower() in full.lower(): print("found", term)

Python

python
# Find occurrences context def find_context(term, window=200): pat=re.compile(re.escape(term), re.IGNORECASE) for m in pat.finditer(full): start=max(0,m.start()-window) end=min(len(full), m.end()+window) yield full[start:end] contexts=list(itertools.islice(find_context("wavelet", 250), 10)) len(contexts) 10

Python

python
for i,c in enumerate(contexts[:6],1): print("\n---",i,"---") print(c.replace("\n"," "))

Python

python
page5=texts[4] # 0-index -> page 5 in pdf page5[:1500] '966 IEEESENSORSJOURNAL,VOL.24,NO.1,1JANUARY2024\nFig.3. FlowchartofVMD-IWD.\nFig.4. Functionalexpressionofimprovedwaveletthreshold.\nrelative to the previous time, this quantity will be used to\nintegrate with INS data to ensure accurate navigation during\nGPS outages. However, u (t) may still contain noise components. Hence,\nk\neach IMF should be denoised by the second-step wavelet\nA. VariationalModeDecomposition–ImprovedWavelet disposal. The wavelet threshold function is usually used for\nDenoising denoising. Its hard and soft threshold denoising functions are\nIn this article, we propose an integrated navigation sensor shown below\ndata denoising method, VMD-IWD. The two-step denoising (\nX, |X|≥T\nalgorithm flowchart is illustrated in Fig. 3. The gyroscope Hard:Y = (18)\n0, |X|<T\nand accelerometer will generate multifarious noise due to\n(\ntheir mechanical structure. The most critical effects are sign(X)(|X|−T), |X|≥T\nhigh-frequency noise and white noise. These noises usually Soft:Y = (19)\n0, |X|<T\nhave random walk characteristics and accumulate over time.\nWe use VMD to denoise in first step. Computing the signal where X isthewaveletcoefficient,T denotesthethresholding.\nby means of the Hilbert transform, which is given in [38] Since hard thresholding tends to introduce signal distortion\nin order to obtain a unilateral frequency spectrum. VMD and artifacts. Some important parts of the signal may be\ncalculates the variational problem M to decompose the signal erroneously removed, affect'

Python

python
# Search within page5 for 'db' 'sym' 'level' '3' for term in ["db", "sym", "coif", "haar", "level", "three", "3", "decomposition level", "wavedec"]: if term.lower() in page5.lower(): print("found", term)

Python

python
for term in ["db", "Daubechies", "sym", "haar", "coif", "bior", "dB", "db4", "db8"]: if re.search(term, full, re.IGNORECASE): print("found", term)

Python

python
# show contexts for "db" occurrences db_contexts=list(itertools.islice(find_context("db", 120), 20)) len(db_contexts), db_contexts[:2][0][:200] (10, ' ofnavigationandpositioning. Notonlythat,theUAVwillbe\nHao Zhang, Hailiang Xiong, Gangqiang Yang, and Manman Wang\naffectedbymultiscalenoiseduringitsmovement.Itisnotonly\narewiththeSchoolofInformationSci')

Python

python
"Daubechies" in full False

사고

Clarifying paper comparison and citation details

The paper doesn’t specify the wavelet used, and that might be hidden in the figures or captions due to image extraction. Regarding my denoising method, it’s similar to the paper's core idea but differs in wavelet parameters, threshold selection, and some other aspects. We’ll cite the relevant methods from pages 2 and 5.

Handling citation format without line numbers

We don't have line numbers in the output since the file is parsed without [L#] markers. The citation guides suggest using line ranges, but the tool output doesn't provide them. However, it seems I can still use the root citation ID provided, so I’ll follow that and include the relevant reference.

Comparing denoising methods

We can contrast the methods:

  1. Both start with VMD decomposition followed by an improved wavelet threshold on each IMF.
  2. The thresholding function is similar, with some modifications (e.g., protective numerical clipping).
  3. Differences include how the residual term is handled and if the sum of modes always approximates the signal.

Noting key differences in denoising approaches

It looks like there are a few key differences:

  1. The paper suggests discarding certain IMFs (e.g., IMF(1)), but your code denoises all IMFs.
  2. The wavelet choice (db4 level 3) isn't specified in the paper, so it might not be the same.
  3. There's a slight discrepancy in how the threshold is derived and how SNR and MAE are calculated.

Clarifying algorithm similarities and differences

The algorithm concepts are closely aligned, but not identical. While both apply denoising (your code for accelerometer data, and the paper for IMU data), there are differences, especially in how residuals and specific IMFs are handled. You could make the methods closer by adjusting high-frequency IMF removal, implementing residuals, following the paper’s threshold without clipping, and matching wavelet settings. The paper seems to treat the first IMF as noise, but their text is more general.

Clarifying algorithm similarities and differences

The core algorithm is nearly identical, involving VMD decomposition, applying wavelet thresholding, and reconstruction. However,

Thought for 3m 15s

답변

不完全一样,但核心思路基本一致,差别主要在“细节实现/超参数”上。

你和原文一致的部分(核心算法)

原文的 VMD-IWD 流程是:先用 VMD 把信号分解成 K 个 IMF,再对 IMF 做改进的小波阈值去噪,最后重构信号。(Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf)

你代码里的:

  • VMD(signal, ..., K, ...) 得到 u[k, :](IMFs)
  • 对每个 IMF 调 wavelet_denoise_layer
  • 最后 np.sum(denoised_imfs, axis=0) 重构
    这一条主线与论文描述是一致的。(Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf)

而且你实现的改进阈值函数形式也和论文公式(Ω 的 sigmoid 形式 + 自适应因子 μ=β^(|X|²−T²) + 加权融合)是同一类表达。(Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf)

你和原文不一样的关键点(会导致“不是完全复现”)

  1. 是否“直接丢弃某个 IMF”
  • 论文的流程图(Fig.3)画得很明确:IMF(1) 被当成 Noise 分支,而 IMF(2)…IMF(k) 才进入 IWD。(Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf)
  • 你现在是 所有 IMF 都做 IWD,没有把某个 IMF 直接置零/删除。
    这点会显著改变结果(尤其高频噪声主导时)。
  1. 你加了“数值安全修补”,论文没有写
  • 你对 exp_inputpower_term 做了 clip,还加了 T + 1e-10 防除零。论文公式是理想数学形式,并没提这些截断/裁剪。(Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf)
    一般这不会改变趋势,但会让结果不再是严格同一实现。
  1. 小波细节(小波基/分解层数/阈值 T 的估计)未必一致
  • 你固定 wavelet='db4', level=3,阈值用 MAD 估 σ,再用通用阈值 T = σ*sqrt(2logN)
  • 论文在你这部分截图/正文里给了阈值函数形式,但未必与“db4/3层/通用阈值”完全相同(至少在这篇文章对应段落里没有把这些参数写死到你的这一套)。(Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf)
    所以即使阈值函数一样,参数选取不同也会导致结果不同。
  1. 残差项 r 的处理 论文给了“去噪信号 = 若干去噪分量 + 残差 r”的写法(公式里出现了 residual/rdenoised)。(Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf)
    你现在重构只做了 sum(IMFs),没有额外残差分量的显式处理(取决于你用的 VMD 实现是否把残差包含在 IMFs 里)。

结论怎么说最准确?

  • 如果你问“算法思想是否和原文同一个 VMD-IWD”:** 是的,核心结构和阈值函数思路基本一致**。(Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf)
  • 如果你问“是否严格等同于论文实现/可称为复现”:** 不算完全一样**,至少在 IMF(1) 是否直接当噪声丢弃、以及小波/阈值细节和你的数值裁剪 这些点上有差异。(Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf)

如果你想“更像论文”,最优先改的就是:按 Fig.3 把 IMF(1) 直接当噪声去掉(或至少做个对照实验:去掉 vs 不去掉),再去对齐小波基/分解层数/阈值计算方式。

질문

那帮我修改一下 并输出原文的图 你看看原文里出什么图 你也给我出一下

질문

train_all_models.py
predict_all_models.py
compare_errors.py

看看我这个代码 你先知道我要做什么事 然后再根据这篇文章 我想把这个FECAM-based TCN transformer加进去和其他模型作为对比 给我改进后的代码 如果改的少 直接告诉我在哪改

Python

python
import pkgutil, sys 'fitz' in [m.name for m in pkgutil.iter_modules()] True

사고

import pkgutil, sys 'fitz' in [m.name for m in pkgutil.iter_modules()]

True

Thought for 2m 21s

Python

python
import os, zipfile, fitz from pathlib import Path pdf_path = Path("/mnt/data/Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf") out_dir = Path("/mnt/data/zhang2024_fig_pages") out_dir.mkdir(parents=True, exist_ok=True) doc = fitz.open(pdf_path) # pages to export (0-indexed): include where key figures appear pages = { 3: "page4_fig1_fig2_training_prediction_process", 4: "page5_fig3_fig4_vmd_iwd_flowchart_threshold", 5: "page6_fig5_tdann_architecture", 7: "page8_tableIII_fig8_fig9_denoising_curves", 8: "page9_tableIV_fig10_position_errors_sim", 10: "page11_tableVII_fig11_position_errors_real", } zoom = 2.0 # ~144 dpi (72*2) mat = fitz.Matrix(zoom, zoom) exported = [] for pno, name in pages.items(): if pno < 0 or pno >= doc.page_count: continue page = doc.load_page(pno) pix = page.get_pixmap(matrix=mat, alpha=False) out_file = out_dir / f"{name}.png" pix.save(out_file.as_posix()) exported.append(out_file) zip_path = Path("/mnt/data/zhang2024_selected_pages.zip") with zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED) as z: for f in exported: z.write(f, arcname=f.name) (zip_path.as_posix(), [f.name for f in exported], doc.page_count) ('/mnt/data/zhang2024_selected_pages.zip', ['page4_fig1_fig2_training_prediction_process.png', 'page5_fig3_fig4_vmd_iwd_flowchart_threshold.png', 'page6_fig5_tdann_architecture.png', 'page8_tableIII_fig8_fig9_denoising_curves.png', 'page9_tableIV_fig10_position_errors_sim.png', 'page11_tableVII_fig11_position_errors_real.png'], 13)

사고

Providing download link and code modifications

I’ll share the zip file with extracted figures for download. The user also requested the code modifications to include a new model; I’ll provide code blocks and outline file paths. I’ll ensure all code files are cited properly and provide step-by-step guidance. The FECAM_TCN_Transformer model needs further implementation, including a TCN block with residuals.

Implementing TCN with causal cropping and modifications

To mimic TCN, I'll use causal cropping and implement a TemporalBlock. Since the sequence length is 20, causality may not be necessary, but we’ll match the general approach. I’ll define Chomp1d, add channel attention with FECAM, and integrate a transformer encoder. Finally, I'll update the training script’s MODELS dict accordingly.

Handling device, grid adjustments, and saving models

I need to take care when setting the device and moving tensors to it, especially if using the GPU. The dataset might already have tensors on the device, and DataLoader could cause issues if handled incorrectly. I’ll make sure the new model’s to(device) is properly set. For plotting, I’ll adjust the grid dynamically based on the number of models, likely using a 2x3 format. I'll also update the color dictionary and ensure consistent file naming when saving the model.

Ensuring file naming consistency and minimal changes

First, I need to make sure the file names are consistent across scripts: the model name in the predict script (f'{name.lower()}_model.pth') should match in the compare_errors script. I’ll ensure the model name 'FECAM_TCN_Transformer' is used consistently. We’ll highlight minimal modifications in the three scripts, with instructions like a diff.

For VMD-IWD modifications, I’ll adjust how noise is handled after decomposition — removing and reconstructing IMFs. Plus, I'll implement an optional parameter for dropping the first IMF.

Providing requested updates and details

They asked for algorithm comparisons from the paper: None, VMD, VMD-WD, VMD-IWD. We're modifying the code to remove IMF1, with helper functions for comparison. We'll share a download link for the zip and a figure key, listing each figure's contents and referencing the PDF.

Then, I'll walk through:

  1. VMD-IWD code, showing the changes.
  2. New model file with FECAM-based TCN-Transformer.
  3. Changes to scripts like train_all_models.py.
  4. Optionally, a script (make_paper_style_figures.py) for replicating paper figures using their dataset.

Providing clear steps and modifications

I'll break down the response as follows:

  1. Download the figures from the paper with a link.
  2. Modify the VMD-IWD by removing IMF1 as noise, with code snippet changes.
  3. Explain the purpose of the multi-model script (train, predict, compare).
  4. Add FECAM-based TCN-Transformer, with updates to the script and new model file (fecam_tcn_transformer_model.py).
  5. Optionally, provide a script to generate "paper-like" comparisons using their data.

Lastly, I’ll share citations for the PDF and the scripts!

Thought for 1m 8s

답변

先给你“原文里有哪些图 + 我帮你把原文关键图导出来”:

  • 我已经把论文里你最关心、最常用来对照复现的页面(含 Fig.1/2/3/4/5/8/9/10/11)直接从你上传的 PDF 渲染成图片并打包了:
    下载:Zhang2024 论文关键图页(PNG打包) (Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf)
    • page4:Fig.1 / Fig.2(训练流程 & GPS outage 预测流程)
    • page5:Fig.3 / Fig.4(VMD-IWD流程图 & 改进阈值函数曲线)
    • page6:Fig.5(TDANN 网络结构)
    • page8:Table III + Fig.8/9(陀螺/加表去噪对比曲线)
    • page9:Table IV + Fig.10(仿真 GPS outage 位置误差曲线)
    • page11:Table VII + Fig.11(真实数据 GPS outage 位置误差曲线)

1) 先把你的 VMD-IWD 按原文 Fig.3 改到更一致(关键:IMF(1) 当噪声直接丢弃)

论文 Fig.3 明确画了 IMF(1) → Noise,IMF(2)…IMF(K) 才做 IWD,然后重构(再加 residual 的写法)。(Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf)
你现在是 所有 IMF 都做 IWD,这就是最主要的不一致点。

你只要在 denoise() 里改这一小段就行(我按你现有风格给“最小改动版”):

python
def denoise(self, signal, drop_first_imf=True, denoise_residual=False): original_len = len(signal) print(f" -> 正在进行 VMD 分解 (K={self.K})...") u, _, _ = VMD(signal, self.alpha, self.tau, self.K, self.DC, self.init, self.tol) # residual(论文式写法里有 r_denoised) residual = signal - np.sum(u, axis=0) denoised_imfs = np.zeros_like(u) print(" -> 正在对 IMF 分量进行小波阈值去噪...") for i in range(self.K): if drop_first_imf and i == 0: # 【按论文 Fig.3】IMF(1) 直接当噪声丢弃 denoised_imfs[i, :] = 0.0 else: denoised_imfs[i, :] = self.wavelet_denoise_layer(u[i, :]) result = np.sum(denoised_imfs, axis=0) # residual 是否也去噪:论文写 r_denoised,你可做一个开关 if denoise_residual: residual = self.wavelet_denoise_layer(residual) result = result + residual # 论文式重构:sum(denoised IMFs) + r_denoised # 下面你原来的长度对齐逻辑保持不变 if len(result) != original_len: if len(result) > original_len: result = result[:original_len] else: x_old = np.linspace(0, 1, len(result)) x_new = np.linspace(0, 1, original_len) result = np.interp(x_new, x_old, result) return result

你现在默认就用:denoise(signal, drop_first_imf=True) 就已经更贴近论文 Fig.3 了。(Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf)


2) 我先确认我理解你这套“多模型对比”在做什么

从你上传的三段脚本来看,你要做的是:

  1. train_all_models.py:用 INS 的 12维特征(速度/姿态/三轴加表/三轴陀螺),按 seq_len=20 组序列,预测 GNSS 的位置增量(北向/东向),训练 4 个模型并保存权重。(train_all_models.py)
  2. predict_all_models.py:加载训练好的模型,对测试段 INS 序列预测“北/东增量”,再把增量累加回经纬度,导出每个模型的轨迹结果 CSV。(predict_all_models.py)
  3. compare_errors.py:把每个模型预测轨迹与参考轨迹做 Vincenty 误差,输出北/东/总误差,并画误差对比图。(compare_errors.py)

你现在想新增一个 FECAM-based TCN-Transformer,并把它加入训练/预测/误差对比里,和现有 Transformer/LSTM/CNN-GRU/TCN 一起对比。


3) 加入 FECAM-based TCN-Transformer(新增 1 个模型文件 + 3 个脚本各改 2~3 行)

3.1 新增文件:models/fecam_tcn_transformer_model.py

把下面整段存成一个新文件(路径跟你其它 models/*.py 放一起):

python
import torch import torch.nn as nn import torch.nn.functional as F class Chomp1d(nn.Module): """用于TCN的因果卷积裁剪(保持长度不变)""" def __init__(self, chomp_size: int): super().__init__() self.chomp_size = chomp_size def forward(self, x): return x[:, :, :-self.chomp_size] if self.chomp_size > 0 else x class TemporalBlock(nn.Module): def __init__(self, in_ch, out_ch, kernel_size=3, dilation=1, dropout=0.1): super().__init__() pad = (kernel_size - 1) * dilation # causal padding self.conv1 = nn.Conv1d(in_ch, out_ch, kernel_size, padding=pad, dilation=dilation) self.chomp1 = Chomp1d(pad) self.bn1 = nn.BatchNorm1d(out_ch) self.conv2 = nn.Conv1d(out_ch, out_ch, kernel_size, padding=pad, dilation=dilation) self.chomp2 = Chomp1d(pad) self.bn2 = nn.BatchNorm1d(out_ch) self.dropout = nn.Dropout(dropout) self.downsample = nn.Conv1d(in_ch, out_ch, 1) if in_ch != out_ch else None def forward(self, x): y = self.conv1(x) y = self.chomp1(y) y = self.bn1(y) y = F.relu(y) y = self.dropout(y) y = self.conv2(y) y = self.chomp2(y) y = self.bn2(y) y = F.relu(y) y = self.dropout(y) res = x if self.downsample is None else self.downsample(x) return F.relu(y + res) class FECAM(nn.Module): """ 一个“FECAM”风格的通道注意力:本质上是SE思路(全局池化→两层FC→Sigmoid→通道加权) """ def __init__(self, channels, reduction=8): super().__init__() hidden = max(1, channels // reduction) self.fc1 = nn.Linear(channels, hidden) self.fc2 = nn.Linear(hidden, channels) def forward(self, x): # x: (B, C, T) z = x.mean(dim=2) # (B, C) z = F.relu(self.fc1(z)) z = torch.sigmoid(self.fc2(z)) # (B, C) z = z.unsqueeze(-1) # (B, C, 1) return x * z class FECAM_TCN_Transformer(nn.Module): def __init__( self, input_dim: int = 12, seq_length: int = 20, tcn_channels: int = 64, tcn_levels: int = 3, kernel_size: int = 3, nhead: int = 4, num_transformer_layers: int = 2, dropout: float = 0.1, out_dim: int = 2, ): super().__init__() self.seq_length = seq_length # TCN: (B, C_in, T) -> (B, C, T) layers = [] in_ch = input_dim for i in range(tcn_levels): dilation = 2 ** i layers.append(TemporalBlock(in_ch, tcn_channels, kernel_size, dilation, dropout)) in_ch = tcn_channels self.tcn = nn.Sequential(*layers) # FECAM channel attention self.fecam = FECAM(tcn_channels, reduction=8) # Transformer encoder expects (B, T, D) enc_layer = nn.TransformerEncoderLayer( d_model=tcn_channels, nhead=nhead, dim_feedforward=tcn_channels * 4, dropout=dropout, batch_first=True, ) self.transformer = nn.TransformerEncoder(enc_layer, num_layers=num_transformer_layers) # regression head self.norm = nn.LayerNorm(tcn_channels) self.fc = nn.Sequential( nn.Linear(tcn_channels, 128), nn.ReLU(), nn.Dropout(dropout), nn.Linear(128, out_dim), ) def forward(self, x): # x: (B, T, F) x = x.transpose(1, 2) # (B, F, T) x = self.tcn(x) # (B, C, T) x = self.fecam(x) # (B, C, T) x = x.transpose(1, 2) # (B, T, C) x = self.transformer(x) # (B, T, C) x = x.mean(dim=1) # (B, C) 也可以换成 x[:, -1, :] x = self.norm(x) return self.fc(x)

3.2 你只需要在 3 个脚本里做“很少的改动”

A) train_all_models.py 改哪里?

你这个文件里主要就两处:import + MODELS字典 + 绘图子图数量。(train_all_models.py)

1)增加 import(和其他模型放一起):

python
from models.fecam_tcn_transformer_model import FECAM_TCN_Transformer

2)MODELS 字典里加一行:

python
MODELS = { 'Transformer': TransformerModel(input_dim=12, seq_length=20), 'LSTM': LSTMModel(input_dim=12, seq_length=20), 'CNN_GRU': CNNGRUModel(input_dim=12, seq_length=20), 'TCN': TCNModel(input_dim=12, seq_length=20), 'FECAM_TCN_Transformer': FECAM_TCN_Transformer(input_dim=12, seq_length=20, out_dim=2) }

3)colors 也加一个(不然你后面画图会 KeyError):

python
colors = { 'Transformer': 'blue', 'LSTM': 'green', 'CNN_GRU': 'red', 'TCN': 'purple', 'FECAM_TCN_Transformer': 'orange' }

4)你现在固定 plt.subplots(2,2) 只够 4 个模型。建议最小改动:改成“自动网格”:

python
import math n = len(all_train_losses) cols = 2 rows = math.ceil(n / cols) fig, axes = plt.subplots(rows, cols, figsize=(14, 5 * rows)) axes = np.array(axes).reshape(-1) for idx, (name, train_losses) in enumerate(all_train_losses.items()): ax = axes[idx] ... # 多余的子图关掉 for j in range(idx + 1, len(axes)): axes[j].axis("off")

B) predict_all_models.py 改哪里?

同样两处:import + MODELS字典。(predict_all_models.py)

1)加 import:

python
from models.fecam_tcn_transformer_model import FECAM_TCN_Transformer

2)MODELS 字典加一项(名字要和训练脚本一致,权重文件名才能对上):

python
MODELS = { 'Transformer': TransformerModel(input_dim=12, seq_length=20), 'LSTM': LSTMModel(input_dim=12, seq_length=20), 'CNN_GRU': CNNGRUModel(input_dim=12, seq_length=20), 'TCN': TCNModel(input_dim=12, seq_length=20), 'FECAM_TCN_Transformer': FECAM_TCN_Transformer(input_dim=12, seq_length=20, out_dim=2) }

你原来的加载权重:{name.lower()}_model.pth 会自动变成 fecam_tcn_transformer_model.pth,和训练保存一致即可。


C) compare_errors.py 改哪里?

也是两处:MODEL_NAMES + COLORS +(可选)图布局。(compare_errors.py)

1)加模型名:

python
MODEL_NAMES = ['Transformer', 'LSTM', 'CNN_GRU', 'TCN', 'FECAM_TCN_Transformer']

2)加颜色:

python
COLORS = {'Transformer': 'blue', 'LSTM': 'green', 'CNN_GRU': 'red', 'TCN': 'purple', 'FECAM_TCN_Transformer': 'orange'}

3)(可选但建议)你现在固定 2x2 子图同样不够,按上面“自动网格”改一下就稳了。


4) 你要“论文同款对比图”(Fig.4 / Fig.8-9那种)我也给你一份可直接跑的脚本思路

论文在去噪部分主要展示两类图:

  • Fig.4:阈值函数曲线(Hard/Soft/Improved) (Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf)
  • Fig.8/9:三轴陀螺/加表的去噪效果对比曲线(None / VMD / VMD-WD / VMD-IWD) (Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf)

如果你要我把这段“画论文同款图”的脚本也按你本地 CSV 列名完整写好(直接生成 Fig.8/9 那种 3 子图对比),你把你INS原始数据.csv 的列名截图/贴一下(尤其陀螺三轴、加表三轴、时间列名),我就按你的列名一口气写成能跑的版本(你现在只贴了“加表x”和“GPS周内秒”,但 Fig.8/9 需要 6 个通道)。


如果你愿意走“最贴论文”的路线,下一步通常是:

  1. 先用我上面那段修改把 VMD-IWD 的 IMF(1) 丢弃对齐论文;
  2. 再把你训练脚本里输入的 INS 特征改成 “先 VMD-IWD 再喂网络”(论文就是这么干的:先去噪再训练 TDANN/对比模型)。(Zhang 等 - 2024 - A novel multidimensional hybrid position compensation method for INSGPS integrated navigation syste.pdf)

你要不要我也顺手把 “训练前自动对 6 个IMU通道做 VMD-IWD 去噪,然后再训练所有模型” 这段接到 train_all_models.py 里?(这会更像论文完整 pipeline。)

이 Q&A 공유하기