【问题标题】:Considerations of model definitions when moving from Tensorflow to PyTorch从 Tensorflow 迁移到 PyTorch 时模型定义的注意事项
【发布时间】:2019-05-09 16:18:11
【问题描述】:

在调试 tf 感到沮丧后,我最近才切换到 PyTorch,并了解它几乎完全等同于在 numpy 中编码。我的问题是我们可以在 PyTorch 模型中使用哪些允许的 python 方面(完全放在 GPU 上),例如。 if-else 必须在tensorflow中实现如下

a = tf.Variable([1,2,3,4,5], dtype=tf.float32)
b = tf.Variable([6,7,8,9,10], dtype=tf.float32)
p = tf.placeholder(dtype=tf.float32)
ps = tf.placeholder(dtype=tf.bool)

li = [None]*5
li_switch = [True, False, False, True, True]

for i in range(5):
    li[i] = tf.Variable(tf.random.normal([5]))

sess = tf.Session()
sess.run(tf.global_variables_initializer())

def func_0():
    return tf.add(a, p)
def func_1():
    return tf.subtract(b, p)

with tf.device('GPU:0'):
    my_op = tf.cond(ps, func_1, func_0)

for i in range(5):
    print(sess.run(my_op, feed_dict={p:li[i], ps:li_switch[i]}))

上述代码在 pytorch 中的结构会发生怎样的变化?如何将上面的变量和操作放在 GPU 上,并在 pytorch 中将列表输入并行化到我们的图形中?

【问题讨论】:

  • 我不认为每个问题都会像堆栈要求我们做的那样遵循模板。问题很简单,在要放在 GPU 上的 pytorch“模型”中,python 的代码(如果有的话)是什么,torch 的代码是什么?上面的代码几乎是我想要的。上面有一些解释的余地​​,任何内容都会帮助我多说几句。
  • 你是对的。但是,我们向您保证准确的重构结果。我们需要看一个输入和输出的例子,我认为这并不多。
  • 好的,我一会儿再编辑。
  • @AndrewNaguib 告诉我

标签: python tensorflow pytorch


【解决方案1】:

要在 PyTorch 中初始化 ab 张量,请执行以下操作:

a = torch.tensor([1,2,3,4,5], dtype=torch.float32)
b = torch.tensor([6,7,8,9,10], dtype=torch.float32)

但是,由于您需要它们完全在 GPU 上,您必须使用神奇的 .cuda() 函数。所以,应该是:

a = torch.tensor([1,2,3,4,5], dtype=torch.float32).cuda()
b = torch.tensor([6,7,8,9,10], dtype=torch.float32).cuda()

将张量移动到 GPU


另一种初始化方式是:

a = torch.FloatTensor([1,2,3,4,5]).cuda()
b = torch.FloatTensor([6,7,8,9,10]).cuda() 

如果我们需要生成随机正态分布,我们使用torch.randn(还有torch.rand,它执行均匀随机分布)。

li = torch.randn(5, 5)

(抓住这个bug,它必须在cuda上初始化,你不能对位于不同处理单元的张量进行操作,即CPU和GPU)

li = torch.randn(5, 5).cuda()

li_switch 初始化没有区别。

处理func_0func_1 的一种可能方法是将它们声明为

def func_0(li_value):
    return torch.add(a, li_value)
def func_1(li_value):
    return torch.sub(b, li_value)

那么,对于谓词函数调用,就这么简单:

for i, pred in enumerate(li_switch):
    if pred:
        func_0(li[i])
    else:
        func_1(li[i])

但是,我建议将您的操作矢量化并执行以下操作:

li_switch = torch.tensor([True, False, False, True, True])
torch.add(a, li[li_switch]).sum(dim=0)
torch.sub(b, li[~li_switch]).sum(dim=0)

这是更加优化的。

【讨论】:

  • 是的,它将按顺序运行。
  • 这就是我不想要的。我希望它在模型内部并在 GPU 上并行运行 100。 tf.cond 是一个可以放在 GPU 上的计算图操作。
  • 安德鲁别那么字面意思,去掉免责声明,理解意图。
  • 嗯,好吧,我删除了它:)
  • @caissalover 检查新的更新并判断是否适合您。
【解决方案2】:

在pytorch中,代码可以像普通python代码一样编写。

CPU

import torch
a = torch.FloatTensor([1,2,3,4,5])
b = torch.FloatTensor([6,7,8,9,10])
cond = torch.randn(5)

for ci in cond:
    if ci > 0:
        print(torch.add(a, 1))
    else:
        print(torch.sub(b, 1))

GPU

像这样将张量移动到 GPU:

a = torch.FloatTensor([1,2,3,4,5]).to('cuda')
b = torch.FloatTensor([6,7,8,9,10]).to('cuda')
cond = torch.randn(5).to('cuda')

import torch.nn as nn

class Cond(nn.Module):
    def __init__(self):
        super(Cond, self).__init__()

    def forward(self, cond, a, b):
        result =  torch.empty(cond.shape[0], a.shape[0]).cuda()
        for i, ci in enumerate(cond):
            if ci > 0:
                result[i] = torch.add(a, 1)
            else:
                result[i] = torch.sub(b, 1)

        return result

cond_model = Cond().to('cuda')
output = cond_model(cond, a, b)

https://pytorch.org/tutorials/beginner/blitz/tensor_tutorial.html#cuda-tensors

【讨论】:

  • 不,在这种情况下 ci 是并行输入。我猜在您的代码中,for 循环在 CPU 上按顺序运行,而 torch.add() 在 GPU 上运行。我希望 if else 也可以在 GPU 上(在模型内部)。并且列表是按顺序提供的,但它们也可以并行应用,在这种情况下,完整的模型需要是一个操作图。 @ManojMohan
  • 是的,如果我们有一个模型来获取这些数据,那么模型可以像张量一样被移动到 GPU 上。
  • 您能否编辑上面的代码并将其编写为模型中的其他内容,采用上面 2 个列表,其中包含 5 个在 GPU 上并行运行的元素。这对我有很大帮助。谢谢!
猜你喜欢
  • 1970-01-01
  • 2016-07-02
  • 1970-01-01
  • 2021-06-03
  • 1970-01-01
  • 2015-12-06
  • 2020-06-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多