Python 将PyMC3 traceplot子图保存到图像文件

Python 将PyMC3 traceplot子图保存到图像文件,python,matplotlib,pymc3,Python,Matplotlib,Pymc3,我试图非常简单地将PyMC3 traceplot函数(请参阅)生成的子图绘制到一个文件中 该函数生成子批的numpy.ndarray(2d) from pymc3 import * import theano.tensor as tt from theano import as_op from numpy import arange, array, empty ### Added these three lines relative to source ####################

我试图非常简单地将PyMC3 traceplot函数(请参阅)生成的子图绘制到一个文件中

该函数生成子批的numpy.ndarray(2d)

from pymc3 import *
import theano.tensor as tt
from theano import as_op
from numpy import arange, array, empty

### Added these three lines relative to source #######################
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

__all__ = ['disasters_data', 'switchpoint', 'early_mean', 'late_mean', 'rate', 'disasters']

# Time series of recorded coal mining disasters in the UK from 1851 to 1962
disasters_data = array([4, 5, 4, 0, 1, 4, 3, 4, 0, 6, 3, 3, 4, 0, 2, 6,
                        3, 3, 5, 4, 5, 3, 1, 4, 4, 1, 5, 5, 3, 4, 2, 5,
                        2, 2, 3, 4, 2, 1, 3, 2, 2, 1, 1, 1, 1, 3, 0, 0,
                        1, 0, 1, 1, 0, 0, 3, 1, 0, 3, 2, 2, 0, 1, 1, 1,
                        0, 1, 0, 1, 0, 0, 0, 2, 1, 0, 0, 0, 1, 1, 0, 2,
                        3, 3, 1, 1, 2, 1, 1, 1, 1, 2, 4, 2, 0, 0, 1, 4,
                        0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1])
years = len(disasters_data)

@as_op(itypes=[tt.lscalar, tt.dscalar, tt.dscalar], otypes=[tt.dvector])
def rateFunc(switchpoint, early_mean, late_mean):
    out = empty(years)
    out[:switchpoint] = early_mean
    out[switchpoint:] = late_mean
    return out


with Model() as model:

    # Prior for distribution of switchpoint location
    switchpoint = DiscreteUniform('switchpoint', lower=0, upper=years)
    # Priors for pre- and post-switch mean number of disasters
    early_mean = Exponential('early_mean', lam=1.)
    late_mean = Exponential('late_mean', lam=1.)

    # Allocate appropriate Poisson rates to years before and after current switchpoint location
    rate = rateFunc(switchpoint, early_mean, late_mean)

    # Data likelihood
    disasters = Poisson('disasters', rate, observed=disasters_data)

    # Initial values for stochastic nodes
    start = {'early_mean': 2., 'late_mean': 3.}

    # Use slice sampler for means
    step1 = Slice([early_mean, late_mean])
    # Use Metropolis for switchpoint, since it accomodates discrete variables
    step2 = Metropolis([switchpoint])

    # njobs>1 works only with most recent (mid August 2014) Thenao version:
    # https://github.com/Theano/Theano/pull/2021
    tr = sample(1000, tune=500, start=start, step=[step1, step2], njobs=1)

    ### gnashing of teeth starts here ################################
    fig, axarr = plt.subplots(3,2)

    # This gives a KeyError
    # axarr = traceplot(tr, axarr)

    # This finishes without error
    trarr = traceplot(tr)

    # doesn't work
    # axarr[0, 0] = trarr[0, 0]

    fig.savefig("disaster.png")
我需要将这些子图移动或复制到matplotlib.figure中以保存图像文件。我所能找到的一切都显示了如何先生成图形的子图,然后构建它们

作为一个最简单的例子,我从中提取了PyMC3代码示例,并在其中添加了几行代码,以尝试处理子批

from pymc3 import *
import theano.tensor as tt
from theano import as_op
from numpy import arange, array, empty

### Added these three lines relative to source #######################
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

__all__ = ['disasters_data', 'switchpoint', 'early_mean', 'late_mean', 'rate', 'disasters']

# Time series of recorded coal mining disasters in the UK from 1851 to 1962
disasters_data = array([4, 5, 4, 0, 1, 4, 3, 4, 0, 6, 3, 3, 4, 0, 2, 6,
                        3, 3, 5, 4, 5, 3, 1, 4, 4, 1, 5, 5, 3, 4, 2, 5,
                        2, 2, 3, 4, 2, 1, 3, 2, 2, 1, 1, 1, 1, 3, 0, 0,
                        1, 0, 1, 1, 0, 0, 3, 1, 0, 3, 2, 2, 0, 1, 1, 1,
                        0, 1, 0, 1, 0, 0, 0, 2, 1, 0, 0, 0, 1, 1, 0, 2,
                        3, 3, 1, 1, 2, 1, 1, 1, 1, 2, 4, 2, 0, 0, 1, 4,
                        0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1])
years = len(disasters_data)

@as_op(itypes=[tt.lscalar, tt.dscalar, tt.dscalar], otypes=[tt.dvector])
def rateFunc(switchpoint, early_mean, late_mean):
    out = empty(years)
    out[:switchpoint] = early_mean
    out[switchpoint:] = late_mean
    return out


