Fast.ai Regression Model

Using fast.ai and Pytorch’s modules, building a regression model and Neural Network using Kaggle’s titanic survival data set
fastpages
jupyter
Author

Eric Vincent

Published

September 16, 2022

import pandas as pd
import numpy as np
df = pd.read_csv('/kaggle/input/titanic-survival-dataset/train.csv')
df = df.drop(columns=['Name', 'Cabin', 'Ticket', 'PassengerId'])
df['Male'] = df['Sex']
df['Male'] = df['Male'].replace({'male': 1, 'female' : 0})
df['Embarked_C'] = df['Embarked']
df['Embarked_C'] = df['Embarked_C'].replace({'S':0, 'C':1})
df['Embarked_S'] = df['Embarked']
df['Embarked_S'] = df['Embarked_S'].replace({'S':1, 'C':0})
df['Pclass1'] = df['Pclass']
df['Pclass2'] = df['Pclass']
df['Pclass3'] = df['Pclass']
df['Pclass1'] = df['Pclass1'].replace({2:0, 3:0})
df['Pclass2'] = df['Pclass2'].replace({1:0, 3:0, 2:1})
df['Pclass3'] = df['Pclass3'].replace({1:0, 2:0, 3:1})
random_parameters = np.random.rand(1,10)
Sibsp, Parch, Age, log_fare, Pclass1, Pclass2, EmbarkS, EmbarkC, Male, Const = [num for num in random_parameters[0]]
maxAge, maxFare = max(df['Age']), max(df['Fare'])
df['Age_N'] = df['Age'] / maxAge
df['log_Fare'] = df['Fare'] / maxFare
df['log_Fare'] = np.log10(df['log_Fare'] + 1)
parameters = {
    Sibsp, Parch, Age, log_fare, Pclass1, Pclass2, EmbarkS, EmbarkC, Male, Const
    
    
}
df['Ones'] = 1
Code
parameters = np.array([0.023121551427445874,
 0.13402581877095354,
 0.1460823666152794,
 0.22088891772092012,
 0.594795670221624,
 0.7961562768917094,
 0.8530100056367039,
 0.8613248152275507,
 0.8901214376590094,
 0.9785782868782011])
model_df = df
model_df = model_df.drop(columns=['Survived', 'Sex', 'Age', 'Fare', 'Embarked'])
model_df = model_df.drop(columns=['Pclass'])
model_df['Age_N'] = model_df['Age_N'].fillna(0)
model_df.isnull().values.any()
True
model_df = model_df.drop(columns=['Pclass3'])
model_df['Embarked_S'] = model_df['Embarked_S'].replace({'Q': 0})
model_df['Embarked_C'] = model_df['Embarked_C'].replace({'Q': 0})
model_df['Linear'] = model_df.dot(parameters)
model_df['Survived'] = df['Survived']
model_df['Loss'] = (model_df['Linear'] - 1)**2
model_df['Linear'].mean()
2.255390616421957
survived_label = model_df['Survived'] == 1
death_label = model_df['Survived'] == 0
survived = model_df.loc[survived_label]
death = model_df.loc[death_label]
pip install fastbook
import fastbook
fastbook.setup_book()
from fastai.vision.all import *
from fastbook import *

