1

図に示すように、負の勾配と正の勾配を持つコードで提供されたデータがあります。

ここに画像の説明を入力

この投稿で適用されたコードを使用して2 つの異なるレジームで構成されたデータの曲線をフィットさせて、このコードを作成しました。正または負の同じ勾配で機能しますが、一方が正で他方が負の場合、線を適切に合わせることができません。

from scipy import optimize
from scipy import optimize, interpolate
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
import numpy as np


x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
y = np.array([4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4])


def two_lines(x, a, b, c, d):
    one = a*x + b
    two = c*x + d
    return np.maximum(one, two)


'''Compute approximate slope and intercept of the two lines'''
poly_low = np.polyfit(x[0:int(0.5*(len(x) + 1))], y[0:int(0.5*(len(x) + 1))], deg=1)
poly_high = np.polyfit(x[int(0.5*(len(x) + 1)):len(x)], y[int(0.5*(len(x) + 1)):len(x)], deg=1)

# This part of the code credit goes to askewchan
pw0 = (poly_low[0], poly_low[1], poly_high[0], poly_high[1]) # a guess for slope, intercept, slope, intercept
pw, cov = curve_fit(two_lines, x, y, pw0)
crossover = (pw[3] - pw[1]) / (pw[0] - pw[2])


figure = plt.figure(figsize=(5.15, 5.15))
figure.clf()
plot = plt.subplot(111)
plt.plot(x, y, 'o', x, two_lines(x, *pw), '-')
plot.set_ylabel('Y', labelpad = 6)
plot.set_xlabel('X', labelpad = 6)
plt.show()

出力

さまざまな斜面の場合: ここに画像の説明を入力

同じ勾配の場合、両方とも負です (正の勾配でも問題なく動作します):

ここに画像の説明を入力

2 つの質問があります。

  1. Pythonでそのような場合に区分線形フィットを適用する方法は?
  2. それを 3 つ以上のレジームに拡張するにはどうすればよいですか?
4

2 に答える 2

0

あなたが持っているものは、あなたが提示している特定の問題とデータに対して基本的に機能しますが、この問題をより一般的に解決するのは間違った方法です. より広い範囲の状況に簡単に拡張することはできません。たとえば、複数のセグメント、線形セグメント間のより複雑な遷移を伴うデータ、適合の特定の側面を調整する必要がある状況などです。主な理由は、最も一般的で困難な方法 (高次元のマルチパラメーター フィット) で、特定の簡単で高度に制約された問題 (重複しない複数の線分をフィットさせる) を解決します。他の問題の中でも特に、この一般化により、フィッティングがパラメーター空間の正しい領域に到達することが難しくなります。 これは、困難な一般化されたグローバル ソリューションで解決しようとしている、簡単にローカライズされた適合に関する問題です。 魅力はわかりますが、おもちゃの例以外ではうまくいかないでしょう。

とはいえ、斜面の正しい標識から始める限り、あなたが持っているものはおもちゃの例として機能します. 少なくとも と から動作しますが、 の定義を考える(1,1,-1,1)(10,10,-10,10)、これらを知る必要もありますtwo_lines。また、一致できるように定義する必要がありますtwo_lines(元の三角形は上向きではなく下向きの三角形でした。これが、おそらく2つの「負の傾斜」線で機能した理由でもあります-負の傾斜であるからではなく、一致させることができるためです)あなたの元の定義による)。

ここに画像の説明を入力

from scipy import optimize
from scipy import optimize, interpolate
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
import numpy as np

x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
y = np.array([4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4])

def two_lines(x, a, b, c, d):
    one = a*x + b
    two = c*x + d
    return np.minimum(one, two)

pw, cov = curve_fit(two_lines, x, y, (10, 10, -10, 10))

figure = plt.figure(figsize=(5.15, 5.15))
figure.clf()
plot = plt.subplot(111)
plt.plot(x, y, 'o')
plt.plot(x, two_lines(x, *pw), '-')
plot.set_ylabel('Y', labelpad = 6)
plot.set_xlabel('X', labelpad = 6)
plt.show()

明らかな代替手段は、独立した区分線形フィットを使用して曲線に沿って移動することです。このアプローチは簡単で、高速で、柔軟性があり、おそらくあなたの直感にぴったりです。このアプローチは、無限の数のセグメントに簡単に拡張することもできます (グローバル ソリューションはおそらく 2 で最大になります)。また、線形セクションへの適合が、完全に線形ではない曲線のセクションによって台無しにされないようにすることもできます (たとえば、 、丸みを帯びたトランジション)。

于 2015-05-01T21:38:15.803 に答える