当前位置: 代码迷 >> python >> 对于这个特定任务,字典或元组列表会更有效吗?
  详细解决方案

对于这个特定任务,字典或元组列表会更有效吗?

热度:104   发布时间:2023-07-14 08:43:06.0

我编写了一个脚本,其目的是通过反复试验找到最适合函数的参数(Markov Chain Monte Carlo)。 参数的生存能力由chi值决定-chi越低越好。

以下是我当前编写的代码部分:

chi1 = fun_chi(B1,G1,C11,C21,C31,C41,C01)
BGCchilist = []
count = -1

for i in range(iteration_MCMC):
    count = count + 1
    print(count)
    B2,G2,C12,C22,C32,C42,C02 = gen_param(B1,G1,C11,C21,C31,C41,C01)
    chi2 = fun_chi(B2,G2,C12,C22,C32,C42,C02)
    ratio = np.exp((-chi2 + chi1) / 2)
    rand = np.random.uniform(0,1)
    if rand < ratio:
        B1 = B2
        G1 = G2
        C11 = C12
        C21 = C22
        C31 = C32
        C41 = C42
        C01 = C02
        chi1 = chi2
    ##save the data
    Bsave = B1
    Gsave = G1
    C1save = C11
    C2save = C21
    C3save = C31
    C4save = C41
    C0save = C01
    chisave = chi1
    BGCchilist.append((Bsave,Gsave,C1save,C2save,C3save,C4save,C0save,chisave))

Blist = [x[0] for x in BGCchilist]
Glist = [x[1] for x in BGCchilist]
C1list = [x[2] for x in BGCchilist]
C2list = [x[3] for x in BGCchilist]
C3list = [x[4] for x in BGCchilist]
C4list = [x[5] for x in BGCchilist]
C0list = [x[6] for x in BGCchilist]
chilist = [x[7] for x in BGCchilist]
minchi = min(x[7] for x in BGCchilist)
mintuple = [x for x in BGCchilist if x[7] == minchi]

我最终通过Matplotlib单独绘制了所有这些列表和迭代图,然后将mintuple保存为文本文件。

一位同事看了看这一点,并告诉我,也许我会更好地使用字典,在每次迭代我做这样的事情担任a_dictionary[chisave] = (B,G,...C0)然后找到mintuple通过在字典中寻找最小值。 但是,似乎从字典中的值元组中提取列表进行绘图似乎更加麻烦并且需要更多步骤。

字典方法会减少步骤,提高效率,还是所有列表按原样行事?

谢谢您的帮助。

这是根据评论做出的答案。 我以为是关于效率的问题,但经过仔细研究,它看起来像是关于如何清理代码的问题。 如果那是授予者,那么以下内容可能会有用:

对于第一部分,我们只是将所有内容保留为元组,并像这样使用inlace扩展...

par1 = B1,G1,C11,C21,C31,C41,C01
chi1 = fun_chi(*par1)
BGCchilist = []

for i in range(iteration_MCMC):

    print (i-1)

    par2  = gen_param(*par1)
    chi2  = fun_chi(*par2)
    ratio = np.exp((-chi2 + chi1) / 2)
    rand  = np.random.uniform(0,1)
    if rand < ratio: par1 = par2
    BGCchilist.append(list(par1) + [chi1]) ##save the data

这是逐字逻辑副本。 但是,我看不到chi1在for循环中被更新。 我猜您也希望这种情况发生吗? 像这样:

par1 = B1,G1,C11,C21,C31,C41,C01
BGCchilist = []

for i in range(iteration_MCMC):

    print (i-1)

    chi1  = fun_chi(*par1) # This is the change
    par2  = gen_param(*par1)
    chi2  = fun_chi(*par2)

    if np.random.uniform(0,1) < np.exp((-chi2 + chi1) / 2): par1 = par2

    BGCchilist.append(list(par1) + [chi1]) ##save the data

我不确定算法,因此无法就此发表明确的评论。

下一部分更有趣。

