AttributeError: 'tuple' 对象没有属性 'size'

问题描述

更新:回顾这个问题后,大部分代码是不必要的。长话短说,Pytorch RNN 的隐藏层需要是一个火炬张量。当我发布问题时,隐藏层是一个元组

下面是我的数据加载器和模型。

from torch.utils.data import TensorDataset,DataLoader

def batch_data(log_returns,sequence_length,batch_size):
    """
    Batch the neural network data using DataLoader
    :param log_returns: asset's daily log returns
    :param sequence_length: The sequence length of each batch
    :param batch_size: The size of each batch; the number of sequences in a batch
    :return: DataLoader with batched data
    """
    
    # total number of batches we can make
    n_batches = len(log_returns)//batch_size
    
    # Keep only enough characters to make full batches
    log_returns = log_returns[:n_batches * batch_size]
    
    y_len = len(log_returns) - sequence_length
    
    x,y = [],[]
    for idx in range(0,y_len):
        idx_end = sequence_length + idx
        x_batch = log_returns[idx:idx_end]
        x.append(x_batch)
        # only making predictions after the last word in the batch
        batch_y = log_returns[idx_end]    
        y.append(batch_y)    
    
    # create tensor datasets
    x_tensor = torch.from_numpy(np.asarray(x))
    y_tensor = torch.from_numpy(np.asarray(y))
    
    # make x_tensor 3-d instead of 2-d
    x_tensor = x_tensor.unsqueeze(-1)
    
    data = TensorDataset(x_tensor,y_tensor)
    
    data_loader = DataLoader(data,shuffle=False,batch_size=batch_size)
    
    # return a DataLoader
    return data_loader
    def init_hidden(self,batch_size):
        ''' Initializes hidden state '''
        # Create two new tensors with sizes n_layers x batch_size x n_hidden,# initialized to zero,for hidden state and cell state of LSTM
        weight = next(self.parameters()).data
        
        if (train_on_gpu):
            hidden = (weight.new(self.n_layers,batch_size,self.n_hidden).zero_().cuda(),weight.new(self.n_layers,self.n_hidden).zero_().cuda())
        else:
            hidden = (weight.new(self.n_layers,self.n_hidden).zero_(),self.n_hidden).zero_())
        
        return hidden

我不知道怎么回事。当我尝试开始训练模型时,收到错误消息:

AttributeError: 'tuple' object has no attribute 'size'

解决方法

问题源于 hidden(在 forward 定义中)不是 Torch.Tensor。因此,r_output,hidden = self.gru(nn_input,hidden) 引发了一个相当混乱的错误,而没有具体说明参数中的错误。尽管您可以看到它是在名为 check_hidden_size()...

nn.RNN 函数中引发的

一开始我很困惑,认为 nn.RNN: h0 的第二个参数是一个包含 (hidden_state,cell_state) 的元组。该调用返回的第二个元素也是如此:hn。情况并非如此,h0hn 都是 Torch.Tensor。有趣的是,您可以解包堆叠张量:

>>> z = torch.stack([torch.Tensor([1,2,3]),torch.Tensor([4,5,6])])
>>> a,b = z
>>> a,b
(tensor([1.,2.,3.]),tensor([4.,5.,6.]))

您应该提供张量作为 nn.GRU __call__ 的第二个参数。


编辑 - 在进一步检查您的代码后,我发现您正在将 hidden 再次转换回 元组...在单元格 [14] 中你有hidden = tuple([each.data for each in hidden])。这基本上用 init_hidden 覆盖了您在 torch.stack 中所做的修改。

退后一步,看看 RNNBase 的 source code 是 RNN 模块的基类。如果没有将隐藏状态提供给转发,它将默认为:

if hx is None:
    num_directions = 2 if self.bidirectional else 1
    hx = torch.zeros(self.num_layers * num_directions,max_batch_size,self.hidden_size,dtype=input.dtype,device=input.device)

这本质上与您要实现的 init 完全相同。当然,您只想在每个时期重置隐藏状态,(我不明白为什么......)。无论如何,一个基本的替代方法是在一个纪元开始时将 hidden 设置为 None,按原样传递给 self.forward_back_prop,然后传递给 rnn,然后传递给 {{1 }} 它将依次默认为您初始化它。然后用该 RNN 前向调用返回的隐藏状态覆盖 self.rnn

总而言之,我只保留了代码的相关部分。从 hidden 中删除 init_hidden 函数并进行这些修改:

AssetGRU
,

在 0 附近应该有 [] 括号而不是 ()。

def forward(self,nn_input,hidden):
    ''' Forward pass through the network. 
        These inputs are x,and the hidden/cell state `hidden`. '''
    
    # batch_size equals the input's first dimension
    batch_size = nn_input.size(0)