linear_classifier

.py

School

University of Michigan *

*We aren’t endorsed by this school

Course

599

Subject

Computer Science

Date

Apr 3, 2024

Type

py

Pages

11

Uploaded by abigailrafter

Report
""" Implements linear classifeirs in PyTorch. WARNING: you SHOULD NOT use ".to()" or ".cuda()" in each implementation block. """ import torch import random import statistics from abc import abstractmethod from typing import Dict, List, Callable, Optional def hello_linear_classifier(): """ This is a sample function that we will try to import and run to ensure that our environment is correctly set up on Google Colab. """ print("Hello from linear_classifier.py!") # Template class modules that we will use later: Do not edit/modify this class class LinearClassifier: """An abstarct class for the linear classifiers""" # Note: We will re-use `LinearClassifier' in both SVM and Softmax def __init__(self): random.seed(0) torch.manual_seed(0) self.W = None def train( self, X_train: torch.Tensor, y_train: torch.Tensor, learning_rate: float = 1e-3, reg: float = 1e-5, num_iters: int = 100, batch_size: int = 200, verbose: bool = False, ): train_args = ( self.loss, self.W, X_train, y_train, learning_rate, reg, num_iters, batch_size, verbose, ) self.W, loss_history = train_linear_classifier(*train_args) return loss_history def predict(self, X: torch.Tensor): return predict_linear_classifier(self.W, X) @abstractmethod def loss( self,
W: torch.Tensor, X_batch: torch.Tensor, y_batch: torch.Tensor, reg: float, ): """ Compute the loss function and its derivative. Subclasses will override this. Inputs: - W: A PyTorch tensor of shape (D, C) containing (trained) weight of a model. - X_batch: A PyTorch tensor of shape (N, D) containing a minibatch of N data points; each point has dimension D. - y_batch: A PyTorch tensor of shape (N,) containing labels for the minibatch. - reg: (float) regularization strength. Returns: A tuple containing: - loss as a single float - gradient with respect to self.W; an tensor of the same shape as W """ raise NotImplementedError def _loss(self, X_batch: torch.Tensor, y_batch: torch.Tensor, reg: float): self.loss(self.W, X_batch, y_batch, reg) def save(self, path: str): torch.save({"W": self.W}, path) print("Saved in {}".format(path)) def load(self, path: str): W_dict = torch.load(path, map_location="cpu") self.W = W_dict["W"] if self.W is None: raise Exception("Failed to load your checkpoint") # print("load checkpoint file: {}".format(path)) class LinearSVM(LinearClassifier): """A subclass that uses the Multiclass SVM loss function""" def loss( self, W: torch.Tensor, X_batch: torch.Tensor, y_batch: torch.Tensor, reg: float, ): return svm_loss_vectorized(W, X_batch, y_batch, reg) class Softmax(LinearClassifier): """A subclass that uses the Softmax + Cross-entropy loss function""" def loss( self, W: torch.Tensor, X_batch: torch.Tensor,
y_batch: torch.Tensor, reg: float, ): return softmax_loss_vectorized(W, X_batch, y_batch, reg) # **************************************************# ################## Section 1: SVM ################## # **************************************************# def svm_loss_naive( W: torch.Tensor, X: torch.Tensor, y: torch.Tensor, reg: float ): """ Structured SVM loss function, naive implementation (with loops). Inputs have dimension D, there are C classes, and we operate on minibatches of N examples. When you implment the regularization over W, please DO NOT multiply the regularization term by 1/2 (no coefficient). Inputs: - W: A PyTorch tensor of shape (D, C) containing weights. - X: A PyTorch tensor of shape (N, D) containing a minibatch of data. - y: A PyTorch tensor of shape (N,) containing training labels; y[i] = c means that X[i] has label c, where 0 <= c < C. - reg: (float) regularization strength Returns a tuple of: - loss as torch scalar - gradient of loss with respect to weights W; a tensor of same shape as W """ dW = torch.zeros_like(W) # initialize the gradient as zero # compute the loss and the gradient num_classes = W.shape[1] num_train = X.shape[0] loss = 0.0 for i in range(num_train): scores = W.t().mv(X[i]) correct_class_score = scores[y[i]] for j in range(num_classes): if j == y[i]: continue margin = scores[j] - correct_class_score + 1 # note delta = 1 if margin > 0: loss += margin ####################################################################### # TODO: # # Compute the gradient of the SVM term of the loss function and store # # it on dW. (part 1) Rather than first computing the loss and then # # computing the derivative, it is simple to compute the derivative # # at the same time that the loss is being computed. #
####################################################################### # Replace "pass" statement with your code dW[:,y[i]] -= X[i]/num_train dW[:,j] += X[i]/num_train ####################################################################### # END OF YOUR CODE # ####################################################################### # Right now the loss is a sum over all training examples, but we want it # to be an average instead so we divide by num_train. loss = loss/num_train # Add regularization to the loss. loss += reg * torch.sum(W * W) ############################################################################# # TODO: # # Compute the gradient of the loss function w.r.t. the regularization term # # and add it to dW. (part 2) # ############################################################################# # Replace "pass" statement with your code dW += 2*reg*W ############################################################################# # END OF YOUR CODE # ############################################################################# return loss, dW def svm_loss_vectorized( W: torch.Tensor, X: torch.Tensor, y: torch.Tensor, reg: float ): """ Structured SVM loss function, vectorized implementation. When you implment the regularization over W, please DO NOT multiply the regularization term by 1/2 (no coefficient). The inputs and outputs are the same as svm_loss_naive. Inputs: - W: A PyTorch tensor of shape (D, C) containing weights. - X: A PyTorch tensor of shape (N, D) containing a minibatch of data. - y: A PyTorch tensor of shape (N,) containing training labels; y[i] = c means that X[i] has label c, where 0 <= c < C. - reg: (float) regularization strength Returns a tuple of: - loss as torch scalar - gradient of loss with respect to weights W; a tensor of same shape as W """ loss = 0.0 dW = torch.zeros_like(W) # initialize the gradient as zero num_classes = W.shape[1] num_train = X.shape[0] #############################################################################
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help