符合幂律

数据挖掘 Python 回归
2022-02-09 20:43:33

我经常遇到我假设来自移动幂律的数据,

y(x)=Axk+B.

我在这里想到了来自未知确定性函数的样本,但是如果您愿意,可以考虑概率分布。

使用 Python 拟合此类数据的最佳方法是什么?这种转变意味着在对数空间中拟合一条直线不起作用。

理想情况下,我更喜欢比直接使用最小二乘法更方便的方法,但如果这是最好的方法,那就是它。在那种情况下,特定的算法是否特别有用?

1个回答

我只想在 pytorch 中拼出 y(x) 并使用带有平方损失的 autograd 以及 A、B 和 k 上的内置梯度下降算法之一。不幸的是,我不知道任何巧妙的技巧可以以非常简单的方式做到这一点,如果那是你所追求的。我试了一下,代码如下

import torch
from torch.nn.functional import mse_loss
from collections import namedtuple
from itertools import count
from random import gauss, seed
seed(49)

# Our model
def f(x, A, B, k):
    return A*(x**k)+B

# Generate sample data
A = gauss(0, 10)
B = gauss(0, 10)
k = gauss(0, 10)
x = torch.arange(1, 10, dtype=torch.float)
y = f(x, A, B, k)
print(f"A={A}, B={B}, k={k}")
print(x)
print(y)

# Define the parameters
Params = namedtuple("Params", "A B k")

params = Params(A=torch.tensor([1.0], requires_grad=True),
                B=torch.tensor([1.0], requires_grad=True),
                k=torch.tensor([1.0], requires_grad=True))

# Fit the parameters
optimizer = torch.optim.Adam(params, lr=1)

tol = 1e-6 # MSE Loss error tolerance
for i in count():
    optimizer.zero_grad()
    y_hat = f(x, params.A, params.B, params.k)
    # Take the logarithm for improved numerical stability
    L = mse_loss(torch.log(y_hat), torch.log(y))
    if L < tol:
        break
    if i % 1000 == 0:
        print(f"Loss ({i}): {L.item()}")
    L.backward()
    optimizer.step()

print(params.A.item(), A)
print(params.B.item(), B)
print(params.k.item(), k)

输出:

A=9.42764034916727, B=4.212889473371394, k=12.835248103593624
tensor([1., 2., 3., 4., 5., 6., 7., 8., 9.])
tensor([1.3641e+01, 6.8901e+04, 1.2542e+07, 5.0349e+08, 8.8279e+09, 9.1657e+10,
        6.6290e+11, 3.6795e+12, 1.6686e+13])
Loss (0): 421.6722717285156
Loss (1000): 0.0005562781007029116
Loss (2000): 9.59674798650667e-06
9.461631774902344 9.42764034916727
4.17124080657959 4.212889473371394
12.833184242248535 12.835248103593624
```