matplotlib.rc('image', cmap='Greys')
death
SibSp Parch Male Embarked_C Embarked_S Pclass1 Pclass2 Age_N log_Fare Ones Linear Survived Loss
0 1 0 1 0.0 1.0 0 0 0.2750 0.006103 1 1.984874 0 0.969977
4 0 0 1 0.0 1.0 0 0 0.4375 0.006771 1 2.102313 0 1.215093
5 0 0 1 0.0 0.0 0 0 0.0000 0.007111 1 1.130991 0 0.017159
6 0 0 1 0.0 1.0 1 0 0.6750 0.041878 1 3.134283 0 4.555164
7 3 1 1 0.0 1.0 0 0 0.0250 0.017507 1 1.959964 0 0.921530
... ... ... ... ... ... ... ... ... ... ... ... ... ...
884 0 0 1 0.0 1.0 0 0 0.3125 0.005935 1 1.993904 0 0.987844
885 0 5 0 0.0 0.0 0 0 0.4875 0.024013 1 2.089977 0 1.188051
886 0 0 1 0.0 1.0 0 1 0.3375 0.010882 1 2.872850 0 3.507568
888 1 2 0 0.0 1.0 0 0 0.0000 0.019437 1 1.881848 0 0.777656
890 0 0 1 0.0 0.0 0 0 0.4000 0.006520 1 1.474995 0 0.225620

549 rows × 13 columns

survived
SibSp Parch Male Embarked_C Embarked_S Pclass1 Pclass2 Age_N log_Fare Ones Linear Survived Loss
1 1 0 0 1.0 0.0 1 0 0.4750 0.056575 1 2.478233 1 2.185174
2 0 0 0 0.0 1.0 0 0 0.3250 0.006666 1 1.859239 1 0.738291
3 1 0 0 0.0 1.0 1 0 0.4375 0.042829 1 2.807605 1 3.267434
8 0 2 0 0.0 1.0 0 0 0.3375 0.009336 1 2.140433 1 1.300588
9 1 0 0 1.0 0.0 0 1 0.1750 0.024771 1 2.248379 1 1.558451
... ... ... ... ... ... ... ... ... ... ... ... ... ...
875 0 0 0 1.0 0.0 0 0 0.1875 0.006082 1 1.366379 1 0.134234
879 0 1 0 1.0 0.0 1 0 0.7000 0.065324 1 2.790723 1 3.206687
880 0 1 0 0.0 1.0 0 1 0.3125 0.021499 1 2.848710 1 3.417730
887 0 0 0 0.0 1.0 1 0 0.2375 0.024714 1 2.596093 1 2.547514
889 0 0 1 1.0 0.0 1 0 0.3250 0.024714 1 2.443635 1 2.084081

342 rows × 13 columns

a = np.array([survived.iloc[0]])
surv = tensor(a)
surv
tensor([[1.0000, 0.0000, 0.0000, 1.0000, 0.0000, 1.0000, 0.0000, 0.4750, 0.0566, 1.0000, 2.4782, 1.0000, 2.1852]])
b = tensor([survived.iloc[0]])
b
# TODO list comprehension for the stacked tensor containing all the rows, the result should be #rows, yaxis, xaxis
# do it on the copy df
tensor([[1.0000, 0.0000, 0.0000, 1.0000, 0.0000, 1.0000, 0.0000, 0.4750, 0.0566, 1.0000, 2.4782, 1.0000, 2.1852]])
Code
survived
SibSp Parch Male Embarked_C Embarked_S Pclass1 Pclass2 Age_N log_Fare Ones Linear Survived Loss
1 1 0 0 1.0 0.0 1 0 0.4750 0.056575 1 2.478233 1 2.185174
2 0 0 0 0.0 1.0 0 0 0.3250 0.006666 1 1.859239 1 0.738291
3 1 0 0 0.0 1.0 1 0 0.4375 0.042829 1 2.807605 1 3.267434
8 0 2 0 0.0 1.0 0 0 0.3375 0.009336 1 2.140433 1 1.300588
9 1 0 0 1.0 0.0 0 1 0.1750 0.024771 1 2.248379 1 1.558451
... ... ... ... ... ... ... ... ... ... ... ... ... ...
875 0 0 0 1.0 0.0 0 0 0.1875 0.006082 1 1.366379 1 0.134234
879 0 1 0 1.0 0.0 1 0 0.7000 0.065324 1 2.790723 1 3.206687
880 0 1 0 0.0 1.0 0 1 0.3125 0.021499 1 2.848710 1 3.417730
887 0 0 0 0.0 1.0 1 0 0.2375 0.024714 1 2.596093 1 2.547514
889 0 0 1 1.0 0.0 1 0 0.3250 0.024714 1 2.443635 1 2.084081

