You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中优化插值数组:最小误差缩减尺寸的标准方法

3D数组插值后优化采样点缩减尺寸的解决方案

问题描述

我在Python中处理一个51×51×181的3D数组,需要做3D插值(可计算任意中间点)。现在要在保持数组元素总数不变的前提下缩减数组尺寸,同时尽可能降低插值误差。示例中的Angles和Shifts不需要等间距,我已经写出了误差函数,但在SciPy里找不到合适的优化器,想问有没有标准解决方案?

示例代码

import numpy as np
from scipy.interpolate import RegularGridInterpolator
import itertools

Data = np.zeros((5, 180))
Angles = np.linspace(0, 360, 10)
Shifts = np.linspace(0, 100, 10)

Data = np.sin(np.deg2rad(Angles[:, None] + Shifts[None, :]))

interp = RegularGridInterpolator((Angles, Shifts), Data, bounds_error=False, fill_value=None)

def errorfunc():
    Angles = np.linspace(0, 360, 50)
    Shifts = np.linspace(0, 100, 50)

    Function_Results = np.sin(np.deg2rad(Angles[:, None] + Shifts[None, :]).flatten())
    Data_interp = interp(np.array(list(itertools.product(Angles, Shifts))))
    Error = np.sqrt(np.mean(np.square(Function_Results - Data_interp)))
    return Error

标准解决方案思路

1. 基于优化器的自适应采样调整

这是解决这类非均匀采样优化问题的核心方案,把采样点位置作为优化变量,用你的误差函数作为目标函数,调用通用优化器求解:

  • 变量定义:将原等间距采样点(如Angles、Shifts)替换为可调整的变量,需保证各维度点数的乘积等于原数组总元素数(比如原51×51×181=466201,可调整为200×200×117这类接近的组合)。
  • 适配SciPy优化器:使用scipy.optimize.minimize,需要把你的误差函数改成接受变量输入的形式——将采样点展平为一维数组传入函数,内部再整理成有序的采样轴,计算插值误差。
  • 约束设置:必须添加边界约束(比如Angles限制在0-360,Shifts限制在0-100),还要添加单调递增约束(保证采样点有序,插值器能正常工作),可通过constraints参数结合type='ineq'实现。

2. 结合数据特征的预采样优化

如果数据存在明显的高频变化区域(比如某些角度/位移区间数值波动剧烈),可以先做特征分析再优化:

  • 计算原数据在各维度的梯度或二阶导数,定位变化剧烈的区域,在这些区域加密采样,平缓区域稀疏采样,能在总点数不变的前提下大幅降低误差。
  • 可以先按等间距缩减点数,再用优化器微调采样点位置,兼顾效率和精度。

3. 改用径向基函数(RBF)插值

如果RegularGridInterpolator的规则限制过多,可尝试SciPy的Rbf插值——它天然支持非均匀采样点。优化思路和之前一致:将采样点位置作为变量,最小化插值误差,缺点是计算成本较高,适合中小规模数据。

适配优化器的误差函数示例

import numpy as np
from scipy.interpolate import RegularGridInterpolator
import itertools
from scipy.optimize import minimize

# 原数据与初始插值器
Angles_orig = np.linspace(0, 360, 10)
Shifts_orig = np.linspace(0, 100, 10)
Data = np.sin(np.deg2rad(Angles_orig[:, None] + Shifts_orig[None, :]))
interp_orig = RegularGridInterpolator((Angles_orig, Shifts_orig), Data, bounds_error=False, fill_value=None)

# 目标:保持总点数100(10×10)不变,调整采样点位置
n_angles = 10
n_shifts = 10

def error_func(x):
    # x前n_angles个元素为Angles,后n_shifts个为Shifts,强制排序保证有序
    angles = np.sort(x[:n_angles])
    shifts = np.sort(x[n_angles:])
    # 构建新插值器
    interp_new = RegularGridInterpolator((angles, shifts), Data, bounds_error=False, fill_value=None)
    # 计算误差
    test_angles = np.linspace(0, 360, 50)
    test_shifts = np.linspace(0, 100, 50)
    test_points = np.array(list(itertools.product(test_angles, test_shifts)))
    true_vals = np.sin(np.deg2rad(test_points[:,0] + test_points[:,1]))
    interp_vals = interp_new(test_points)
    return np.sqrt(np.mean(np.square(true_vals - interp_vals)))

# 初始猜测:等间距采样点
x0 = np.concatenate([np.linspace(0, 360, n_angles), np.linspace(0, 100, n_shifts)])
# 边界约束
bounds = [(0, 360)]*n_angles + [(0, 100)]*n_shifts
# 单调递增约束:保证后一个采样点≥前一个
constraints = []
for i in range(n_angles-1):
    constraints.append({'type': 'ineq', 'fun': lambda x, i=i: x[i+1] - x[i]})
for i in range(n_shifts-1):
    constraints.append({'type': 'ineq', 'fun': lambda x, i=i: x[n_angles + i+1] - x[n_angles + i]})

# 执行优化(用SLSQP处理带约束的优化问题)
result = minimize(error_func, x0, bounds=bounds, constraints=constraints, method='SLSQP')

# 提取优化后的采样点
optimized_angles = np.sort(result.x[:n_angles])
optimized_shifts = np.sort(result.x[n_angles:])

内容的提问来源于stack exchange,提问作者Okapi575

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 00:10:48