Torch.autograd returns nonetype?

ctrl-f “torch.autograd.grad(”

this is terminal output of print statements:

tensor(1.3312, grad_fn=)
tensor(1.7920, grad_fn=)
(None,)
Traceback (most recent call last):
line 71, in
est= unadjusted_langevin.sample(alpha)
line 34, in sample
loss_term = torch.Tensor(self.step_size*grad_f_at_x)
TypeError: must be real number, not NoneType

Tried also removing allow_unused=True, then i get the error RuntimeError: One of the differentiated Tensors appears to not have been used in the graph. Set allow_unused=True if this is the desired behavior.

import torch
from precondSGLD import pSGLD
import copy

class UnadjustedLangevin(object):
def init(self, x, func, step_size, iteration_limit):
super(UnadjustedLangevin, self).init()

    self.func = func
    self.step_size = step_size
    self.counter = 0.0
    self.x = x
    self.x.requires_grad = True
    self.iteration_limit = iteration_limit
    self.samples = []


#pull one sample x_k1 from initial sample x_k
def sample(self,alpha):
    #output = self.R.matmul(self.normal.sample()) + self.mu
    #output = 0

    #need to take -log of fx_output as that's f
    fx_output = torch.Tensor(self.func(self.x))

    fx_output.requires_grad = True
    print(torch.norm(self.x))
    print(torch.norm(fx_output))
    grad_f_at_x = torch.autograd.grad(torch.norm(self.x), torch.norm(fx_output), allow_unused=True)

    print(grad_f_at_x)

    loss_term = torch.Tensor(self.step_size*grad_f_at_x)
    z_k = torch.normal(torch.zeros_like(self.x), torch.eye(2))
    x_k1 = self.x - loss_term + torch.sqrt(2*self.step_size)*z_k


    self.samples.append(x_k1)

    self.counter += 1
    return self.samples

import torch
from sampling_algs import *
import numpy as np
from scipy.linalg import logm
import matplotlib.pyplot as plt
import copy
np.random.seed(14)
torch.manual_seed(14)

##This is the main script

torch.set_default_tensor_type(‘torch.FloatTensor’) #cuda not available
#torch.set_default_tensor_type(‘torch.cuda.FloatTensor’) #cuda available

class GaussianDistribution(object):
def init(self, mean, cov_matrix):
super(GaussianDistribution, self).init()

    self.mu = mean
    self.cov = cov_matrix
    self.precision = torch.inverse(cov_matrix)

    self.R = torch.cholesky(self.cov)
    self.normal = torch.distributions.normal.Normal(torch.zeros_like(mean), 
        torch.ones_like(mean))

def pdf_func1(self, alpha):
    #mixed Gaussian
    alpha = torch.Tensor(alpha)
    #print(torch.zeros_like(alpha))
    loss_val = (torch.normal(-torch.zeros_like(alpha), torch.eye(2)) + 
    torch.normal(torch.zeros_like(alpha), torch.eye(2)))
    return 0.5*loss_val
    #return 0.5*(((x - mean).T).matmul(self.precision)).matmul(x - self.mean)

def sample(self):
    #print(self.normal.sample())
    return self.normal.sample() + self.mu 

#MAIN
if name == ‘main’:
#working in n=2
dim = 2

#############################
#Log Concave Test Cases
#alpha=torch.Tensor([0.1,0.1])
#alpha=torch.Tensor([0.3,0.3])
alpha=torch.Tensor([0.5,0.5]) #log concave value of a mag<1

#Non-Log Concave Test Cases
#alpha=torch.Tensor([1,1]) #non log concave value of a mag>1 
#alpha=torch.Tensor([2,2])
#alpha=torch.Tensor([3,3])
##############################
gaussian_dist = GaussianDistribution(alpha, torch.eye(dim)) 
step_size = 1
p0 = torch.normal(torch.zeros_like(alpha), torch.eye(2))

##RUN ULA algorithm. should output an array of values to plot
unadjusted_langevin = UnadjustedLangevin(p0, gaussian_dist.pdf_func1, step_size, iteration_limit=int(1e4))

hist_samples = []
loss_log = []


#Collect 10,000 samples
for j in range(int(1e4)):
    est= unadjusted_langevin.sample(alpha)
    if j%3 == 0:
        hist_samples.append(est.cpu().numpy())

est_samples = np.array(hist_samples)[200:]
num_samples = est_samples.shape[0]


#TODO: change gaussian_dist here to the mixture Gaussian in problem 9
num_samples = 10000
true_samples = np.zeros([num_samples, 2])
for j in range(num_samples):
    true_samples[j, :] = gaussian_dist.sample().cpu().numpy()