FastAi LSTM 前向方法问题
FastAi LSTM forward method issue
尝试创建一个简单的 LSTM 模型并使用 FastAI 框架但失败了。
class SimpleLSTM(nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim, bs):
super().__init__()
self.input_dim = input_dim
self.hidden_dim = hidden_dim
self.output_dim = output_dim
self.bs = bs
self.lstm = nn.LSTM(self.input_dim, self.hidden_dim)
self.linear = nn.Linear(self.hidden_dim, self.output_dim)
def forward(self, *inputs):
print(f'in[0]: {inputs[0].shape}')
out, self.h = self.lstm(inputs[0].view(1, self.bs, self.input_dim))
y_pred = self.linear(out)
return y_pred[-1]
当我将原始数据提供给模型时,这个模块可以工作,但是当我用 Learner 模块初始化它时,它失败了。
它抱怨数据的形状是错误的。完整代码在这里
import torch
import torch.nn as nn
import pandas as pd
import fastai
from fastai.tabular import *
size = 200
bs = 20
X = torch.randn(size, 5)
y = (X.T[0] * 1.2 + X.T[1] * 4.2 + X.T[2] * 0.56 + X.T[3] * 0.12 + X.T[4] * 7.2 + torch.randn(size)).view(size, 1)
valid_ratio = 0.2
valid_samples = int(valid_ratio * size)
print(f'X.shape: {X.shape}')
print(f'y.shape: {y.shape}')
df = pd.concat([pd.DataFrame(X.data.numpy()), pd.DataFrame(y.data.numpy())], axis=1)
df.columns = ['a', 'b', 'c', 'd', 'e', 'y']
class SimpleLSTM(nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim, bs):
super().__init__()
self.input_dim = input_dim
self.hidden_dim = hidden_dim
self.output_dim = output_dim
self.bs = bs
self.lstm = nn.LSTM(self.input_dim, self.hidden_dim)
self.linear = nn.Linear(self.hidden_dim, self.output_dim)
def forward(self, *inputs):
print(f'in[0]: {inputs[0].shape}')
out, self.h = self.lstm(inputs[0].view(1, self.bs, self.input_dim))
y_pred = self.linear(out)
return y_pred[-1]
model = SimpleLSTM(input_dim=5, hidden_dim=100, output_dim=1, bs=bs)
model
out = model(X[:bs])
print(f'out shape: {out.shape}')
out = model(X[:bs])
print(f'out shape: {out.shape}')
procs = [Normalize]
valid_idx = range(len(df)-valid_samples, len(df))
dep_var = 'y'
data = TabularDataBunch.from_df('.', df, dep_var, valid_idx=valid_idx, procs=procs, bs=bs)
learner = Learner(data, model)
learner.fit_one_cycle(1)
我的观察是 FastAI 将提供两个参数,一个形状为 (bs, ),另一个形状为 (bs, input_dim)。为什么要传递(bs, )参数?
您的观察是正确的,并且在您的数据束 collate_function
中发生了什么。基本上,当遍历数据加载器时,x 是 data.collate_fn([data.train_ds.x[i] for i in list_indices)
,其中 list_indices 是您用于该批次的样本的索引列表。
当您查看 data.train_ds.x[0]
时,您会得到
TabularLine d -0.4334; e 1.3458; a 0.4151; c 0.2837; b -0.6355;
和 data.train_ds.x[0].data
产量:
[tensor(0), tensor([-0.4334, 1.3458, 0.4151, 0.2837, -0.6355])]
之所以会出现这种情况,是因为 fastai 中的表格数据处理的是分类变量和连续变量,这是通过使用 tabular_learner
.
创建一个特殊的学习器来处理的。
这里有两种可能的解决方案:
修改数据集,使 data.train_ds.x[i].data
成为形状为 5 的张量。
修改 collate_fn
使其 returns 一个 (bs, input_dim) 形状的张量也应该可以解决问题。
例如添加:
custom_collate_fn = lambda b: data_collate([(x.data[1], y) for (x, y) in b])
并在数据束创建中传递 collate_fn=custom_collate_fn
将起作用。但是,您稍后会收到错误消息,因为您有 200 件商品,而您的模型仅在批量大小为 64 时才有效。如果您在这方面需要帮助,请告诉我。
尝试创建一个简单的 LSTM 模型并使用 FastAI 框架但失败了。
class SimpleLSTM(nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim, bs):
super().__init__()
self.input_dim = input_dim
self.hidden_dim = hidden_dim
self.output_dim = output_dim
self.bs = bs
self.lstm = nn.LSTM(self.input_dim, self.hidden_dim)
self.linear = nn.Linear(self.hidden_dim, self.output_dim)
def forward(self, *inputs):
print(f'in[0]: {inputs[0].shape}')
out, self.h = self.lstm(inputs[0].view(1, self.bs, self.input_dim))
y_pred = self.linear(out)
return y_pred[-1]
当我将原始数据提供给模型时,这个模块可以工作,但是当我用 Learner 模块初始化它时,它失败了。
它抱怨数据的形状是错误的。完整代码在这里
import torch
import torch.nn as nn
import pandas as pd
import fastai
from fastai.tabular import *
size = 200
bs = 20
X = torch.randn(size, 5)
y = (X.T[0] * 1.2 + X.T[1] * 4.2 + X.T[2] * 0.56 + X.T[3] * 0.12 + X.T[4] * 7.2 + torch.randn(size)).view(size, 1)
valid_ratio = 0.2
valid_samples = int(valid_ratio * size)
print(f'X.shape: {X.shape}')
print(f'y.shape: {y.shape}')
df = pd.concat([pd.DataFrame(X.data.numpy()), pd.DataFrame(y.data.numpy())], axis=1)
df.columns = ['a', 'b', 'c', 'd', 'e', 'y']
class SimpleLSTM(nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim, bs):
super().__init__()
self.input_dim = input_dim
self.hidden_dim = hidden_dim
self.output_dim = output_dim
self.bs = bs
self.lstm = nn.LSTM(self.input_dim, self.hidden_dim)
self.linear = nn.Linear(self.hidden_dim, self.output_dim)
def forward(self, *inputs):
print(f'in[0]: {inputs[0].shape}')
out, self.h = self.lstm(inputs[0].view(1, self.bs, self.input_dim))
y_pred = self.linear(out)
return y_pred[-1]
model = SimpleLSTM(input_dim=5, hidden_dim=100, output_dim=1, bs=bs)
model
out = model(X[:bs])
print(f'out shape: {out.shape}')
out = model(X[:bs])
print(f'out shape: {out.shape}')
procs = [Normalize]
valid_idx = range(len(df)-valid_samples, len(df))
dep_var = 'y'
data = TabularDataBunch.from_df('.', df, dep_var, valid_idx=valid_idx, procs=procs, bs=bs)
learner = Learner(data, model)
learner.fit_one_cycle(1)
我的观察是 FastAI 将提供两个参数,一个形状为 (bs, ),另一个形状为 (bs, input_dim)。为什么要传递(bs, )参数?
您的观察是正确的,并且在您的数据束 collate_function
中发生了什么。基本上,当遍历数据加载器时,x 是 data.collate_fn([data.train_ds.x[i] for i in list_indices)
,其中 list_indices 是您用于该批次的样本的索引列表。
当您查看 data.train_ds.x[0]
时,您会得到
TabularLine d -0.4334; e 1.3458; a 0.4151; c 0.2837; b -0.6355;
和 data.train_ds.x[0].data
产量:
[tensor(0), tensor([-0.4334, 1.3458, 0.4151, 0.2837, -0.6355])]
之所以会出现这种情况,是因为 fastai 中的表格数据处理的是分类变量和连续变量,这是通过使用 tabular_learner
.
这里有两种可能的解决方案:
修改数据集,使
data.train_ds.x[i].data
成为形状为 5 的张量。修改
collate_fn
使其 returns 一个 (bs, input_dim) 形状的张量也应该可以解决问题。
例如添加:
custom_collate_fn = lambda b: data_collate([(x.data[1], y) for (x, y) in b])
并在数据束创建中传递 collate_fn=custom_collate_fn
将起作用。但是,您稍后会收到错误消息,因为您有 200 件商品,而您的模型仅在批量大小为 64 时才有效。如果您在这方面需要帮助,请告诉我。