AttributeError: 'tuple' object has no attribute 'size'
AttributeError: 'tuple' object has no attribute 'size'
更新:回顾这个问题后,大部分代码都是不必要的。总之,Pytorch RNN 的隐藏层需要是 torch 张量。我发题的时候隐藏层是元组
下面是我的数据加载器。
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'
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)
问题来自 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
。事实并非如此 h0
和 hn
都是 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__
.
的第二个参数
Edit - 在进一步检查您的代码后,我发现您正在将 hidden
再次转换回 tuple ... 在单元格 [14] 中,您有 hidden = tuple([each.data for each in hidden])
。这基本上会用 torch.stack
.
覆盖您在 init_hidden
中所做的修改
退后一步,查看 RNNBase 的 source code 和 RNN 模块的基础 class。如果隐藏状态没有给前向它会默认为:
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)
这基本上与您要实现的完全相同。当然你只想在每个时期重置隐藏状态,(我不明白为什么......)。无论如何,一个基本的替代方案是在纪元开始时将 hidden
设置为 None
,按原样传递给 self.forward_back_prop
,然后传递给 rnn
,然后传递给 [=36] =] 这将默认为您初始化它。然后用该 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)
...
...
更新:回顾这个问题后,大部分代码都是不必要的。总之,Pytorch RNN 的隐藏层需要是 torch 张量。我发题的时候隐藏层是元组
下面是我的数据加载器。
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'
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)
问题来自 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
。事实并非如此 h0
和 hn
都是 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__
.
Edit - 在进一步检查您的代码后,我发现您正在将 hidden
再次转换回 tuple ... 在单元格 [14] 中,您有 hidden = tuple([each.data for each in hidden])
。这基本上会用 torch.stack
.
init_hidden
中所做的修改
退后一步,查看 RNNBase 的 source code 和 RNN 模块的基础 class。如果隐藏状态没有给前向它会默认为:
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)
这基本上与您要实现的完全相同。当然你只想在每个时期重置隐藏状态,(我不明白为什么......)。无论如何,一个基本的替代方案是在纪元开始时将 hidden
设置为 None
,按原样传递给 self.forward_back_prop
,然后传递给 rnn
,然后传递给 [=36] =] 这将默认为您初始化它。然后用该 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)
...
...