首页 > 解决方案 > Python 在不同条件下最小化

问题描述

我目前正在尝试为大型点数据集找到替换的点数据集。我想以不规则的方式定义替换数据集的点,从而最佳地描述该区域。我写了一个函数“目标”。这需要一个 numpy 数组,其中包含 x 个点。这些点我想在最后分发优化。该函数首先计算原始曲线上的交点,然后计算面积。误差用作参考区域。如何确保“最佳”分配积分?如何整合条件以便在此处设置数据集的限制?

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

from scipy.integrate import simps
from scipy.optimize import minimize
from numpy import trapz

# testpoints given by user
base_points_x = np.array([0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1])
base_points_y = np.array([1,5,5.5,6,6.5,6.7,6.9,7,7.1,7.15])

# calculate the base area
base_area_trapz = trapz(base_points_y, x=base_points_x)
base_area_simps = simps(base_points_y, x=base_points_x)
print("base area =", round(base_area_trapz,4))
print("base area =", round(base_area_simps,4))

# 1. method, use a discrete small equal discretised number of points
dis_points = 5
first_points_x = np.linspace(base_points_x[0], base_points_x[-1], dis_points)
first_points_y = np.zeros(dis_points)

for n in range(0, dis_points):
    xa = np.argmin(base_points_x <= first_points_x[n])
    xb = np.argmax(base_points_x >= first_points_x[n])
    first_points_y[n] = np.interp(first_points_x[n], base_points_x, base_points_y)

#calculate the first area and difference
first_area_trapz = trapz(first_points_y, x=first_points_x)
first_area_simps = simps(first_points_y, x=first_points_x)

print("base area =", round(first_area_trapz, 4), round(base_area_trapz-first_area_trapz, 4))
print("base area =", round(first_area_simps, 4), round(base_area_simps-first_area_simps, 4))

# 2. method optimize the area
def objective(x):
    y = np.zeros(len(x))
    for n in range(0, len(x)):
        xa = np.argmin(base_points_x <= x[n])
        xb = np.argmax(base_points_x >= x[n])
        y[n] = np.interp(x[n], base_points_x, base_points_y)

    return base_area_trapz - trapz(y, x=x)

#guess values (taken from previous function)
x0 = first_points_x
res = minimize(objective, x0, method='nelder-mead', bounds=[])

为了更好地理解,我举了一个例子:

在此处输入图像描述

标签: pythonnumpyoptimizationminimize

解决方案


您正在寻找的东西被称为分段线性函数近似。您可以使用 Pythonpwlf包轻松构建它们。

python3 -m pip install pwlf

然后,作为使用示例(警告,可能有点慢):

import numpy as np
import pwlf
import matplotlib.pyplot as plt

# Generate some dummy data.
X = np.linspace(0, 2*np.pi, 100)
y = np.sin(X) * X * X

pwlffit = pwlf.PiecewiseLinFit(X, y)
# Atol sets absolute tolerance, see scipy.optimize.differential_evolution.
lfx = pwlffit.fit(5, atol=1e-10)
lfy = pwlffit.predict(lfx)

plt.plot(X, y, label="data")
plt.plot(lfx, lfy, label="approximation")
plt.scatter(lfx, lfy, label="breakpoints")
plt.legend()
plt.tight_layout()
plt.show()

阴谋


推荐阅读