Python 如何加速dict的构造,该dict的值是按条件填充的?
我需要建立一个新的字典,它的值是有条件地填充的。我的问题是;我需要搜索数百万个项目才能做到这一点。下面是我尝试用少量的信息来做这件事,但在实践中,我需要用数百倍于其大小的东西来做同样的事情,这将需要几个小时Python 如何加速dict的构造,该dict的值是按条件填充的?,python,dictionary,Python,Dictionary,我需要建立一个新的字典,它的值是有条件地填充的。我的问题是;我需要搜索数百万个项目才能做到这一点。下面是我尝试用少量的信息来做这件事,但在实践中,我需要用数百倍于其大小的东西来做同样的事情,这将需要几个小时 import torch, copy import numpy as np # initialize model class mlp1(torch.nn.Module): def __init__(self, num_features, num_hidden, num_classe
import torch, copy
import numpy as np
# initialize model
class mlp1(torch.nn.Module):
def __init__(self, num_features, num_hidden, num_classes):
super(mlp1, self).__init__()
self.num_classes = num_classes
self.input_layer = torch.nn.Linear(num_features, num_hidden)
self.out_layer = torch.nn.Linear(num_hidden, num_classes)
def forward(self, x):
x = self.input_layer(x)
x = torch.sigmoid(x)
logits = self.out_layer(x)
probas = torch.softmax(logits, dim=1)
return logits, probas
# instantiate model
model = mlp1(num_features=28*28, num_hidden=100, num_classes=10)
# initial params
initial_dict = copy.deepcopy(model.state_dict())
# trained params
trained_dict = copy.deepcopy(model.state_dict()) # pretend its different
# masks
mask = {
name: torch.tensor(np.random.choice([False, True],
size=torch.numel(weight),
p=[0.5, 0.5]).reshape(weight.shape))
for name, weight in initial_dict.items()
}
# create a new model state
#### how to improve this ####
result = {}
# for each key
for key in initial_dict.keys():
# if key is not in the new dict
if key not in result:
# add it
result[key] = []
# get current shape to reshape later
current_shape = initial_dict[key].shape
# for each value in each dict
for v1, v2, v3 in zip(initial_dict[key], trained_dict[key], mask[key]):
# if multidimensional
if len(v1.shape) >= 1:
# loop again
for vv1, vv2, vv3 in zip(v1, v2, v3):
# if mask condition is met
if vv3.item() == True:
# append trained dict values
result[key].append(vv2.item())
# other wise
else:
# append initial dict values
result[key].append(vv1.item())
# else if not multidimensional
elif len(v1.shape) <= 1:
# if mask condition is met
if v3.item() == True:
# if do the same as bove
result[key].append(vv2.item())
else:
result[key].append(vv1.item())
# turn key to tensor
result[key] = torch.as_tensor(result[key])
# reshape
result[key] = result[key].reshape(current_shape)
#### how to improve this ####
编辑2:
解决方法是使用矢量化操作,我想这应该是已知的。一些提高性能的技巧: 结果字典具有基于初始字典键的键。当您解包初始字典键(它们是唯一的)时,保证不会看到同一个键两次。因此,如果钥匙不在检查中,您可以保存自己的
将键和值一起解包,而不是使用键然后查找值
for key, value in initial_dict.items():
print(key, value)
使用字典理解(用于下面的优化C代码),而不是制作一个空字典并添加到其中
e、 g
initial={a:10,“b:11}
double={k:v*2表示k,v在initial.items()中为v}
#{a:20,“b:22}
为了使用字典理解,您需要将多行逻辑封装到一个函数中并调用该函数。这对提高代码的可读性和可重用性都有好处
def过程(初始值、训练值、掩码值):
形状=初始值。形状
输出=[]
#你的逻辑。。。
output.append(1)
output.append(2)
返回输出
结果_dict={k:k初始_dict.items()中k,v的过程(v,经过训练的_dict[v],掩码[v])
你对多维数组使用嵌套循环听起来也是一个可以优化的领域。你能用一次迭代来代替嵌套吗?你能用字典或列表理解来至少提高当前逻辑的速度吗
风格评论:
对于Python样式,当涉及到布尔值时,使用is True
而不是==True
你的v2和vv2等变量是模糊的。它们需要合适的名称。这样你就不必评论这是经过训练的或初始的
另外,您的if和elif语句只有两个分支,其中一个分支保证会被命中,因此可以将其设置为just if和else。非常感谢这篇超详细的文章。我认为我没有击中目标,因为我所做的工作产生了基本相同的运行时间,从快速的%timeit判断。我添加了我对fn所做的工作如果你能继续帮助我更好地改进这个过程,请在上面编辑。代码看起来好多了。每一秒的注释都没有什么意义,实际上使代码更难阅读。我很失望你没有看到速度的提高。也许你可以使用np数组而不是输出列表?Numpy和Pandas一直很麻烦y在C级进行了优化,也有很多方法可以使相同的任务在C级完成,并获得不同的速度。我还建议使用库或IDE工具进行Python评测。这将告诉您逻辑的哪个部分计算时间最长,然后您可以对其进行优化。您的输入数据有多大?也许几个小时是合理的您可以将其作为一项长期运行的任务。您可以通过在云中的增强硬件上运行它,甚至将数据拆分为多个部分,并在多台机器上并行处理来加速它。您甚至可以在本地尝试。使用Python库的多核处理在单个脚本中很难实现。但是,也许你可以在4个终端窗口中开始编写脚本,使用4个内核(你需要研究如何确保每次使用不同的内核),然后通过并行处理,速度将提高4倍。当然,你必须在它们之间拆分输入数据,并重新组合4个输出数据。
for key, value in initial_dict.items():
print(key, value)