342 rows × 13 columns

survived_tensor
tensor([[1.0000, 0.0000, 0.0000,  ..., 2.4782, 1.0000, 2.1852],
        [0.0000, 0.0000, 0.0000,  ..., 1.8592, 1.0000, 0.7383],
        [1.0000, 0.0000, 0.0000,  ..., 2.8076, 1.0000, 3.2674],
        ...,
        [0.0000, 1.0000, 0.0000,  ..., 2.8487, 1.0000, 3.4177],
        [0.0000, 0.0000, 0.0000,  ..., 2.5961, 1.0000, 2.5475],
        [0.0000, 0.0000, 1.0000,  ..., 2.4436, 1.0000, 2.0841]])
len(survived_tensor), len(death_tensor)
(342, 549)
num = range(len(survived))
stacked_survived = [tensor(survived.iloc[num]) for num in num]
copydf = model_df
copydf = copydf.drop(columns=['Age_N', 'log_Fare', 'Ones', 'Linear', 'Loss'])
copydf['Embarked_C'].mean(), copydf['Embarked_S'].mean()
(0.1889763779527559, 0.7244094488188977)
# implement same logic for tensor stacked -- death here is still using 13 rows, need to update.aka next code block
r = [tensor(death.iloc[num]) for num in range(len(death))]
rStacked = torch.stack(r).float()
rStacked.shape
# this makes sense, 549 rows, single vector with (1x13rows) vs they had a rank 3 tensor
torch.Size([549, 13])
copydf['Embarked_S'] = copydf['Embarked_S'].fillna(0)
copydf['Embarked_C'] = copydf['Embarked_C'].fillna(0)
copydf
SibSp Parch Male Embarked_C Embarked_S Pclass1 Pclass2 Survived
0 1 0 1 0.0 1.0 0 0 0
1 1 0 0 1.0 0.0 1 0 1
2 0 0 0 0.0 1.0 0 0 1
3 1 0 0 0.0 1.0 1 0 1
4 0 0 1 0.0 1.0 0 0 0
... ... ... ... ... ... ... ... ...
886 0 0 1 0.0 1.0 0 1 0
887 0 0 0 0.0 1.0 1 0 1
888 1 2 0 0.0 1.0 0 0 0
889 0 0 1 1.0 0.0 1 0 1
890 0 0 1 0.0 0.0 0 0 0

891 rows × 8 columns

# we now have a single tensor that was created from calling tensor over all of our labelled rows of data using tensor()
survived_label = copydf['Survived'] == 1
death_label = copydf['Survived'] == 0
survived = copydf.loc[survived_label]
# survived['Embarked_S'] = survived['Embarked_S'].fillna(0)
# survived['Embarked_C'] = survived['Embarked_C'].fillna(0)
death = copydf.loc[death_label]
# num = range(len(survived))
# nums = range(len(death))
stacked_survived = [tensor(survived.iloc[num]) for num in range(len(survived))]
stacked_death = [tensor(death.iloc[num]) for num in range(len(death))]
# stacked_survived.shape, stacked_death.shape
len(stacked_death), len(stacked_survived)
(549, 342)
# Combine all of the rows of tensors previously created into a single 2 dimensional tensor - we also want the average in each labelled stacked tensor here

# Divide by the number of deaths of survivors in each label?
survive_tensors_stacked = torch.stack(stacked_survived).float()
death_tensors_stacked = torch.stack(stacked_death).float()


