5

我有一个图,它在两个轴上都是对数的。我有 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()
4

3 回答 3

7

为了更好地理解这个问题,让我们先谈谈普通的线性回归(polyfit在这种情况下,函数就是你的线性回归算法)。


假设您有一组数据点 (x,y),如下所示:

线性回归图

您想创建一个预测y为 的函数的模型x,因此您使用线性回归。使用模型:

y = mx + b

并使用一些线性代数计算最能预测您的数据的m和的值。b

接下来,您使用您的模型将 y 的值预测为 x 的函数。您可以通过为 x 选择一组值(想想 linspace)并计算 y 的相应值来做到这一点。绘制这些 (x,y) 对可以为您提供回归线。


现在,让我们谈谈对数回归。在这种情况下,我们仍然有两个变量,y 与 x,我们仍然对它们的关系感兴趣,即能够预测y给定x的 。唯一的区别是,现在y恰好x是另外两个变量的对数,我将它们称为log(F)log(R)。到目前为止,这只不过是一个简单的名称更改。

对数回归图

线性回归也以同样的方式工作。你仍然在回归 y 与 x。线性回归算法并不关心这一点yx实际上是log(F)-log(R)它对算法没有任何影响。

最后一步有点不同——这就是你在上面的情节中被绊倒的地方。你正在做的是计算

F = m R + b

但这是不正确的,因为和之间的关系F不是R线性的。(这就是您使用对数图的原因。)

相反,您应该计算

log(F) = m log(R) + b

如果你改变它(将 10 提高到双方的幂并重新排列),你会得到

F = c R^m

哪里c = 10^bF这是和之间的关系R:它是幂律关系。(幂律关系是对数图最擅长的。)

在您的代码中,您在调用时使用 A 和 B polyfit,但您应该使用log(A)and log(B)

于 2015-06-05T17:29:56.567 回答
5

您的线性拟合未在对数图中显示的相同数据上执行。

像这样制作 a 和 b numpy 数组

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

现在您可以对它们执行操作。loglog-plot 的作用是将 a 和 b 的以 10 为底的对数。你可以这样做

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

这就是 loglog 图可视化的内容。通过将 logA 和 logB 绘制为常规图来检查这一点。对日志数据重复线性拟合,并将您的线绘制在与 logA、logB 数据相同的图中。

coefficients = numpy.polyfit(logB, logA, 1)
polynomial = numpy.poly1d(coefficients)
ys = polynomial(b)
plt.plot(logB, logA)
plt.plot(b, ys)
于 2015-06-05T16:04:01.173 回答
2

其他答案提供了很好的解释和解决方案。但是,我想提出一个对自己有很大帮助的解决方案,也许也会对您有所帮助。

另一种编写对数刻度线拟合的简单方法是powerfit下面代码中的函数。它接收原始数据xy数据,通过使用许多新的 x 点,您可以获得对数刻度上的直线。在当前情况下,值xnewx(两者都是b)相同。

定义新的 x 坐标的优点是,无论出于何种目的,您都可以获得尽可能少或尽可能多的 powerfitted 线点。

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()
于 2018-06-20T08:50:47.560 回答