精华内容
下载资源
问答
  • Pytorch获取中间层表示

    2019-04-26 16:44:45
    这里先只是搬运过来,https://github.com/zergtant/pytorch-handbook/blob/master/chapter4/4.1-fine-tuning.ipynb,还没测试,但觉得以后会...in_list= [] #存放待输出中间层内容 def hook(module, input, output...

    这里先只是搬运过来,https://github.com/zergtant/pytorch-handbook/blob/master/chapter4/4.1-fine-tuning.ipynb,还没测试,但觉得以后会用到。

    根据提供的方法,需要经过如下步骤:

    1)定义hook函数

    in_list= [] #存放待输出中间层内容
    def hook(module, input, output): #需要三元组输入
        for i in range(input[0].size(0)):
            in_list.append(input[0][i].cpu().numpy())

    2)待输出中间层注册hook,比如原始例子注册了avgpool层

    model.avgpool.register_forward_hook(hook)

    3)前向跑起来并保存

    with torch.no_grad():
        for batch_idx, data in enumerate(dataloader):
            x,y= data
            y_ = model(x)
    
    features=np.array(in_list)
    np.save("features",features)

     

    展开全文
  • Pytorch获取中间层信息-hook函数

    千次阅读 多人点赞 2019-09-10 12:38:20
    由于pytorch会自动舍弃图计算的中间结果,所以想要获取这些数值就需要使用hook函数。hook函数包括tensor的hook和nn.Module的hook,用法相似。hook函数在使用后应及时删除,以避免每次都运行钩子增加运行负载。hook...

    参考链接:https://www.cnblogs.com/hellcat/p/8512090.html
    由于pytorch会自动舍弃图计算的中间结果,所以想要获取这些数值就需要使用hook函数。hook函数包括tensor的hook和nn.Module的hook,用法相似。hook函数在使用后应及时删除,以避免每次都运行钩子增加运行负载。hook函数主要用在获取某些中间结果的情景,如中间某一层的输出或某一层的梯度。这些结果本应写在forward函数中,但如果在forward函数中专门加上这些处理,可能会使处理逻辑比较复杂,这时候使用hook技术就更合适一些

    Tensor对象

    参考:https://pytorch.org/docs/stable/tensors.html
    有如下的register_hook(hook)方法,为Tensor注册一个backward hook,用来获取变量的梯度。
    hook必须遵循如下的格式:hook(grad) -> Tensor or None,其中grad为获取的梯度
    具体的实例如下:

    import torch
    
    grad_list = []
    def print_grad(grad):
        grad = grad * 2
        grad_list.append(grad)
    
    x = torch.tensor([[1., -1.], [1., 1.]], requires_grad=True)
    h = x.register_hook(print_grad)    # double the gradient
    out = x.pow(2).sum()
    out.backward()
    print(grad_list)
    '''
    [tensor([[ 4., -4.],
            [ 4.,  4.]])]
    '''
    # 删除hook函数
    h.remove()
    

    Module对象

    register_forward_hook(hook)register_backward_hook(hook)两种方法,分别对应前向传播和反向传播的hook函数。

    register_forward_hook(hook)

    在网络执行forward()之后,执行hook函数,需要具有如下的形式:

    hook(module, input, output) -> None or modified output
    

    hook可以修改input和output,但是不会影响forward的结果。最常用的场景是需要提取模型的某一层(不是最后一层)的输出特征,但又不希望修改其原有的模型定义文件,这时就可以利用forward_hook函数。

    import torch
    import torch.nn as nn
    import torch.nn.functional as F
    
    
    class LeNet(nn.Module):
        def __init__(self):
            super(LeNet, self).__init__()
            self.conv1 = nn.Conv2d(3, 6, 5)
            self.conv2 = nn.Conv2d(6, 16, 5)
            self.fc1 = nn.Linear(16*5*5, 120)
            self.fc2 = nn.Linear(120, 84)
            self.fc3 = nn.Linear(84, 10)
    
        def forward(self, x):
            out = F.relu(self.conv1(x))
            out = F.max_pool2d(out, 2)
            out = F.relu(self.conv2(out))
            out = F.max_pool2d(out, 2)
            out = out.view(out.size(0), -1)
            out = F.relu(self.fc1(out))
            out = F.relu(self.fc2(out))
            out = self.fc3(out)
            return out
    
    features = []
    def hook(module, input, output):
        features.append(output.clone().detach())
    
    
    net = LeNet()
    x = torch.randn(2, 3, 32, 32)
    handle = net.conv2.register_forward_hook(hook)
    y = net(x)
    
    print(features[0].size())
    handle.remove()
    

    register_backward_hook(hook)

    每一次module的inputs的梯度被计算后调用hook,hook必须具有如下的签名:

    hook(module, grad_input, grad_output) -> Tensor or None
    

    grad_inputgrad_output参数分别表示输入的梯度和输出的梯度,是不能修改的,但是可以通过return一个梯度元组tuple来替代grad_input
    展示一个实例来解析grad_inputgrad_output参数:

    import torch
    import torch.nn as nn
    
    
    def hook(module, grad_input, grad_output):
        print('grad_input: ', grad_input)
        print('grad_output: ', grad_output)
    
    
    x = torch.tensor([[1., 2., 10.]], requires_grad=True)
    module = nn.Linear(3, 1)
    handle = module.register_backward_hook(hook)
    y = module(x)
    y.backward()
    print('module_weight: ', module.weight.grad)
    
    handle.remove()
    

    输出:

    grad_input:  (tensor([1.]), tensor([[ 0.1236, -0.0232, -0.5687]]), tensor([[ 1.],
            [ 2.],
            [10.]]))
    grad_output:  (tensor([[1.]]),)
    module_weight:  tensor([[ 1.,  2., 10.]])
    

    可以看出,grad_input元组包含(bias的梯度输入x的梯度权重weight的梯度),grad_output元组包含输出y的梯度。
    可以在hook函数中通过return来修改grad_input

    import torch
    import torch.nn as nn
    
    
    def hook(module, grad_input, grad_output):
        print('grad_input: ', grad_input)
        print('grad_output: ', grad_output)
        return grad_input[0] * 0, grad_input[1] * 0, grad_input[2] * 0,
    
    
    x = torch.tensor([[1., 2., 10.]], requires_grad=True)
    module = nn.Linear(3, 1)
    handle = module.register_backward_hook(hook)
    y = module(x)
    y.backward()
    print('module_bias: ', module.bias.grad)
    print('x: ', x.grad)
    print('module_weight: ', module.weight.grad)
    
    handle.remove()
    

    输出:

    grad_input:  (tensor([1.]), tensor([[ 0.1518,  0.0798, -0.3170]]), tensor([[ 1.],
            [ 2.],
            [10.]]))
    grad_output:  (tensor([[1.]]),)
    module_bias:  tensor([0.])
    x:  tensor([[0., 0., -0.]])
    module_weight:  tensor([[0., 0., 0.]])
    

    对于没有参数的Module,比如nn.ReLU来说,grad_input元组包含(输入x的梯度),grad_output元组包含(输出y的梯度)。

    def hook(module, grad_input, grad_output):
        print('grad_input: ', grad_input)
        print('grad_output: ', grad_output)
        return (grad_input[0] / 4, )
    
    
    x = torch.tensor([-1., 2., 10.], requires_grad=True)
    module = nn.ReLU()
    handle = module.register_backward_hook(hook)
    y = module(x).sum()
    z = y * y
    z.backward()
    
    print(x.grad)  # tensor([0., 6., 6.])
    handle.remove()
    

    输出:

    grad_input:  (tensor([ 0., 24., 24.]),)
    grad_output:  (tensor([24., 24., 24.]),)
    tensor([0., 6., 6.])
    

    y=ReLU(x1)+ReLU(x2)+ReLU(x3)y=ReLU(x_{1})+ReLU(x_{2})+ReLU(x_{3})
    z=y2z=y^{2}
    grad_output是传到ReLU模块的输出值的梯度,即zy=2y=24\frac{\partial z}{\partial y}=2y=24
    grad_input是进入ReLU模块的输入值的梯度,由yx1=0,yx2=1,yx3=1\frac{\partial y}{\partial x_{1}}=0,\frac{\partial y}{\partial x_{2}}=1,\frac{\partial y}{\partial x_{3}}=1,可得:
    zyyx1=0,zyyx2=24,zyyx3=24\frac{\partial z}{\partial y}\frac{\partial y}{\partial x_{1}}=0,\frac{\partial z}{\partial y}\frac{\partial y}{\partial x_{2}}=24,\frac{\partial z}{\partial y}\frac{\partial y}{\partial x_{3}}=24
    在hook函数中可以对输入值xx的梯度进行缩放:
    [0,24,24]/4=[0,6,6][0,24,24]/4=[0,6,6]

    展开全文
  • pytorch获取模型的中间层输出结果

    千次阅读 2020-09-08 18:36:25
    如果想要获取模型的中间层输出,则需要在计算前标定目标层位置(通过forward返回),或者把模型在那层截断(当作一个小模型)输出。本文介绍2种获取模型中间层输出结果的方法: 1. 标定目标层位置 def forward(self, ...

    在inference阶段,整个模型会load到GPU上,进行端到端的计算,通常只会给你输出一个最终结果。

    如果想要获取模型的中间层输出,则需要在计算前标定目标层位置(通过forward返回),或者把模型在那层截断(当作一个小模型)输出。本文介绍2种获取模型中间层输出结果的方法:

    1. 标定目标层位置

    def forward(self, x):
        layer1_out = self.layer1(x)
        layer2_out = self.layer2(layer1_out)
        out = self.final_layer(layer2_out)
        return out #, layer2_out

    如果想看第二层的输出结果,只需在return的时候把layer2_out返回即可。

    2. 把模型在某层截断

    class MyModel:
        def __init__(self, xxx):
            self.backbone = net1()
            self.head = net2()
        def forward(self, x):
            out = self.head(net1(x))
            return out
    
    if __name__=='__main__':
        model = MyModel()
        x = cv2.imread('xxx')
        mid_out = model.backbone(x)
        print(mid_out.size())

     

    展开全文
  • 今天小编就为大家分享一篇pytorch 获取层权重,对特定层注入hook, 提取中间层输出的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 今天小编就为大家分享一篇pytorch 输出中间层特征的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • pytorch 输出中间层特征

    万次阅读 2018-05-21 11:20:57
    只保存模型参数时,可以读取网络结构,然后按照对应的中间层输出即可。but:Pytorch 论坛给出的答案并不好用,无论是hooks,还是重建网络并去掉某些层,这些方法都不好用(在我看来)。我们可...

    pytorch 输出中间层特征:

    tensorflow输出中间特征,2种方式:

    1. 保存全部模型(包括结构)时,需要之前先add_to_collection 或者 用slim模块下的end_points

    2. 只保存模型参数时,可以读取网络结构,然后按照对应的中间层输出即可。

    but:Pytorch 论坛给出的答案并不好用,无论是hooks,还是重建网络并去掉某些层,这些方法都不好用(在我看来)。

    我们可以在创建网络class时,在forward时加入一个dict 或者 list,dict是将中间层名字与中间层输出分别作为key:value,然后作为第二个值返回。前提是:运行创建自己的网络(无论fine-tune),只保存网络参数。

    个人理解:虽然每次运行都返回2个值,但是运行效率基本没有变化。

    附上代码例子:

    import torch
    import torchvision
    import numpy as np
    from torch import nn
    from torch.nn import init
    from torch.autograd import Variable
    from torch.utils import data

    EPOCH=20
    BATCH_SIZE=64
    LR=1e-2

    train_data=torchvision.datasets.MNIST(root='./mnist',train=True,
                                          transform=torchvision.transforms.ToTensor(),download=False)
    train_loader=data.DataLoader(train_data,batch_size=BATCH_SIZE,shuffle=True)

    test_data=torchvision.datasets.MNIST(root='./mnist',train=False)

    test_x=Variable(torch.unsqueeze(test_data.test_data,dim=1).type(torch.FloatTensor)).cuda()/255
    test_y=test_data.test_labels.cuda()

    class CNN(nn.Module):
        def __init__(self):
            super().__init__()
            self.conv1=nn.Sequential(
                    nn.Conv2d(in_channels=1,out_channels=16,kernel_size=4,stride=1,padding=2),
                    nn.ReLU(),
                    nn.MaxPool2d(kernel_size=2,stride=2))
            self.conv2=nn.Sequential(nn.Conv2d(16,32,4,1,2),nn.ReLU(),nn.MaxPool2d(2,2))
            self.out=nn.Linear(32*7*7,10)
            
        def forward(self,x):
            per_out=[] ############修改处##############
            x=self.conv1(x)
            per_out.append(x) # conv1
            x=self.conv2(x)
            per_out.append(x) # conv2
            x=x.view(x.size(0),-1)
            output=self.out(x)
            return output,per_out
        
    cnn=CNN().cuda() # or cnn.cuda()

    optimizer=torch.optim.Adam(cnn.parameters(),lr=LR)
    loss_func=nn.CrossEntropyLoss().cuda()############################

    for epoch in range(EPOCH):
        for step,(x,y) in enumerate(train_loader):
            b_x=Variable(x).cuda()# if channel==1 auto add c=1
            b_y=Variable(y).cuda()
    #        print(b_x.data.shape)
            optimizer.zero_grad()
            output=cnn(b_x)[0] ##原先只需要cnn(b_x) 但是现在需要用到第一个返回值##
            loss=loss_func(output,b_y)# Variable need to get .data
            loss.backward()
            optimizer.step()
            
            if step%50==0:
                test_output=cnn(test_x)[0]
                pred_y=torch.max(test_output,1)[1].cuda().data.squeeze()
                '''
                why data ,because Variable .data to Tensor;and cuda() not to numpy() ,must to cpu and to numpy
                and .float compute decimal
                '''
                accuracy=torch.sum(pred_y==test_y).data.float()/test_y.size(0)
                print('EPOCH: ',epoch,'| train_loss:%.4f'%loss.data[0],'| test accuracy:%.2f'%accuracy)
            #                                             loss.data.cpu().numpy().item() get one value

        torch.save(cnn.state_dict(),'./model/model.pth')

    ##输出中间层特征,根据索引调用##

    conv1: conv1=cnn(b_x)[1][0]

    conv2: conv2=cnn(b_x)[1][1]


    ##########################

    hook使用:

    res=torchvision.models.resnet18()

    def get_features_hook(self, input, output):# self 代表类模块本身
        print(output.data.cpu().numpy().shape)

    handle=res.layer2.register_forward_hook(get_features_hook)

    a=torch.ones([1,3,224,224])

    b=res(a) 直接打印出 layer2的输出形状,但是不好用。因为,实际中,我们需要return,而hook明确指出 不可以return 只能print。

    所以,不建议使用hook。


    展开全文
  • 获取VGG中间层输出结果 VGG结构 VGG的结构根据其网络层数的深度,分为四种,分别为11,13,16,19.这四种对应的网络结构的配置的声明见下。 defaultcfg = { 11 : [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, ...
  • pytorch-中间层可视化

    万次阅读 2021-02-17 22:12:26
    如果想要获取模型的中间层输出,则需要在计算前标定目标层位置(通过forward返回),或者把模型在那层截断(当作一个小模型)输出。本文介绍2种获取模型中间层输出结果的方法: 1. 标定目标层位置 def forward(self, ...
  • pytorch获取nn.Sequential的中间层输出

    千次阅读 2020-04-30 14:11:41
    对于nn.Sequential结构,要想获取中间网络层输出,可以使用循环遍历的方式得到。 示例 import torch import torch.nn as nn model = nn.Sequential( nn.Conv2d(3, 9, 1, 1, 0, bias=False), nn.BatchNorm2d(9), n...
  • #获取模型权重 for k, v in model_2.state_dict().iteritems(): print("Layer {}".format(k)) print(v) #获取模型权重 for layer in model_2.modules(): if isinstance(layer, nn....
  • 今天小编就为大家分享一篇pytorch获取vgg16-feature层输出的例子,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • pytorch利用hook获取模型中间层输出

    千次阅读 2019-10-22 08:56:49
    原文链接 https://www.cnblogs.com/hellcat/p/8512090.html
  • 为了节省显存,pytorch在反向传播的过程中只保留了计算图中的叶子结点的梯度值,而未保留中间节点的梯度,如下例所示: import torch x = torch.tensor(3., requires_grad=True) y = x ** 2 z = 4 * y z....
  • pytorch模型中间层特征的提取

    万次阅读 热门讨论 2018-04-28 14:14:24
    参考pytorch论坛:How to extract features of an image from a trained model 定义一个特征提取的类: #中间特征提取 class FeatureExtractor(nn.Module): def __init__(self, submodule, extracted_layers): ...
  • PyTorch提取中间层的特征(Resnet)

    万次阅读 2019-03-11 22:22:27
    特征提取在深度学习的训练中是经常要做的事情,之前的一篇blog有写到使用pytorch提取Vgg、Resnet、Densenet三种模型下的特征,这里所述的是提取全... 在本文中,主要是介绍提取中间层的特征,对于特征的提取,可以先...
  • PyTorch获取vgg16 features每层输出

    千次阅读 2020-03-13 22:46:23
    实际应用时可能比较想获取VGG中间层输出,那么就可以如下操作: import numpy as np import torch from torchvision import models from torch.autograd import Variable import torchvision.transforms as ...
  • pytorch获取vgg16-feature层输出

    千次阅读 2018-03-15 21:12:48
    实际应用时可能比较想获取VGG中间层输出,那么就可以如下操作:import numpy as np import torch from torchvision import models from torch.autograd import Variable import torchvision.transforms as ...
  • 获取Pytorch中间某一权重或者特征

    万次阅读 多人点赞 2019-04-02 16:06:20
    获取Pytorch中间某一权重或者特征 问题:训练好的网络模型想知道中间某一的权重或者看看中间某一的特征,如何处理呢? 1.获取某一权重,并保存到excel中; 以resnet18为例说明: import torch import pandas as pd...
  • 今天小编就为大家分享一篇获取Pytorch中间某一权重或者特征的例子,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,154
精华内容 861
关键字:

pytorch获取中间层输出