Blist    = [x[0] for x in BGCchilist]
Glist    = [x[1] for x in BGCchilist]
C1list   = [x[2] for x in BGCchilist]
C2list   = [x[3] for x in BGCchilist]
C3list   = [x[4] for x in BGCchilist]
C0list   = [x[6] for x in BGCchilist]
C4list   = [x[5] for x in BGCchilist]
chilist  = [x[7] for x in BGCchilist]

可以简单地替换为:

BList,  GList,           \
C1List, C2List, C3List   \
C0List, C4List, chilist  = zip(*BGCchilist)

我认为这就是它的作用。 请单独检查此部分。

最后,您真的需要所有列表吗? 还是只需要chiList

我想剩下的应该很容易吗? 你所拥有的还可以。 检查min功能中的key参数。 因此,如果您出于某种原因不想要所有列表,则可以跳过该部分并在for循环中找到最小值,或者可以执行以下操作:

minChi     = min( zip(*BGCchilist)[-1] )
allMinChis = filter( lambda m: m[7] == minChi, BGCchilist)

Cheeers!

注意:我尚未测试代码,因此可能存在错误。 请检查代码,并确保这就是您想要的。

dict将减少步骤,并且也更易于阅读。 使用minchi作为键:

BGCchilist = {}

# in the loop

    BGCchilist[chisave] = [Bsave, Gsave, C1save,C2save,C3save,C4save,C0save,chisave]

# out of the loop

minchi = min(BGCchilist.keys())
mintuple = BGCchilist[minchi]

如果需要保存导致相同chi值的参数的每种组合,请更改dict以保留每个键的元组列表,而不只是列表:

from collections import defaultdict

BGCchilist = defaultdict(list)

...

    BGCchilist[chisave].append([...all the saves...])

...

minchi = min(BGCchilist.keys())
mintuples = BGCchilist[minchi]
# at this point mintuples has at least one tuple of params that got
# this chi score, maybe more

更新:

好的,这是我对您的要求的理解:

  • 您需要保存参数的每个组合以及所得的得分
  • 完成后您需要获得最低的得分
  • 完成后,您需要每个输入参数的列表以及chi分数

我将为此使用一个简单的类。 它可能不会少于几行,但可读性会更高:

# lightly tested
class BGCChiData(object):  # (object) not needed in Python3
    def __init__(self):
        self.data = defaultdict(list)
    def __getitem__(self, chi):
        return self.data[chi]
    def __setitem__(self, chi, params):
        self.data[chi].append(params)
    @property
    def min_chi(self):
        return min(self.data.keys())
    @property
    def B(self):
        return [tup[0] for val in self.data.values() for tup in val]
    @property
    def G(self):
        return [tup[1] for val in self.data.values() for tup in val]
    @property
    def C1(self):
        return [tup[2] for val in self.data.values() for tup in val]
    @property
    def C2(self):
        return [tup[3] for val in self.data.values() for tup in val]
    @property
    def C3(self):
        return [tup[4] for val in self.data.values() for tup in val]
    @property
    def C4(self):
        return [tup[5] for val in self.data.values() for tup in val]
    @property
    def C0(self):
        return [tup[6] for val in self.data.values() for tup in val]
    @property
    def chi(self):
        return [tup[7] for val in self.data.values() for tup in val]

chi1 = fun_chi(B1,G1,C11,C21,C31,C41,C01)
BGCchi = BGCChiData()

for count in range(iteration_MCMC):
    print(count)
    B2,G2,C12,C22,C32,C42,C02 = gen_param(B1,G1,C11,C21,C31,C41,C01)
    chi2 = fun_chi(B2,G2,C12,C22,C32,C42,C02)
    ratio = np.exp((-chi2 + chi1) / 2)
    rand = np.random.uniform(0,1)
    if rand < ratio:
        B1 = B2
        G1 = G2
        C11 = C12
        C21 = C22
        C31 = C32
        C41 = C42
        C01 = C02
        chi1 = chi2
    ##save the data
    BGCchi[chi1].append(B1, G1, C11, C21, C31, C41, C01)

minchi = BGCchi.min_chi
mintuple = BGCchi[minchi]
B1list = BGCchi.B
# etc. etc.
  相关解决方案