【发布时间】:2022-01-12 20:39:38
【问题描述】:
我正在生成一个 Erdos-Renyi 网络并计算其度数分布。我知道它接近Poisson distribution,所以我想将我的经验分布拟合到理论分布。为了确定理论分布的参数,我使用来自 SciPy 的 differential evolution 最小二乘法。这是我的代码:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import networkx as nx
from scipy.stats import poisson, expon
from scipy.optimize import curve_fit, differential_evolution
from numpy.polynomial import Polynomial
from scipy.integrate import quad
from functools import partial
def get_deg_distribution(G):
deg_sequence = sorted([deg for _, deg in G.degree()], reverse=True)
deg_distribution = pd.DataFrame(np.column_stack(np.unique(deg_sequence, return_counts=True)),
columns=['Degree', 'Count'])
deg_distribution['Probability'] = deg_distribution['Count'] / deg_distribution['Count'].sum()
deg_span = np.arange(deg_distribution['Degree'].min(), deg_distribution['Degree'].max() + 1)
missing_degs = list(set(deg_span) - set(deg_distribution['Degree']))
add_df = pd.DataFrame(0.0, index=missing_degs, columns=['Count', 'Probability']).reset_index()
add_df.columns = deg_distribution.columns
deg_distribution = pd.concat([deg_distribution, add_df]).sort_values('Degree').reset_index(drop=True)
return deg_distribution
G = nx.erdos_renyi_graph(2500, 0.025, seed=42)
dist = get_deg_distribution(G)
xdata = list(dist['Degree'])
ydata = list(dist['Probability'])
def func(k, mu, loc):
return poisson.pmf(k, mu, loc)
def param_func(params, ydata):
return np.linalg.norm(partial(func, xdata)(*params) - ydata)**2
bounds = [(0, 100), (-5, 5)]
params_found = differential_evolution(param_func, bounds=bounds, args=(ydata,))['x']
这段代码有几个谜团。首先,不同的差分进化运行会产生不同的参数集。这本身不是问题,因为确实可能存在许多全局最小值。但是,这些参数集中的 func(xdata, *params) 总是产生零,就好像该方法正在最小化 func 本身而不是其平方误差 参数函数。第三,所有这些参数集的 param_func 值正好是 0.03708384。这是一个问题 - 这不是全球最低限度!只需采用 (65, 0) 参数集,它会给你合理的分布近似值,如果你检查图,误差实际上是 0.002 左右。我之前在其他函数上运行过管道本身,试试这样的:
def func(x, a, b):
return a*x**2 + b
xdata = np.linspace(0, 10, 11)
ydata = func(xdata, 1, 5)
def param_func(params, ydata):
return np.linalg.norm(partial(func, xdata)(*params) - ydata)**2
bounds = [(-20, 20), (-20, 20)]
params_found = differential_evolution(param_func, bounds=bounds, args=(ydata,))['x']
它工作得很好,但在这个特定的情况下它完全失败了,我不知道为什么。
【问题讨论】:
标签: python optimization scipy networkx