优化仿真

Optimise simulation

我有一个使用 pandas 的模拟,模拟随机骰子的投掷 12 次(这是一次试验),然后存储成功的概率。

我计算任何给定 n 次试验成功概率的代码由 def Simulation(n) 给出:

import numpy as np
import pandas as pd

def Simulation(n):
    """Python function to simulate n rolls of 6-sided die and estimate probability of all faces appearing at least once"""
    if n <= 0: print("Enter a positive integer for number of simulations!")

    # Create an datafrane of results of die throw for n simulations and 12 trials
    rand_int = np.random.randint(1, 7, size=(n, 12))
    randint_df = pd.DataFrame(rand_int)

    # Add column of success (True) and failure (False to dataframe

    # All possible values of trial
    list = [1, 2, 3, 4, 5, 6]

    # Count # of trial outcomes=True/Success
    success = randint_df.apply(lambda row: len(np.setdiff1d(list, row)) == 0, axis=1)
    randint_df['Success'] = success

    # Determine probability of Success
    number_success = randint_df.Success.sum()
    probability = number_success / (n * 12)

    return probability

接下来我实现 Simulation(n) 迭代 range(0,100,5) 中的一系列系列,以获得不同的 n 值并将结果存储在数据帧中:

"""Python code to graph probability of success for 6-sided die roll 12-times"""
import numpy as np
import pandas as pd
import sim_func
import matplotlib.pyplot as plt

#Calculate probability for series simulations & series

#Create datatframe for results
result = pd.DataFrame(columns=['Series','Simulation','Probability'])

for series in range(0,100,5):
    for n in range(100,100000,10):
        prob=sim_func.Simulation(n)
        #Create new dataframe of series number & probability of success
        df_new_row=pd.DataFrame({'Series':series,'Simulation':n,'Probability':prob},index=[0])
        result=pd.concat([result,df_new_row],axis=0,ignore_index=True)

result.index.name = "Index"

#Plot changing probability for each series vs number of simulations
result.pivot_table(index='Simulation',columns='Series',values='Probability').plot()

# set y label
plt.ylabel('Probability of Success')
# set y label
plt.xlabel('Number Simulations (n)')
# set title
plt.title('Probability vs Simulations (n) for changing number of Series')

plt.show()

模拟一直持续到 运行,我不完全确定原因。我觉得为每个 n 添加概率结果是低效的,而且速度很慢,但我不知道如何优化。

如有任何见解,我们将不胜感激。

使用 pandas 数据框来 运行 模拟并存储不同 n 次试验的结果。然后将结果绘制成图表。

这是我认为会对您有所帮助的谦虚 re-work。关于代码和速度需要指出的几件事。

  1. 不要使用关键字作为变量名...您使用 list 作为 list。这会让你很头疼。

  2. 您有点不符合您对“试用”的定义。我认为你的意图是 1 次试验是 p{roll 6 faces of 6 sided die in 12 rolls}。意识到这是一个固定值,做更多的试验只会提高对这个固定值的估计。注意:我得到了不同的结果,因为你除以 12 ??

  3. 关于速度....您可以简化您的模拟功能,只需要即时查看每个试验。这是相当快的,如果你尝试 super-huge 次试验,你可以避免使用大内存块。避免在此处制作数据框,如果您正在进行大量试验,制作它会“成本高昂”。我想你也可以在 12 x N numpy 数组上非常有效地做一些直接数学运算 而无需 数据框。在您的主代码中,您真的 想要避免将行单独连接到数据框。它非常 慢。像我展示的那样用记录“一次完成”是可行的方法。

  4. 探索大space。我建议使用幂级数,否则您的结果会非常庞大​​。 [1, 10, 100, 1000, 10000, ...] 你真的需要从十数到 100,000 吗?我用的是2^n的幂级数,但是有很多选项或者分数幂等可以用。

如果您对“试用”有不同的看法,您应该能够很容易地修改此代码以适应。

代码

"""Python code to graph probability of success for 6-sided die roll 12-times"""
import numpy as np
import pandas as pd
# import sim_func
import matplotlib.pyplot as plt

# calculate the prob of rolling all 6 faces of 6-sided die in rolls=rolls
def sim2(trials, rolls=12):
    successes = 0
    for t in range(trials):
        # we have all 6 values if set size is 6
        if len(set(np.random.randint(1, 7, rolls))) == 6:  
            successes += 1
    return successes/trials


# hold the results in a list
result = []  

for series in 'ABCDE':
    # a power series is good for exploring a large range of values...
    for n in [2**p for p in range(12)]:
        prob=sim_func.sim2(n)
        # create a record of the result
        res = {'Series': series, 'Trials': n, 'P': prob}
        result.append(res)

# assemble the dataframe "all at once" rather than a bazillion concats
result = pd.DataFrame.from_records(result)

#Plot changing probability for each series vs number of simulations
result.pivot_table(index='Trials',columns='Series',values='P').plot()

# set y label
plt.ylabel('Probability of Success')
# set y label
plt.xlabel('Number Simulations (n)')
# set title
plt.title('Probability vs Simulations (n) for changing number of Series')

plt.show()

输出