numpy 将直线拟合到双对数曲线

h43kikqp  于 2023-10-19  发布在  其他
关注(0)|答案(3)|浏览(138)

我有一个图表,在两个坐标轴上都是对数的。我有pyplot的loglog函数来做这件事。它也给出了两个坐标轴上的对数标度。
现在,使用numpy,我将一条直线拟合到我所拥有的点集。然而,当我在图上绘制这条线时,我不能得到一条直线。我得到一条曲线。

蓝线是所谓的“直线”。它没有被直接绘制出来。我想把这条直线和红点画出的曲线拟合起来
下面是我用来绘制点的代码:

import numpy
from matplotlib import pyplot as plt
import math
fp=open("word-rank.txt","r")
a=[]
b=[]

for line in fp:
    string=line.strip().split()
    a.append(float(string[0]))
    b.append(float(string[1]))

coefficients=numpy.polyfit(b,a,1)
polynomial=numpy.poly1d(coefficients)
ys=polynomial(b)
print polynomial
plt.loglog(b,a,'ro')
plt.plot(b,ys)
plt.xlabel("Log (Rank of frequency)")
plt.ylabel("Log (Frequency)")
plt.title("Frequency vs frequency rank for words")
plt.show()
k97glaaz

k97glaaz1#

为了更好地理解这个问题,让我们首先讨论一下简单的线性回归(在本例中,polyfit函数是您的线性回归算法)。
假设你有一组数据点(x,y),如下所示:

您希望创建一个模型,将y预测为x的函数,因此使用线性回归。它使用模型:
y = mx + b
并使用一些线性代数计算最能预测数据的mb的值。
接下来,使用模型预测作为x函数的y值。你可以通过为x选择一组值(想想linspace)并计算相应的y值来实现。绘制这些(x,y)对可以得到回归线。
现在,让我们来谈谈对数回归。在这种情况下,我们仍然有两个变量,y和x,我们仍然对它们的关系感兴趣,即能够预测x。唯一的区别是,现在yx恰好是另外两个变量的数组,我称之为log(F)log(R)。到目前为止,这只不过是一个简单的名称更改。

线性回归也以同样的方式工作。你仍然在回归y对x。线性回归算法不关心yx实际上是log(F)log(R)-这对算法没有区别。
最后一步有点不同-这就是你在上面的情节中被绊倒的地方。你所做的是计算
F = m R + b
但这是不正确的,因为FR之间的关系不是线性的。(这就是为什么你使用双对数图。
相反,您应该计算
log(F) = m log(R) + b
如果你变换这个(两边的10次方再重新排列),你会得到
F = c R^m
其中c = 10^b.这是FR之间的关系:是一种幂律关系。(幂律关系是对数-对数图最擅长的。
在代码中,调用polyfit时使用A和B,但应该使用log(A)log(B)

n7taea2i

n7taea2i2#

您的线性拟合不是对双对数图中显示的相同数据执行的。
像这样创建a和B numpy数组

a = numpy.asarray(a, dtype=float)
b = numpy.asarray(b, dtype=float)

现在您可以对它们执行操作。双对数图的作用是对a和b取以10为底的对数。你也可以这样做,

logA = numpy.log10(a)
logB = numpy.log10(b)

这就是双对数图的可视化效果。通过将logA和logB绘制为常规图来检查这一点。对log数据重复线性拟合,并在与logA,logB数据相同的图中绘制直线。

coefficients = numpy.polyfit(logB, logA, 1)
polynomial = numpy.poly1d(coefficients)
ys = polynomial(b)
plt.plot(logB, logA)
plt.plot(b, ys)
zqdjd7g9

zqdjd7g93#

其他答案提供了很好的解释和解决方案。不过,我想提出一个解决方案,帮助自己很多,也许会帮助你。
另一种简单的写双对数刻度线的方法是下面代码中的函数powerfit。它接受原始的xy数据,并通过使用一些新的x点,您可以在双对数尺度上获得一条直线。在当前情况下,值xnewx相同(都是b)。
定义新的x坐标的优点是,您可以获得幂拟合线的尽可能少或尽可能多的点,以满足您可能需要它们的任何目的。

import numpy as np
from matplotlib import pyplot as plt
import math

def powerfit(x, y, xnew):
    """line fitting on log-log scale"""
    k, m = np.polyfit(np.log(x), np.log(y), 1)
    return np.exp(m) * xnew**(k)

fp=open("word-rank.txt","r")
a=[]
b=[]

for line in fp:
    string=line.strip().split()
    a.append(float(string[0]))
    b.append(float(string[1]))

ys = powerfit(b, a, b)

plt.loglog(b,a,'ro')
plt.plot(b,ys)
plt.xlabel("Log (Rank of frequency)")
plt.ylabel("Log (Frequency)")
plt.title("Frequency vs frequency rank for words")
plt.show()

相关问题