Python
2 in One Neural Network

2 in One Neural Network

Here we present a 2 in one network. A neural network which does regression and classification at same time.

Iris data set has been used in this example

Loading the dataset

import pandas as pd
path = '.../Iris/iris.csv'
df = pd.read_csv(path)
df.head()

Shuffle the dataframe

df = df.sample(frac=1)

Inputs and Outputs

We take sepal.length, sepal.width and petal.length as an input parameter. We take petal.width as first output parameter and variety as second parameter. The prediction of petal.width is a regression task while prediction of variety is a multi class classification task.

input_df = df[['sepal.length','sepal.width','petal.length']]
output_df1 = df[['petal.width']]
output_df2 = df[['variety']]
#Change the variety from name to number
output_df2['variety'] = pd.factorize(output_df2['variety'])[0]

#Reading values from dataframe and making arrays
X = input_df.values
Y1 = output_df1.values
Y2 = output_df2.values

#Dividing data into train and test set
X_train = X[:130]
X_test = X[130:]

Y1_train = Y1[:130]
Y1_test = Y1[130:]

Y2_train = Y2[:130]
Y2_test = Y2[130:]

Scaling and converting data to format suitable for PyTorch model

from sklearn.preprocessing import MinMaxScaler    
scaler = MinMaxScaler()

X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

Y1_train = scaler.fit_transform(Y1_train)
Y1_test = scaler.transform(Y1_test)

import torch

X_train = torch.from_numpy(X_train)
X_test = torch.from_numpy(X_test)

Y1_train = torch.from_numpy(Y1_train)
Y1_test = torch.from_numpy(Y1_test)

Y2_train = torch.from_numpy(Y2_train)
Y2_test = torch.from_numpy(Y2_test)

X_train = X_train.float()
X_test = X_test.float()

Y1_train = Y1_train.float()
Y1_test = Y1_test.float()

Y2_train = torch.squeeze(Y2_train)
Y2_test = torch.squeeze(Y2_test)

Defining Neural Network

import torch.nn as nn
class Net(nn.Module):
        def __init__(self):
            super(Net, self).__init__()
            self.intermediate = nn.Sequential(
                nn.Linear(3,512),
                nn.ReLU(),
                nn.Dropout(0.4),
                nn.Linear(512,128),
                nn.ReLU(),
                nn.Dropout(0.4),
                nn.Linear(128,64),
                nn.ReLU(),
            )
            #for regression
            self.P_width = nn.Sequential(
                nn.Linear(64, 1),
                nn.Sigmoid()
            )

            #for multiclass classification
            self.variety_classifier = nn.Sequential(
                nn.Linear(64, 3),
                nn.Sigmoid()
            )
        def forward(self, x):
            x = self.intermediate(x)
            petal_width = self.P_width(x)
            variety = self.variety_classifier(x)
            return petal_width,variety

Defining a function to calculate accuracy for multiclass classification

def multi_acc(y_pred, y_test):
    y_pred_softmax = torch.log_softmax(y_pred, dim = 1)
    _, y_pred_tags = torch.max(y_pred_softmax, dim = 1)    
    
    correct_pred = (y_pred_tags == y_test).float()
    acc = correct_pred.sum() / len(correct_pred)
    
    acc = torch.round(acc * 100)
    
    return acc

Instantiate model

model=Net()

Defining Loss function and optimizer

#Loss function for regression
petal_w_criterion = nn.L1Loss()

#Loss function for multiclass classification
variety_criterion = nn.CrossEntropyLoss()

#Defining the optimizer
optimizer = torch.optim.Adam(model.parameters(), lr= 1e-4)

Training the model

train_petal_w_loss = []
train_variety_loss = []
train_variety_accuracy = []

epochs = 10000
for i in range(epochs):
  petal_w, variety =model(X_train.float())
  
  accuracy = multi_acc(variety, Y2_train)

  petal_w_loss = petal_w_criterion(petal_w, Y1_train)
  variety_loss = variety_criterion(variety,Y2_train)

  total_loss = petal_w_loss + variety_loss
  total_loss.backward()

  train_petal_w_loss.append(petal_w_loss)
  train_variety_loss.append(variety_loss)
  train_variety_accuracy.append(accuracy)
  optimizer.step()
  if (i%1000 == 0):
    print(f'Accuracy after {i} epochs {accuracy}\n')

print(f'Accuracy after {i} epochs {accuracy}\n')

Plotting accuracy and losses

import matplotlib.pyplot as plt
fig,ax = plt.subplots(1,3,figsize=(20,5))
ax = ax.flat
ax[0].plot(train_variety_accuracy, 'b')
ax[1].plot(train_variety_loss, 'r')
ax[2].plot(train_petal_w_loss, 'g')


ax[0].set_xlabel('Epochs')
ax[1].set_xlabel('Epochs')
ax[2].set_xlabel('Epochs')


ax[0].set_ylabel('Accuracy')
ax[1].set_ylabel('Loss')
ax[2].set_ylabel('Loss')

ax[0].set_title('Variety Accuracy')
ax[1].set_title('Variety Loss')
ax[2].set_title('Petal width loss')
plt.show()

Accuracy and losses for test data

petal_w, variety =model(X_test.float())

accuracy = multi_acc(variety, Y2_test)

petal_w_loss = petal_w_criterion(petal_w, Y1_test)
variety_loss = variety_criterion(variety,Y2_test)
print(f'Variety accuracy: {accuracy}\n')
print(f'petal_w_loss: {petal_w_loss}\n')
print(f'variety_loss: {variety_loss}\n')