with Model() as model:

    # Prior for distribution of switchpoint location
    switchpoint = DiscreteUniform('switchpoint', lower=0, upper=years)
    # Priors for pre- and post-switch mean number of disasters
    early_mean = Exponential('early_mean', lam=1.)
    late_mean = Exponential('late_mean', lam=1.)

    # Allocate appropriate Poisson rates to years before and after current switchpoint location
    rate = rateFunc(switchpoint, early_mean, late_mean)

    # Data likelihood
    disasters = Poisson('disasters', rate, observed=disasters_data)

    # Initial values for stochastic nodes
    start = {'early_mean': 2., 'late_mean': 3.}

    # Use slice sampler for means
    step1 = Slice([early_mean, late_mean])
    # Use Metropolis for switchpoint, since it accomodates discrete variables
    step2 = Metropolis([switchpoint])

    # njobs>1 works only with most recent (mid August 2014) Thenao version:
    # https://github.com/Theano/Theano/pull/2021
    tr = sample(1000, tune=500, start=start, step=[step1, step2], njobs=1)

    ### gnashing of teeth starts here ################################
    fig, axarr = plt.subplots(3,2)

    # This gives a KeyError
    # axarr = traceplot(tr, axarr)

    # This finishes without error
    trarr = traceplot(tr)

    # doesn't work
    # axarr[0, 0] = trarr[0, 0]

    fig.savefig("disaster.png")
我尝试了subplot()和add_subplot()行中的一些变体,但没有成功——所有错误都指向这样一个事实,即必须首先为图形创建空的子地块,而不是分配给预先存在的子地块

from pymc3 import *
import theano.tensor as tt
from theano import as_op
from numpy import arange, array, empty

### Added these three lines relative to source #######################
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

__all__ = ['disasters_data', 'switchpoint', 'early_mean', 'late_mean', 'rate', 'disasters']

# Time series of recorded coal mining disasters in the UK from 1851 to 1962
disasters_data = array([4, 5, 4, 0, 1, 4, 3, 4, 0, 6, 3, 3, 4, 0, 2, 6,
                        3, 3, 5, 4, 5, 3, 1, 4, 4, 1, 5, 5, 3, 4, 2, 5,
                        2, 2, 3, 4, 2, 1, 3, 2, 2, 1, 1, 1, 1, 3, 0, 0,
                        1, 0, 1, 1, 0, 0, 3, 1, 0, 3, 2, 2, 0, 1, 1, 1,
                        0, 1, 0, 1, 0, 0, 0, 2, 1, 0, 0, 0, 1, 1, 0, 2,
                        3, 3, 1, 1, 2, 1, 1, 1, 1, 2, 4, 2, 0, 0, 1, 4,
                        0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1])
years = len(disasters_data)

@as_op(itypes=[tt.lscalar, tt.dscalar, tt.dscalar], otypes=[tt.dvector])
def rateFunc(switchpoint, early_mean, late_mean):
    out = empty(years)
    out[:switchpoint] = early_mean
    out[switchpoint:] = late_mean
    return out


with Model() as model:

    # Prior for distribution of switchpoint location
    switchpoint = DiscreteUniform('switchpoint', lower=0, upper=years)
    # Priors for pre- and post-switch mean number of disasters
    early_mean = Exponential('early_mean', lam=1.)
    late_mean = Exponential('late_mean', lam=1.)

    # Allocate appropriate Poisson rates to years before and after current switchpoint location
    rate = rateFunc(switchpoint, early_mean, late_mean)

    # Data likelihood
    disasters = Poisson('disasters', rate, observed=disasters_data)

    # Initial values for stochastic nodes
    start = {'early_mean': 2., 'late_mean': 3.}

    # Use slice sampler for means
    step1 = Slice([early_mean, late_mean])
    # Use Metropolis for switchpoint, since it accomodates discrete variables
    step2 = Metropolis([switchpoint])

    # njobs>1 works only with most recent (mid August 2014) Thenao version:
    # https://github.com/Theano/Theano/pull/2021
    tr = sample(1000, tune=500, start=start, step=[step1, step2], njobs=1)

    ### gnashing of teeth starts here ################################
    fig, axarr = plt.subplots(3,2)

    # This gives a KeyError
    # axarr = traceplot(tr, axarr)

    # This finishes without error
    trarr = traceplot(tr)

    # doesn't work
    # axarr[0, 0] = trarr[0, 0]

    fig.savefig("disaster.png")
另一个例子(请参见,大约80%的情况下,从

### Mysterious code to be explained in Chapter 3.
)完全避免该实用程序,并手动构建子地块,因此可能没有好的答案?pymc3.traceplot输出是否确实是无法使用的孤立子批数据阵列?

您能否打印
类型(trarr[0,0])
并发布结果

首先,matplotlib轴对象是图形的一部分,只能存在于图形内部。因此,不可能简单地获取一个轴并将其放置到另一个图形中。但是,在您的情况下,可能是,
fig.add_轴(trarr[0,0])
仍然有效。我怀疑,但你还是可以试试

除此之外,还有一个名为
ax
的关键字参数

斧头:斧头 Matplotlib轴。默认为“无”

虽然还不清楚如何将多个子地块指定为一个Axis对象,但您仍然可以尝试使用它。尝试将单个轴放入或您自己创建的子地块轴数组
axarr
中,或仅放入其中的一部分

编辑,只是没有人监督评论中的一小行:

根据traceplot(tr,ax=axarr)中的答案,确实报告说工作正常。

我遇到了同样的问题。我正在使用
pymc3
3.5和
matplotlib
2.1.2

我意识到可以通过以下方式导出traceplot:

trarr = traceplot(tr)

fig = plt.gcf() # to get the current figure...
fig.savefig("disaster.png") # and save it directly

谢谢你的评论。
类型(trarr[0,0])
为。我尝试了
fig.add_axes(…)
建议,得到了与之前类似的错误——轴需要已经存在于fig中。我还尝试了将预先构建的子地块的numpy.ndarray输入traceplot函数,编辑:如果一个人记得对参数
traceplot(tr,ax=axarr)
使用keywork,它就可以正常工作。