# mean_survived = stacked_death.mean(0)
# mean_death = stacked_survived.mean(0)
survive_tensors_stacked.shape, death_tensors_stacked.shape # i.e. 2 x rank 2 tensors with each 342 & 549 labels respectively, consisting of 8 rows each
(torch.Size([342, 8]), torch.Size([549, 8]))
mean_survived = survive_tensors_stacked.mean(0)
mean_death = death_tensors_stacked.mean(0)
mean_survived,mean_death
# embarked rows are Nan - due to fillna?  -- no more
(tensor([0.4737, 0.4649, 0.3187, 0.2719, 0.6345, 0.3977, 0.2544, 1.0000]),
 tensor([0.5537, 0.3297, 0.8525, 0.1366, 0.7778, 0.1457, 0.1767, 0.0000]))
single_survivor = survive_tensors_stacked[1]
single_death = death_tensors_stacked[1]

single_death, single_survivor
(tensor([0., 0., 1., 0., 1., 0., 0., 0.]),
 tensor([0., 0., 0., 0., 1., 0., 0., 1.]))
import torch.nn.functional as F
# distance between survivor and meandeath tensor
F.l1_loss(single_survivor.float(),mean_death), F.mse_loss(single_survivor,mean_death).sqrt()
(tensor(0.4271), tensor(0.5318))
# distance between survivor and survivor tensor

F.l1_loss(single_survivor.float(),mean_survived), F.mse_loss(single_survivor,mean_survived).sqrt()
# need RElu given that data contains many 0? -- > nan output 

# Update - both values are smaller than the distance between the survivor and the mean of the death
(tensor(0.3183), tensor(0.3487))
def survive_distance(a,b): 
    return (a-b).abs().mean()
# distance_all_survived = survive_distance(survive_tensors_stacked, mean_survived)
# distance_all_survived
type(stacked_survived), type(mean_survived)
(list, torch.Tensor)
# calculate the distance for all of the survivors in the validation set compared to the valid_surivivors_tens object - i.e. Pytorch will use broadcasting given that the tensors are of different rank
valid_survivor_dist = survive_distance(survive_tensors_stacked, mean_survived)
valid_survivor_dist, valid_survivor_dist.shape
(tensor(0.4210), torch.Size([]))
# Create a function that to determine if the row is a survivor 
def is_alive(x): return survive_distance(x,mean_survived) < survive_distance(x,mean_death)
# Test it out -- the range here might not be the same given that this is for rows and not images of a rank 3 tensor with a hor and vert axixs
# Update - changed the -1,-2 to simple mean() to fix the index out of range
is_alive(single_survivor), is_alive(single_survivor).float
# function works, is a valid survivor
(tensor(True), <function Tensor.float>)
# Test our function on the whole validation set of survivors :
is_alive(survive_tensors_stacked)
tensor(True)
# Calculate the accuracy for each of the survivors and deaths by taking the average of that function for all survivors and its inverse for all deaths
accuracy_alive = is_alive(survive_tensors_stacked).float() .mean()
accuracy_death = (1 - is_alive(death_tensors_stacked).float()).mean()

accuracy_alive,accuracy_death,(accuracy_alive+accuracy_death)/2
(tensor(1.), tensor(1.), tensor(1.))

Use Stochastic Gradient Descent to optimize our prediction model

  1. Initialize the weights.
  2. For each row, use these weights to predict whether it appears to be a survivor or not
  3. Based on these predictions, calculate how good the model is (its loss).
  4. Calculate the gradient, which measures for each weight, how changing that weight would change the loss
  5. Step (that is, change) all the weights based on that calculation.
  6. Go back to the step 2, and repeat the process.
  7. Iterate until we stop the training process
# Simple quadractic function that will be used for SGD
def f(x): return x**2

# Get a tensor which will requre gradients
xt = tensor(3.).requires_grad_()
yt = f(xt)
yt.backward()
xt.grad
tensor(6.)
# Repeat the steps but with a vector argument 
xt = tensor([3.,4.,10.]).requires_grad_()
xt

