Hi, I just implemented an customized modules as follows:
class Loss(torch.nn.Module):
’’‘
Implement the loss function from output from RNN.
Ref paper: https://arxiv.org/abs/1308.0850 1
’’‘
def init(self):
’’‘
x is sequence of coordinates with dim (batch, seq_length, 3).
Parameters are sequence of output from rnn with dim (batch, seq_length, 128).
’’'
self.e = []      	  # predicted end of stroke probability scalar
self.m1 = []        # vector of means for x1 with len 20
self.m2 = []        # vector of means for x2 with len 20
self.pi = []        # vector of mixture density network coefficients with len 20
self.rho = []       # vector of correlation with len 20
self.s1 = []        # vector of standard deviation for x1 with len 20
self.s2 = []        # vector of standard deviation for x2 with len 20
self.x1 = []        # x1 coordinate at t+1
self.x2 = []        # x2 coordinates at t + 1
self.et = []        # end of probability indicator from ground truth
self.batch = 0      # batch size
self.seq_length = 0 # reduce by 1 because loss is caculated at t+1 timestamp
self.parameters = []
def forward(self, x, para):
	''' 
	Implement eq 26 of ref paper for each batch.
	Input:
		para: dim(seq_len, batch, 121)
		x:    dim(seq_len, batch, 3)
	'''
	if x.size()[0] == para.size()[0]:
		self.seq_length = x.size()[0] - 1
		total_loss = 0
		for i in range(self.seq_length):
			# prepare parameters
			self.__get_para(i, x, para)
			normalpdf = self.__para2normal(self.x1, self.x2, self.m1, self.m2, self.s1, self.s2, self.rho) #dim (n_batch, 20)
			single_loss = self.__singleLoss(normalpdf)
			total_loss += single_loss
		return total_loss
	else:
		raise Exception("x and para don't match")


def __get_para(self, i, x, para):
	'''
	Slice and process parameters to the right form.
	Implementing eq 18-23 of ref paper.
	'''
	self.batch = x.size()[1]
	self.e = torch.sigmoid(-para[i,:,0])  # eq 18
	self.parameters = para

	# slice remaining parameters and training inputs
	self.pi, self.m1, self.m2, self.s1, self.s2, self.rho = torch.split(self.parameters[i,:,1:], 20, dim = 1) # dim(batch, 20)
	self.x1 = x[i+1,:,0].resize(self.batch, 1)  # dim(batch, 1)
	self.x2 = x[i+1,:,1].resize(self.batch, 1)
	self.et = x[i+1,:,2].resize(self.batch, 1)
	
	## process parameters
	# pi
	max_pi = torch.max(self.pi, dim = 1)[0]
	max_pi = max_pi.expand_as(self.pi)
	diff = self.pi - max_pi
	red_sum = torch.sum(diff, dim = 1).expand_as(self.pi)
	self.pi = diff.div(red_sum)

	# sd
	self.s1 = self.s1.exp()
	self.s2 = self.s2.exp()

	# rho
	self.rho = self.rho.tanh()


	# reshape ground truth x1, x2 to match m1, m2 because broadcasting is currently not supported by pytorch
	self.x1 = self.x1.expand_as(self.m1)
	self.x2 = self.x2.expand_as(self.m2)


def __para2normal(self, x1, x2, m1, m2, s1, s2, rho):
	'''
	Implement eq 24, 25 of ref paper.
	All input with dim(1, batch, 20)
	'''
	norm1 = x1.sub(m1)
	norm2 = x2.sub(m2)
	s1s2 = torch.mul(s1, s2)
	z = torch.pow(torch.div(norm1, s1), 2) + torch.pow(torch.div(norm2, s2), 2) - \
		2*torch.div(torch.mul(rho, torch.mul(norm1, norm2)), s1s2)
	negRho = 1 - torch.pow(rho, 2)
	expPart = torch.exp(torch.div(-z, torch.mul(negRho, 2)))
	coef = 2*np.pi*torch.mul(s1s2, torch.sqrt(negRho))
	result = torch.div(expPart, coef)
	return result

	
def __singleLoss(self, normalpdf):
	'''
	Calculate loss for single time stamp. eq 26
	Input: normalpdf (1,n_batch, 20).
	'''
	epsilon = 1e-20  # floor of loss from mixture density component since initial loss could be zero
	mix_den_loss = torch.mul(self.pi, normalpdf)
	red_sum_loss = torch.sum(torch.log(mix_den_loss))  # sum for all batch
	end_loss = torch.sum(torch.log(torch.mul(self.e, self.et) + torch.mul(1-self.e, 1 - self.et)))
	total_loss = -red_sum_loss - end_loss
	
	return total_loss/self.batch

when I call loss(x, para), the following error comes up:
‘Loss’ object has no attribute ‘_forward_hooks’
What does the error message imply ?
Specifically, what is hook used for ?
Did I get the error because I have no parameters in this module ?