# Import the libraries we need for this lab
import torch.nn as nn
import torch
import matplotlib.pyplot as plt
import numpy as np
from torch.utils.data import Dataset, DataLoader
Softmax Classifer 1D
Training Two Parameter, Mini-Batch Gradient Decent, Training Two Parameter Mini-Batch Gradient Decent
Objective
- How to build a Softmax classifier by using the Sequential module in pytorch.
Table of Contents
In this lab, you will use Softmax to classify three linearly separable classes, the features are in one dimension
Estimated Time Needed: 25 min
Preparation
We’ll need the following libraries:
Use the helper function to plot labeled data points:
# Create class for plotting
def plot_data(data_set, model = None, n = 1, color = False):
= data_set[:][0]
X = data_set[:][1]
Y == 0, 0].numpy(), Y[Y == 0].numpy(), 'bo', label = 'y = 0')
plt.plot(X[Y == 1, 0].numpy(), 0 * Y[Y == 1].numpy(), 'ro', label = 'y = 1')
plt.plot(X[Y == 2, 0].numpy(), 0 * Y[Y == 2].numpy(), 'go', label = 'y = 2')
plt.plot(X[Y -0.1, 3))
plt.ylim((
plt.legend()if model != None:
= list(model.parameters())[0][0].detach()
w = list(model.parameters())[1][0].detach()
b = ['yhat=0', 'yhat=1', 'yhat=2']
y_label = ['b', 'r', 'g']
y_color = []
Y for w, b, y_l, y_c in zip(model.state_dict()['0.weight'], model.state_dict()['0.bias'], y_label, y_color):
* X + b).numpy())
Y.append((w * X + b).numpy(), y_c, label = y_l)
plt.plot(X.numpy(), (w if color == True:
= X.numpy()
x = x.reshape(-1)
x = np.ones(x.shape)
top = Y[0].reshape(-1)
y0 = Y[1].reshape(-1)
y1 = Y[2].reshape(-1)
y2 = y1 > y1, interpolate = True, color = 'blue')
plt.fill_between(x, y0, where = y1 > y2, interpolate = True, color = 'blue')
plt.fill_between(x, y0, where = y1 > y0, interpolate = True, color = 'red')
plt.fill_between(x, y1, where = ((y1 > y2) * (y1 > y0)),interpolate = True, color = 'red')
plt.fill_between(x, y1, where = (y2 > y0) * (y0 > 0),interpolate = True, color = 'green')
plt.fill_between(x, y2, where = (y2 > y1), interpolate = True, color = 'green')
plt.fill_between(x, y2, where
plt.legend() plt.show()
Set the random seed:
#Set the random seed
0) torch.manual_seed(
<torch._C.Generator at 0x7b9882167170>
Make Some Data
Create some linearly separable data with three classes:
# Create the data class
class Data(Dataset):
# Constructor
def __init__(self):
self.x = torch.arange(-2, 2, 0.1).view(-1, 1)
self.y = torch.zeros(self.x.shape[0])
self.y[(self.x > -1.0)[:, 0] * (self.x < 1.0)[:, 0]] = 1
self.y[(self.x >= 1.0)[:, 0]] = 2
self.y = self.y.type(torch.LongTensor)
self.len = self.x.shape[0]
# Getter
def __getitem__(self,index):
return self.x[index], self.y[index]
# Get Length
def __len__(self):
return self.len
Create the dataset object:
# Create the dataset object and plot the dataset object
= Data()
data_set
data_set.x plot_data(data_set)
Build a Softmax Classifier
Build a Softmax classifier by using the Sequential module:
# Build Softmax Classifier technically you only need nn.Linear
= nn.Sequential(nn.Linear(1, 3))
model model.state_dict()
OrderedDict([('0.weight',
tensor([[ 0.5239],
[-0.4626],
[-0.4925]])),
('0.bias', tensor([-0.0875, -0.0961, -0.7790]))])
0] data_set[
(tensor([-2.]), tensor(0))
0][0]) model(data_set[
tensor([-0.7210, -1.4580, 1.9142], grad_fn=<ViewBackward0>)
Train the Model
Create the criterion function, the optimizer and the dataloader
# Create criterion function, optimizer, and dataloader
= nn.CrossEntropyLoss()
criterion = torch.optim.SGD(model.parameters(), lr = 0.01)
optimizer = DataLoader(dataset = data_set, batch_size = 5) trainloader
Train the model for every 50 epochs plot, the line generated for each class.
# Train the model
= []
LOSS def train_model(epochs):
for epoch in range(epochs):
if epoch % 50 == 0:
pass
plot_data(data_set, model)for x, y in trainloader:
optimizer.zero_grad()= model(x)
yhat = criterion(yhat, y)
loss
LOSS.append(loss)
loss.backward()
optimizer.step()300) train_model(
Analyze Results
Find the predicted class on the test data:
= model(data_set.x[10:20])
pred_0 = pred_0.max(1)
_, yhat_0 print(yhat_0)
tensor([0, 1, 1, 1, 1, 1, 1, 1, 1, 1])
# Make the prediction
= model(data_set.x)
z = z.max(1)
_, yhat print("The prediction:", yhat)
The prediction: tensor([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
Calculate the accuracy on the test data:
# Print the accuracy
= (data_set.y == yhat).sum().item()
correct = correct / len(data_set)
accuracy print("The accuracy: ", accuracy)
The accuracy: 0.225
You can also use the softmax function to convert the output to a probability,first, we create a Softmax object:
=nn.Softmax(dim=-1) Softmax_fn
The result is a tensor Probability
, where each row corresponds to a different sample, and each column corresponds to that sample belonging to a particular class
= Softmax_fn(z) Probability
we can obtain the probability of the first sample belonging to the first, second and third class respectively as follows:
for i in range(3):
print(f"probability of class {i} isg given by {Probability[0,i]}")
probability of class 0 isg given by 0.08364968001842499
probability of class 1 isg given by 0.5964528322219849
probability of class 2 isg given by 0.31989753246307373