Lesson 5: using a simple Sequential model in Tabular Learner

to practice and get deeper understanding i tried to use a simple sequential model in tabular learner
for simplicity i used the iris dataset

from fastai.tabular.all import *
import torch.nn as nn

df = pd.read_csv('iris.csv')
split = TrainTestSplitter(random_state=42)(df)
df.species = pd.Categorical(df.species)

dls = TabularPandas(df, splits=split, procs=[Normalize], cat_names=[], cont_names=list(df.columns[:-1]), y_names='species', y_block=CategoryBlock()).dataloaders(bs=8)

class NNet(nn.Module):
    def __init__(self):
        super(NNet, self).__init__()
        self.nnet = nn.Sequential(
            nn.Linear(4,10),
            nn.ReLU(),
            nn.Linear(10,3),
            nn.Softmax()
        )
    def forward(self, x, _):
        return self.nnet(x.view(-1,4))

model = NNet()
learn = Learner(dls, model=model, metrics=accuracy, loss_func=CrossEntropyLossFlat)
learn.fit(10, lr=0.1)

when running learn.fit() i get this error:
RuntimeError: Boolean value of Tensor with more than one value is ambiguous

A. if i define learner the simplest way:
learn = tabular_learner(dls, metrics=accuracy, layers=[10], cbs=ShowGraphCallback())
everything works as expected, the training is done, i get predictions
what am i doing wrong?

B. also when checking dls.one_batch() i get:

(tensor([], size=(8, 0), dtype=torch.int64),
tensor([[-0.9863, -0.1293, -1.2199, -1.3095],
[ 1.0859, 0.5455, 1.1311, 1.2229],

what is this empty tensor on top, i can not figure it out?

thank you!

I think you need loss_func = CrossEntropyLossFlat(). But I’d need the full trace to know more

1 Like

hi,

thank you for checking this!

colab version here: Google Colab

full trace when loss_func = CrossEntropyLossFlat
https://pastebin.com/3WHkq2G3

another error when loss_func = CrossEntropyLossFlat()
ValueError : Expected input batch_size (0) to match target batch_size (8).
full trace: https://pastebin.com/MEc30iED

When creating the TabularPandas object you pass cat_names=[]. The dataloaders still create batches structured as (x_cat, x_cont, y) but since you don’t have categorical data it creates an empty tensor in that place.

You already acount for that distinction (cat/cont) in your forward pass when you split the input into x and _ but as mentioned before the first part of the input is the categorical one, so right now you are passing the empty tensor to the model instead of x_cont.
Switching the order:

def forward(self, _, x): …

together with @muellerzr’s fix should make the learner work :slight_smile:

2 Likes

thank you very much!
it worked! :smile: :heart:

1 Like