# Add sum to the quadratic function so it can take a vector (rank-1 tensor) and return a scalar (rank-0 tensor)
def f(x): return (x**2).sum()

yt = f(xt)
yt
tensor(125., grad_fn=<SumBackward0>)
yt.backward()
xt.grad
# Implement stepping with a learning rate
lr = 1e-5
# w -= gradient(w) * lr
# Loss function that will be used in our parameters, and quadratic function that will be used to measure the inputs vs the functions parameters
def mse(preds, targets): return ((preds-targets)**2).mean()

def f(t, params):
    a,b,c = params
    return a*(t**2) + (b*t) + c
# 1
def init_params(size, std=1.0): return (torch.randn(size)*std).requires_grad_()


weights = init_params((8,1))
bias = init_params(1)
# get train x
train_x = torch.cat([survive_tensors_stacked, death_tensors_stacked]).view(-1, 8)
(train_x[0]*weights.T).sum() + bias
tensor([-1.1449], grad_fn=<AddBackward0>)
# TODO get validation data through kaggle and make it as a stacked tensor
def sigmoid(x): return 1/(1+torch.exp(-x))

def survive_loss_updated(predictions, targets):
    predictions = predictions.sigmoid()
    return torch.where(targets==1, 1-predictions, predictions).mean()
train_y = tensor([1]*len(survived) + [0]*len(death)).unsqueeze(1)

# dset =

dset = list(zip(train_x,train_y))
x,y = dset[0]
x.shape,y

# UPDATE DL SO THAT XB SHAPE AND YB SHAPE REFLECT WHAT WE WANT
dl = DataLoader(dset, batch_size=8)
xb,yb = first(dl)
xb.shape,yb.shape
(torch.Size([8, 8]), torch.Size([8, 1]))
twenty_percent_df = pd.read_csv('/kaggle/input/titanic-survival-dataset/train.csv')
twenty_percent_df['Male'] = twenty_percent_df['Sex']
twenty_percent_df['Male'] = twenty_percent_df['Male'].replace({'male': 1, 'female' : 0})
twenty_percent_df['Embarked_C'] = twenty_percent_df['Embarked']
twenty_percent_df['Embarked_C'] = twenty_percent_df['Embarked_C'].replace({'S':0, 'C':1, 'Q':0})
twenty_percent_df['Embarked_S'] = twenty_percent_df['Embarked']
twenty_percent_df['Embarked_S'] = twenty_percent_df['Embarked_S'].replace({'S':1, 'C':0, 'Q':0})
twenty_percent_df['Pclass1'] = twenty_percent_df['Pclass']
twenty_percent_df['Pclass2'] = twenty_percent_df['Pclass']
twenty_percent_df['Pclass1'] = twenty_percent_df['Pclass1'].replace({2:0, 3:0})
twenty_percent_df['Pclass2'] = twenty_percent_df['Pclass2'].replace({1:0, 3:0, 2:1})
twenty_percent_df = twenty_percent_df.drop(columns=['Sex', 'Age', 'Fare', 'Embarked', 'Pclass'])
twenty_percent_df['Embarked_S'] = twenty_percent_df['Embarked_S'].fillna(0)
twenty_percent_df['Embarked_C'] = twenty_percent_df['Embarked_C'].fillna(0)
twenty_percent_df = twenty_percent_df.drop(columns=['Name', 'Cabin', 'PassengerId', 'Ticket'])
eighty_percent_df = twenty_percent_df.iloc[180:]
twenty_percent_df = twenty_percent_df.iloc[:179]
# labels for both training and validation data

#training
survived_label_train = eighty_percent_df['Survived'] == 1
death_label_train = eighty_percent_df['Survived'] == 0
survived_train = eighty_percent_df.loc[survived_label_train]
death_train = eighty_percent_df.loc[death_label_train]
stacked_survived_train = [tensor(survived_train.iloc[num]) for num in range(len(survived_train))]
stacked_death_train = [tensor(death_train.iloc[num]) for num in range(len(death_train))]

