Подгонка прямой линии к логарифмической кривой в matplotlib

У меня есть график, логарифмический по обеим осям. Для этого у меня есть функция loglog pyplot. Это также дает мне логарифмическую шкалу по обеим осям.

Теперь, используя 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()

person Rohit Shinde    schedule 05.06.2015    source источник
comment
Разве это не просто то, что вы строите прямую линию в логарифмическом масштабе?   -  person Andrzej Pronobis    schedule 05.06.2015
comment
Да, это так. Но как мне построить его с помощью matplotlib, чтобы он идеально покрывал линию?   -  person Rohit Shinde    schedule 05.06.2015


Ответы (3)


Ваша линейная подгонка не выполняется на тех же данных, что и на логарифмическом графике.

Создайте массивы a и b numpy, подобные этому

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

Теперь вы можете выполнять над ними операции. Что делает loglog-plot, так это логарифмирование по основанию 10 как a, так и b. Вы можете сделать то же самое,

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)
person trueter    schedule 05.06.2015
comment
должен ys = polynomial(logB) ? - person Brandon Dube; 23.04.2018

Чтобы лучше понять эту проблему, давайте сначала поговорим о простой линейной регрессии (функция 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. Алгоритму линейной регрессии все равно, что y и x на самом деле являются log(F) и log(R) - это не имеет значения для алгоритма.

Последний шаг немного отличается — и именно здесь вы спотыкаетесь на своем графике выше. То, что вы делаете, это вычисление

F = m R + b

но это неверно, потому что связь между F и R не является линейной. (Вот почему вы используете логарифмический график.)

Вместо этого вы должны вычислить

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

Если вы преобразуете это (возведите 10 в степень обеих сторон и переставьте), вы получите

F = c R^m

где c = 10^b. Это отношение между F и R: это отношение степенного закона. (Степенные отношения — это то, для чего лучше всего подходят логарифмические графики.)

В вашем коде вы используете A и B при вызове polyfit, но вы должны использовать log(A) и log(B).

person charlesreid1    schedule 05.06.2015

Другие ответы предлагают отличные объяснения и решение. Однако я хотел бы предложить решение, которое очень помогло мне и, возможно, поможет и вам.

Еще один простой способ записи строки, подходящей для логарифмического масштаба, — это функция powerfit в приведенном ниже коде. Он принимает исходные данные x и y, и, используя ряд новых точек x, вы можете получить прямую линию в логарифмическом масштабе. В данном случае значения xnew такие же, как x (которые оба равны 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()
person BarendB    schedule 20.06.2018