AttributeError:“元组”对象没有属性“大小”

Posted

技术标签:

【中文标题】AttributeError:“元组”对象没有属性“大小”【英文标题】:AttributeError: 'tuple' object has no attribute 'size' 【发布时间】:2021-04-09 02:37:45 【问题描述】:

更新:回顾这个问题后,大部分代码都是不必要的。长话短说,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, batch_size, self.n_hidden).zero_().cuda())
        else:
            hidden = (weight.new(self.n_layers, batch_size, self.n_hidden).zero_(),
                      weight.new(self.n_layers, batch_size, self.n_hidden).zero_())
        
        return hidden

我不知道出了什么问题。当我尝试开始训练模型时,我收到错误消息:

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

【问题讨论】:

能否提供调用模型的代码? 已添加到我的帖子中...如果您还想查看训练循环,请告诉我 nn_input的类型是什么type(nn_input) @Mattpats,是的,这也会很有趣。更准确地说,作为hidden 传递的值是什么? github.com/mattpats/GRU_time_series_regression 【参考方案1】:

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)

【讨论】:

不,.size 是一个函数,使用整数调用 torch.Tensor.size 将返回该轴上的大小。【参考方案2】:

问题在于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.Tensors。不过有趣的是,您可以解压堆叠张量:

>>> 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])。这基本上会用torch.stack 覆盖您在init_hidden 中所做的修改。

退后一步,看看 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,然后传递给self.rnn,这又将默认初始化为你。然后用该 RNN 前向调用返回的隐藏状态覆盖 hidden

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

def forward_back_prop(rnn, optimizer, criterion, inp, target, hidden):
    ...
    if hidden is not None:
        hidden = hidden.detach()
    ...
    output, hidden = rnn(inp, hidden)  
    ...
    return loss.item(), hidden


def train_rnn(rnn, batch_size, optimizer, criterion, n_epochs, show_every_n_batches):
    ...
    for epoch_i in range(1, n_epochs + 1):
        
        hidden = None
        
        for batch_i, (inputs, labels) in enumerate(train_loader, 1):
            loss, hidden = forward_back_prop(rnn, optimizer, criterion, 
                                             inputs, labels, hidden)
            ...

    ...

【讨论】:

感谢您的回复。不幸的是,我仍然收到相同的错误消息。不确定这是否有帮助,但这个笔记本最初是一个 NLP 单词生成器。我正在尝试将其转换为回归模型,以便预测时间序列中的下一个数字,而不是预测下一个单词。两个模型的主要区别在于新模型中没有嵌入层。没有嵌入层会解释错误信息吗? 我认为嵌入层不是问题。您能否提供调用 GRU 类的主训练循环的代码? 我认为将整个笔记本和数据集发布到 github 会更容易。如果您更喜欢在 *** 中查看它,请告诉我。 github.com/mattpats/GRU_time_series_regression 我认为它现在正在正常训练。非常感谢您的帮助。不过,我有一个快速的问题。通过在每个 epoch 开始时设置 hidden=None,隐藏状态将初始化/重置为您描述的 RNNBase 代码中提供的默认隐藏状态。但是当您提到这个时说“我不明白为什么”,您是否想到了更好的方法? 我只是好奇将数据集中所有数据点的隐藏状态保留在内存中的原因是什么。这是你在某处读到的东西吗?我自己也不知道答案。我不会考虑这样做,而是让它在每次调用时重置状态。

以上是关于AttributeError:“元组”对象没有属性“大小”的主要内容,如果未能解决你的问题,请参考以下文章

AttributeError:“元组”对象在 pyspark 中没有属性“startswith”

AttributeError:当向 Pytorch LSTM 网络提供输入时,“元组”对象没有属性“dim”

model.fit AttributeError:“元组”对象没有属性“形状”

AttributeError: 'RDD' 对象没有属性 'show'

AttributeError:“NumpyArrayIterator”对象没有属性“类”

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