#stack
survive_tensors_stacked_train = torch.stack(stacked_survived_train).float()
death_tensors_stacked_train = torch.stack(stacked_death_train).float()

#validation
survived_label_validation = twenty_percent_df['Survived'] == 1
death_label_validation = twenty_percent_df['Survived'] == 0
survived_validation = twenty_percent_df.loc[survived_label_validation]
death_validation = twenty_percent_df.loc[death_label_validation]
stacked_survived_validation = [tensor(survived_validation.iloc[num]) for num in range(len(survived))]
stacked_death_validation = [tensor(death_validation.iloc[num]) for num in range(len(death))]

#stack
survive_tensors_stacked_validation = torch.stack(stacked_survived_validation).float()
death_tensors_stacked_validation = torch.stack(stacked_death_validation).float()
# create the stacked tensors for both training data and validation data

# create training dl
train_x = torch.cat([survive_tensors_stacked_train, death_tensors_stacked_train]).view(-1, 8)
train_y = tensor([1]*len(survived) + [0]*len(death)).unsqueeze(1)
dset = list(zip(train_x,train_y))
dl = DataLoader(dset, batch_size=8)

# create validation dl
valid_x = torch.cat([survive_tensors_stacked_validation, death_tensors_stacked_validation]).view(-1, 8)
valid_y = tensor([1]*len(survive_tensors_stacked_validation) + [0]*len(death_tensors_stacked_validation)).unsqueeze(1)
valid_dset = list(zip(valid_x,valid_y))
valid_dl = DataLoader(valid_dset, batch_size=8)

# finally
dls = DataLoaders(dl, valid_dl)

def batch_accuracy(xb, yb):
    preds = xb.sigmoid()
    correct = (preds>0.5) == yb
    return correct.float().mean()

# neural net
simple_net = nn.Sequential(
    nn.Linear(8,1),
    nn.ReLU(),
    nn.Linear(1,8)
)


learn = Learner(dls, simple_net, opt_func=SGD,
                loss_func=survive_loss_updated, metrics=batch_accuracy)

learn.fit(40, 0.1)
epoch train_loss valid_loss batch_accuracy time
0 0.509653 0.502687 0.473765 00:00
1 0.508797 0.502065 0.477132 00:00
2 0.507841 0.501465 0.477273 00:00
3 0.506854 0.500884 0.480079 00:00
4 0.505843 0.500287 0.480780 00:00
5 0.504807 0.499660 0.482183 00:00
6 0.503729 0.498991 0.482183 00:00
7 0.502581 0.498265 0.483025 00:00
8 0.501378 0.497482 0.485690 00:00
9 0.500111 0.496636 0.488356 00:00
10 0.498759 0.495647 0.488917 00:00
11 0.496819 0.493076 0.501403 00:00
12 0.492483 0.488248 0.542789 00:00
13 0.485624 0.480793 0.586700 00:00
14 0.475594 0.470186 0.586841 00:00
15 0.461520 0.455530 0.628367 00:00
16 0.443047 0.436796 0.638749 00:00
17 0.420336 0.414819 0.633979 00:00
18 0.394467 0.390664 0.637907 00:00
19 0.366764 0.363788 0.644220 00:00
20 0.336472 0.332068 0.709877 00:00
21 0.301700 0.296407 0.799102 00:00
22 0.266188 0.264302 0.799383 00:00
23 0.236447 0.239894 0.803030 00:00
24 0.215284 0.221003 0.808361 00:00
25 0.199868 0.205571 0.830107 00:00
26 0.187974 0.192608 0.840348 00:00
27 0.178303 0.181214 0.883558 00:00
28 0.170570 0.170600 0.889450 00:00
29 0.163774 0.160689 0.931257 00:00
30 0.157617 0.151713 0.937009 00:00
31 0.152163 0.143193 0.944865 00:00
32 0.147052 0.135531 0.947952 00:00
33 0.142345 0.128379 0.949916 00:00
34 0.138021 0.121739 0.951459 00:00
35 0.134111 0.115172 0.951740 00:00
36 0.130328 0.109340 0.951740 00:00
37 0.126849 0.103617 0.951880 00:00
38 0.123680 0.098068 0.991583 00:00
39 0.120625 0.093022 0.996773 00:00
# same for the validation set 

