生成器对象列表的计算平均值
Computing mean of list of generator objects
// Initialize 2-D array, each entry is some neural network
phi = [[None] * n for _ in range(m)]
for i in range(m):
for j in range(n):
phi[i][j] = NeuralNetwork()
// Let k, i be arbitrary indices
p1 = torch.nn.utils.parameters_to_vector(phi[k][i - 1].parameters())
p2 = torch.nn.utils.parameters_to_vector(mean of phi[:][i-1])
我想基本上计算参数 phi[k][i-1]
和整个列的平均值 phi[:][i-1]
之间的均方误差,即 ((p1 - p2)**2).sum()
我尝试了以下方式:
tmp = [x.parameters() for x in self.phi[:][i - 1]]
mean_params = torch.mean(torch.stack(tmp), dim=0)
p2 = torch.nn.utils.parameters_to_vector(mean_params)
但这行不通,因为 tmp 是生成器对象的列表。更具体地说,我想我的问题是计算生成器对象的平均值。
首先,我们可以定义一个函数来计算模型列表的平均参数。为了避免同时创建每个模型的参数副本,我们可能希望将其计算为 运行 总和。例如
def average_parameters_vector(model_list):
n = len(model_list)
avg = 0
for model in model_list:
avg = avg + torch.nn.utils.parameters_to_vector(model.parameters()) / n
return avg
然后您可以创建 p1
和 p2
并计算 mean-squared 错误
p1 = torch.nn.utils.parameters_to_vector(phi[k][i - 1].parameters())
p2 = average_parameters_vector(phi[:][i - 1])
mse = ((p1 - p2)**2).mean()
如果你真的想要一个 one-line 解决方案,它也可能是最快的,你可以通过制作一个包含 phi[:][i - 1]
中模型的所有参数的单个张量来计算它,然后意味着减少它们。但如前所述,这将显着增加内存使用量,尤其是当您的模型通常有数百万个参数时。
# Uses lots of memory but potentially the fastest solution
def average_parameters_vector(model_list):
return torch.stack([torch.nn.utils.parameters_to_vector(model.parameters()) for model in model_list]).mean(dim=0)
另一方面,如果您非常关心内存使用情况,那么您可以一次计算每个单独参数的平均值。
# more memory efficient than original solution but probably slower
def average_parameters_vector(model_list):
n = len(model_list)
num_params = len(list(model_list[0].parameters()))
averages = [0] * num_params
for model in model_list:
for pidx, p in enumerate(model.parameters()):
averages[pidx] = averages[pidx] + p.data.flatten() / n
return torch.cat(averages)
// Initialize 2-D array, each entry is some neural network
phi = [[None] * n for _ in range(m)]
for i in range(m):
for j in range(n):
phi[i][j] = NeuralNetwork()
// Let k, i be arbitrary indices
p1 = torch.nn.utils.parameters_to_vector(phi[k][i - 1].parameters())
p2 = torch.nn.utils.parameters_to_vector(mean of phi[:][i-1])
我想基本上计算参数 phi[k][i-1]
和整个列的平均值 phi[:][i-1]
之间的均方误差,即 ((p1 - p2)**2).sum()
我尝试了以下方式:
tmp = [x.parameters() for x in self.phi[:][i - 1]]
mean_params = torch.mean(torch.stack(tmp), dim=0)
p2 = torch.nn.utils.parameters_to_vector(mean_params)
但这行不通,因为 tmp 是生成器对象的列表。更具体地说,我想我的问题是计算生成器对象的平均值。
首先,我们可以定义一个函数来计算模型列表的平均参数。为了避免同时创建每个模型的参数副本,我们可能希望将其计算为 运行 总和。例如
def average_parameters_vector(model_list):
n = len(model_list)
avg = 0
for model in model_list:
avg = avg + torch.nn.utils.parameters_to_vector(model.parameters()) / n
return avg
然后您可以创建 p1
和 p2
并计算 mean-squared 错误
p1 = torch.nn.utils.parameters_to_vector(phi[k][i - 1].parameters())
p2 = average_parameters_vector(phi[:][i - 1])
mse = ((p1 - p2)**2).mean()
如果你真的想要一个 one-line 解决方案,它也可能是最快的,你可以通过制作一个包含 phi[:][i - 1]
中模型的所有参数的单个张量来计算它,然后意味着减少它们。但如前所述,这将显着增加内存使用量,尤其是当您的模型通常有数百万个参数时。
# Uses lots of memory but potentially the fastest solution
def average_parameters_vector(model_list):
return torch.stack([torch.nn.utils.parameters_to_vector(model.parameters()) for model in model_list]).mean(dim=0)
另一方面,如果您非常关心内存使用情况,那么您可以一次计算每个单独参数的平均值。
# more memory efficient than original solution but probably slower
def average_parameters_vector(model_list):
n = len(model_list)
num_params = len(list(model_list[0].parameters()))
averages = [0] * num_params
for model in model_list:
for pidx, p in enumerate(model.parameters()):
averages[pidx] = averages[pidx] + p.data.flatten() / n
return torch.cat(averages)