SoFunction
Updated on 2024-12-19

How pytorch defines new auto derivative functions

pytorch defines new autoderivative function

You want to customize the derivation function in pytorch to define your own automatic derivation operations by implementing and overriding the forward and backward functions. Refer to the demo on the official website: Portal

Straight to the code, define a ReLu to implement automatic derivatives

import torch

class MyRelu():
    @staticmethod
    def forward(ctx, input):
        # We use ctx context objects to cache for use in backpropagation, ctx storage can only hold tensor when stored
        # In forward propagation, we receive a context object ctx and a tensor input containing the input;
        # We must return a tensor containing the output of
        # (min = 0) means that all values in the input are specified to range from 0 to positive infinity, e.g. input=[-1,-2,3] is converted to input=[0,0,3].
        ctx.save_for_backward(input)
        
        # Returns several values, and backward accepts parameters containing ctx and those values.
        return (min = 0)

    @staticmethod
    def backward(ctx, grad_output):
        # Read out the input tensor stored in the ctx
        input, = ctx.saved_tensors
        
        # grad_output holds the gradient of the backpropagation process
        grad_input = grad_output.clone()
        
        # Here is the rule for ReLu, which says that if the original data is less than 0, then relu is 0, so the gradient of the corresponding index is set to 0.
        grad_input[input < 0] = 0
        return grad_input

Perform input data and test

dtype = 
device = ('cuda' if .is_available() else 'cpu')
# Use torch's generator to define random numbers, note whether cpu or gpu random numbers are generated
generator=(device).manual_seed(42)

# N is the Batch, H is the hidden dimension. #
# D_in is input dimension;D_out is output dimension.
N, D_in, H, D_out = 64, 1000, 100, 10

x = (N, D_in, device=device, dtype=dtype,generator=generator)
y = (N, D_out, device=device, dtype=dtype, generator=generator)

w1 = (D_in, H, device=device, dtype=dtype, requires_grad=True, generator=generator)
w2 = (H, D_out, device=device, dtype=dtype, requires_grad=True, generator=generator)

learning_rate = 1e-6
for t in range(500):
    relu = 
    # Arithmetic with function incoming parameters
    y_pred = relu((w1)).mm(w2)
	# Calculated losses
    loss = (y_pred - y).pow(2).sum()
    if t % 100 == 99:
        print(t, ())
    # Dissemination
    ()
    with torch.no_grad():
        w1 -= learning_rate * 
        w2 -= learning_rate * 
       	
        .zero_()
        .zero_()

pytorch autoderivative and logistic regression

automatic derivation

The return_graph is set to True, and backpropagation can be performed twice.

logistic regression

import torch
import  as nn
import  as plt
import numpy as np
torch.manual_seed(10)
#======== generates data =============
sample_nums = 100
mean_value = 1.7
bias = 1
n_data = (sample_nums,2)
x0 = (mean_value*n_data,1)+bias# Category 0 data
y0 = (sample_nums)#category0 tags
x1 = (-mean_value*n_data,1)+bias# Category 1 data
y1 = (sample_nums)# Category 1 labels
train_x = ((x0,x1),0)
train_y = ((y0,y1),0)
#========== select models ===========
class LR():
    def __init__(self):
        super(LR,self).__init__()
         = (2,1)
         = ()

    def forward(self,x):
        x = (x)
        x = (x)
        return x

lr_net = LR()# Instantiate logistic regression models

#============== selective loss function ===============
loss_fn = ()
#============== selecting the optimizer =================
lr = 0.01
optimizer = (lr_net.parameters(),lr = lr,momentum=0.9)

#=============== model training ==================
for iteration in range(1000):
    # Forward propagation
    y_pred = lr_net(train_x)# Output of the model
    #Calculate the loss
    loss = loss_fn(y_pred.squeeze(),train_y)
    # Backpropagation
    ()
    #Update parameters
    ()

    # Drawing
    if iteration % 20 == 0:
        mask = y_pred.ge(0.5).float().squeeze() # Categorized in 0.5
        correct = (mask==train_y).sum()# of samples correctly predicted
        acc = ()/train_y.size(0)# Classification accuracy

        (()[:,0],()[:,1],c='r',label='class0')
        (()[:,0],()[:,1],c='b',label='class1')

        w0,w1 = lr_net.[0]
        w0,w1 = float(()),float(())
        plot_b = float(lr_net.[0].item())
        plot_x = (-6,6,0.1)
        plot_y = (-w0*plot_x-plot_b)/w1

        (-5,7)
        (-7,7)
        (plot_x,plot_y)

        (-5,5,'Loss=%.4f'%(),fontdict={'size':20,'color':'red'})
        ('Iteration:{}\nw0:{:.2f} w1:{:.2f} b{:.2f} accuracy:{:2%}'.format(iteration,w0,w1,plot_b,acc))
        ()
        ()
        (0.5)
        if acc > 0.99:
            break

summarize

The above is a personal experience, I hope it can give you a reference, and I hope you can support me more.