validdf = pd.read_csv('/kaggle/input/test-titanic/test.csv')
validdf['Male'] = validdf['Sex']
validdf['Male'] = validdf['Male'].replace({'male': 1, 'female' : 0})
validdf['Embarked_C'] = validdf['Embarked']
validdf['Embarked_C'] = validdf['Embarked_C'].replace({'S':0, 'C':1, 'Q':0})
validdf['Embarked_S'] = validdf['Embarked']
validdf['Embarked_S'] = validdf['Embarked_S'].replace({'S':1, 'C':0, 'Q':0})
validdf['Pclass1'] = validdf['Pclass']
validdf['Pclass2'] = validdf['Pclass']
validdf['Pclass1'] = validdf['Pclass1'].replace({2:0, 3:0})
validdf['Pclass2'] = validdf['Pclass2'].replace({1:0, 3:0, 2:1})
validdf['Embarked_S'] = validdf['Embarked_S'].fillna(0)
validdf['Embarked_C'] = validdf['Embarked_C'].fillna(0)



validdf
PassengerId Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked Male Embarked_C Embarked_S Pclass1 Pclass2
0 892 3 Kelly, Mr. James male 34.5 0 0 330911 7.8292 NaN Q 1 0 0 0 0
1 893 3 Wilkes, Mrs. James (Ellen Needs) female 47.0 1 0 363272 7.0000 NaN S 0 0 1 0 0
2 894 2 Myles, Mr. Thomas Francis male 62.0 0 0 240276 9.6875 NaN Q 1 0 0 0 1
3 895 3 Wirz, Mr. Albert male 27.0 0 0 315154 8.6625 NaN S 1 0 1 0 0
4 896 3 Hirvonen, Mrs. Alexander (Helga E Lindqvist) female 22.0 1 1 3101298 12.2875 NaN S 0 0 1 0 0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
413 1305 3 Spector, Mr. Woolf male NaN 0 0 A.5. 3236 8.0500 NaN S 1 0 1 0 0
414 1306 1 Oliva y Ocana, Dona. Fermina female 39.0 0 0 PC 17758 108.9000 C105 C 0 1 0 1 0
415 1307 3 Saether, Mr. Simon Sivertsen male 38.5 0 0 SOTON/O.Q. 3101262 7.2500 NaN S 1 0 1 0 0
416 1308 3 Ware, Mr. Frederick male NaN 0 0 359309 8.0500 NaN S 1 0 1 0 0
417 1309 3 Peter, Master. Michael J male NaN 1 1 2668 22.3583 NaN C 1 1 0 0 0

418 rows × 16 columns

validdf['Embarked_S'] = validdf['Embarked_S'].fillna(0)
validdf['Embarked_C'] = validdf['Embarked_C'].fillna(0)
validdf = validdf.drop(columns=['Name', 'Cabin', 'PassengerId', 'Ticket'])
stacked_pass_valid = [tensor(validdf.iloc[num]) for num in range(len(validdf))]
validdf
SibSp Parch Male Embarked_C Embarked_S Pclass1 Pclass2
0 0 0 1 0 0 0 0
1 1 0 0 0 1 0 0
2 0 0 1 0 0 0 1
3 0 0 1 0 1 0 0
4 1 1 0 0 1 0 0
... ... ... ... ... ... ... ...
413 0 0 1 0 1 0 0
414 0 0 0 1 0 1 0
415 0 0 1 0 1 0 0
416 0 0 1 0 1 0 0
417 1 1 1 1 0 0 0

