【问题标题】:How to extrapolate a function based on x,y values?如何根据 x,y 值推断函数?
【发布时间】:2018-06-09 10:58:02
【问题描述】:

好的,几天前我开始使用 Python。我主要将它用于数据科学,因为我是一名本科化学专业的学生。好吧,现在我遇到了一个小问题,因为我必须推断一个函数。我知道如何制作简单的图表,所以请尽量简单地向我解释。我开始:

from matplotlib import pyplot as plt
from matplotlib import style
style.use('classic')
x = [0.632455532, 0.178885438, 0.050596443, 0.014310835, 0.004047715]
y = [114.75, 127.5, 139.0625, 147.9492188, 153.8085938]
x2 = [0.707, 0.2, 0.057, 0.016, 0.00453]
y2 = [2.086, 7.525, 26.59375,87.03125, 375.9765625]

因此,对于这些值,我必须找出一种推断方法,以便在我的 x=0 时获得 y(或 y2)值。我知道如何在数学上做到这一点,但我想知道 python 是否可以做到这一点以及如何在 Python 中执行它。有简单的方法吗?你能给我举一个我给定价值观的例子吗? 谢谢

【问题讨论】:

  • 您是否混淆了外插和插值?
  • 不,我特别需要超出我的值范围的值
  • 您的问题不清楚。你在问什么?你能提供一些示例输入/输出吗?
  • @pault 好的,我让我的问题更简单了......我希望现在更清楚了。我只是想推断一个函数,但我只有该函数的某些值。现在首先我需要一个函数,它可以在给定值的范围内给我合理的输出
  • 听起来您可能想应用线性回归?

标签: python numpy matplotlib extrapolation


【解决方案1】:

快速查看您的数据,

from matplotlib import pyplot as plt
from matplotlib import style
style.use('classic')

x1 = [0.632455532, 0.178885438, 0.050596443, 0.014310835, 0.004047715]
y1 = [114.75, 127.5, 139.0625, 147.9492188, 153.8085938]
plt.plot(x1, y1)

x2 = [0.707, 0.2, 0.057, 0.016, 0.00453]
y2 = [2.086, 7.525, 26.59375,87.03125, 375.9765625]
plt.plot(x2, y2)

这绝对不是线性的。如果你知道这是什么类型的函数,你可能想使用scipy's curve fitting 来获得一个你可以使用的最合适的函数。

编辑:

如果我们将绘图转换为对数对数,

import numpy as np

plt.plot(np.log(x1), np.log(y1))

plt.plot(np.log(x2), np.log(y2))

它们看起来很线性(如果你眯着眼睛看的话)。寻找最合适的线,

np.polyfit(np.log(x1), np.log(y1), 1)
# array([-0.05817402,  4.73809081])

np.polyfit(np.log(x2), np.log(y2), 1)
# array([-1.01664659,  0.36759068])

我们可以转换回函数,

# f1:
# log(y) = -0.05817402 * log(x) + 4.73809081
# so
# y = (e ** 4.73809081) * x ** (-0.05817402)
def f1(x):
    return np.e ** 4.73809081 * x ** (-0.05817402)

xs = np.linspace(0.01, 0.8, 100)
plt.plot(x1, y1, xs, f1(xs))

# f2:
# log(y) = -1.01664659 * log(x) + 0.36759068
# so
# y = (e ** 0.36759068) * x ** (-1.01664659)
def f2(x):
    return np.e ** 0.36759068 * x ** (-1.01664659)

plt.plot(x2, y2, xs, f2(xs))

第二个看起来相当不错;第一个仍然需要一些改进(即找到一个更具代表性的函数并对其进行曲线拟合)。但是你应该对这个过程有一个很好的了解;-)

【讨论】:

  • 好吧,这不是真的,你的权利。有没有办法对第一组值 (x,y) 进行线性回归?
  • 你的号码是从哪里来的?你知道他们应该遵循什么样的方程式吗? Scipy 的三次样条拟合docs.scipy.org/doc/scipy/reference/tutorial/interpolate.html 可以很好地进行插值,但对于外推来说并不那么准确(即通常很糟糕)。
  • 我同意@HughBothwell 的上述评论——最好了解这些数字的来源以及他们预期的关系类型。话虽如此,根据这些图,log-log 肯定看起来像是要走的路。
【解决方案2】:

这里有一些示例代码,希望可以帮助您开始为您的目的构建线性模型。

import numpy as np
from sklearn.linear_model import LinearRegression
from matplotlib import pyplot as plt

# sample data
x = [0.632455532, 0.178885438, 0.050596443, 0.014310835, 0.004047715]
y = [114.75, 127.5, 139.0625, 147.9492188, 153.8085938]

# linear model
lm = LinearRegression()
lm.fit(np.array(x).reshape(-1, 1), y)

test_x = np.linspace(0.01, 0.7, 100)
test_y = [lm.predict(xx) for xx in test_x]

## try linear model with log(x)
lm2 = LinearRegression()
lm2.fit(np.log(np.array(x)).reshape(-1, 1), y)

test_y2 = [lm2.predict(np.log(xx)) for xx in test_x]

# plot
plt.figure()
plt.plot(x, y, label='Given Data')
plt.plot(test_x, test_y, label='Linear Model')
plt.plot(test_x, test_y2, label='Log-Linear Model')
plt.legend()

这会产生以下内容:

正如@Hugh Bothwell 所展示的,您给出的值没有线性关系。但是,取 x 的对数似乎会产生更好的拟合。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-17
    • 2021-07-18
    • 1970-01-01
    • 1970-01-01
    • 2020-06-06
    • 1970-01-01
    • 2019-03-15
    • 2020-12-10
    相关资源
    最近更新 更多