418 rows × 7 columns

# diff between tensor and torch.cat ? VALID DSET IS THE OBJECT THAT WILL ULTIMATELY BE IN THE LEARNER
valid_x = torch.cat([survive_tensors_stacked, death_tensors_stacked]).view(-1, 8)
valid_y = tensor([1]*len(survive_tensors_stacked) + [0]*len(death_tensors_stacked)).unsqueeze(1)
valid_dset = list(zip(valid_x,valid_y))
valid_dl = DataLoader(valid_dset, batch_size=418)

# need both dl, valid dl and dl
# then 
linear_model = nn.Linear(8,1)
opt = SGD(linear_model.parameters(), lr)
# train_model(linear_model, 20)
#pass in the training and validatin data here
dls = DataLoaders(dl, valid_dl)
#finally 

# batch accuracy is optional 
def batch_accuracy(xb, yb):
    preds = xb.sigmoid()
    correct = (preds>0.5) == yb
    return correct.float().mean()

learn = Learner(dls, nn.Linear(8,1), opt_func=SGD,
                loss_func=survive_loss_updated, metrics=batch_accuracy)

learn.fit(10, lr=lr)
epoch train_loss valid_loss batch_accuracy time
0 0.462106 0.474574 0.640853 00:00
1 0.462066 0.474545 0.640853 00:00
2 0.462022 0.474515 0.640853 00:00
3 0.461978 0.474486 0.640853 00:00
4 0.461934 0.474457 0.640853 00:00
5 0.461889 0.474427 0.640853 00:00
6 0.461845 0.474398 0.640853 00:00
7 0.461801 0.474368 0.640853 00:00
8 0.461756 0.474339 0.640853 00:00
9 0.461712 0.474310 0.640853 00:00
# update the learner as a Neural Network
simple_net = nn.Sequential(
    nn.Linear(8,1),
    nn.ReLU(),
    nn.Linear(1,8)
)


learn = Learner(dls, simple_net, opt_func=SGD,
                loss_func=survive_loss_updated, metrics=batch_accuracy)

learn.fit(30, 0.1)
epoch train_loss valid_loss batch_accuracy time
0 0.477024 0.488728 0.552048 00:00
1 0.465068 0.484222 0.579966 00:00
2 0.452527 0.479878 0.579265 00:00
3 0.440095 0.475671 0.583894 00:00
4 0.427957 0.471588 0.584175 00:00
5 0.416164 0.467649 0.586420 00:00
6 0.404775 0.463854 0.585999 00:00
7 0.393790 0.460202 0.586560 00:00
8 0.383232 0.456691 0.586700 00:00
9 0.373102 0.453315 0.617144 00:00
10 0.363406 0.450072 0.621633 00:00
11 0.354151 0.446956 0.621352 00:00
12 0.345341 0.443954 0.621493 00:00
13 0.336966 0.441063 0.620932 00:00
14 0.329048 0.438224 0.623317 00:00
15 0.321520 0.435297 0.623597 00:00
16 0.314350 0.432160 0.624018 00:00
17 0.307599 0.428523 0.626263 00:00
18 0.301146 0.423695 0.628928 00:00
19 0.294620 0.415390 0.643098 00:00
20 0.286420 0.401846 0.657828 00:00
21 0.275414 0.380488 0.696549 00:00
22 0.259564 0.348015 0.740881 00:00
23 0.237341 0.304325 0.817059 00:00
24 0.210966 0.255090 0.860550 00:00
25 0.184133 0.202349 0.902637 00:00
26 0.156528 0.147107 0.988636 00:00
27 0.132545 0.112562 1.000000 00:00
28 0.117088 0.095011 1.000000 00:00
29 0.106355 0.083928 1.000000 00:00

learn.recorder.values[-1][2]
1.0