Yong KIM
Yong KIM

Reputation: 11

tf.tape.gradient() returns None for my numerical function model

I'm trying to use tf.GradientTape(). But the problem is tape.gradientreturns None, so that the error output (TypeError : unsupported operand type(s) for *: 'float' and 'NoneType') popped up. As you can see in my code, dloss_dparams = tape.gradient(Cost, [XX,YY]) returns none. I don't know What is the problem. Does anyone why it behaves like this?

import tensorflow as tf
import math
import numpy as np
from numpy import loadtxt
import scipy.integrate as inte
from numpy import asarray
from numpy import savetxt

DPA_l=7.68e+5 #Displacements/ion/cm
Na = 6.10e+22 # atomic density atoms/cm3
c=0.0424
S = math.pi*(0.05)**2
rmax=0.23#cm
rmin=-0.23
m=100
n=100
Ndpa =1
Ninitial=1
dx = (rmax-rmin)/m
dy = (rmax-rmin)/n

dfInd = loadtxt('intensity_2c_re2.csv', delimiter =',')
dfRi = loadtxt('p2c_t,ri,sd_re3.csv', delimiter =',')
Fnd = np.full((len(dfInd),m+1,n+1),np.nan)
DPAnd = np.full((len(dfInd),m+1,n+1),np.nan)
Lnd = np.full((len(dfInd),m+1,n+1),np.nan)

def I_V(bb):
    return 2.2e-8+bb*1e-9
def T_D(aa):
    return 7.9e-2 +aa*1e-3

Vnd = np.full((len(dfInd),m+1,n+1),np.nan)
And = np.full((len(dfInd),m+1,n+1),np.nan)
A2nd = np.full((len(dfInd),m+1,n+1),np.nan)
f_x = np.full((len(dfInd),1),np.nan)
f_y = np.full((len(dfInd),1),np.nan)
SSB = np.full((len(dfInd),1),0)
F0nd =np.full((len(dfInd),2),np.nan)

#initial value
for i in range(len(dfInd)): 
    F0nd[i,1] = (0.762*dfInd[i,2]*dfInd[i,0]/S)*0.1*np.sqrt(2)/(2*(np.sqrt(math.pi))*math.erf(1/(5*c*2**2.5))*c)
    F0nd[i,0]= dfInd[i,0]
 
f_x[0,0] = inte.quad(lambda x : np.math.exp((-(x-(rmax))**2)/(2*c**2)),0,rmax-rmin)[0]
f_y[0,0] = inte.quad(lambda y : np.exp((-(y-(rmax))**2)/(2*c**2)),0,rmax-rmin)[0]
F0nd[0,1] = (0.762*dfInd[0,2]*dfInd[1,0]/S)*0.1*math.sqrt(2)/(2*(math.sqrt(math.pi))*math.erf(1/(5*c*2**2.5))*c) ###추가 12/29
DPAnd[0,:,:] = 0
Lnd[0,:,:] = 0
Vnd[0,:,:] = 0

for j in range(m+1):
    for k in range(n+1):
        Fnd[0,j,k] = math.sqrt(F0nd[0,1])*np.math.exp(-(((j*dx-(rmax))**2)/(2*c**2)))*math.sqrt(F0nd[0,1])*np.exp(-(((k*dy-(rmax))**2)/(2*c**2)))
        And[0,j,k] = ((np.exp((-(j*dx-(rmax))**2)/(2*c**2))+np.exp((-((j+1)*dx-(rmax))**2)/(2*c**2)))*0.5*dx/f_x[0])*((np.exp((-(k*dy-(rmax))**2)/(2*c**2))+np.exp((-((k+1)*dy-(rmax))**2)/(2*c**2)))*0.5*dy/f_y[0])
        A2nd[0,j,k] = (1-Vnd[0,j,k])*And[0,j,k]


def predictions(XX,YY):
    i=0
    v=1
    aa=0.0
    bb=0.0
    
    f_x[i+1,0] = inte.quad(lambda x : np.exp((-(x-(rmax-XX))**2)/(2*c**2)),0,rmax-rmin)[0]  #f_x[1,0] #f_x[21,0]
    f_y[i+1,0] = inte.quad(lambda y : np.exp((-(y-(rmax-YY))**2)/(2*c**2)),0,rmax-rmin)[0]  #f_y[1,0] #f_y[21,0]
    for j in range(m+1):
        for k in range(n+1):
            Fnd[i+1,j,k] = F0nd[i+1,1]*np.exp(-(((j*dx-(rmax-XX))**2)/(2*c**2)))*np.exp(-(((k*dy-(rmax-YY))**2)/(2*c**2)))
            And[i+1,j,k] = ((np.exp((-(j*dx-(rmax-XX))**2)/(2*c**2))+np.exp((-((j+1)*dx-(rmax-XX))**2)/(2*c**2)))*0.5*dx/f_x[i+1])*((np.exp((-(k*dy-(rmax-YY))**2)/(2*c**2))+np.exp((-((k+1)*dy-(rmax-YY))**2)/(2*c**2)))*0.5*dy/f_y[i+1])
            DPAnd[i+1,j,k] = DPAnd[i,j,k] + DPA_l*Fnd[i,j,k]/Na
                
            if  DPAnd[i+1,j,k] < T_D(aa) :
                Lnd[i+1,j,k] = DPAnd[i+1,j,k]/(T_D(aa))
            elif DPAnd[i+1,j,k]>=T_D(aa) :
                Lnd[i+1,j,k] = 1.0
                    
            if Lnd[i+1,j,k]<1:
                A2nd[i+1,j,k] = (1.0-Lnd[i+1,j,k])*And[i+1,j,k]*0.79 + 1.0*And[i+1,j,k]*0.21
            elif Lnd[i+1,j,k]==1.0:
                A2nd[i+1,j,k] = (1.0-Lnd[i+1,j,k])*And[i+1,j,k]
                    
    SSB = I_V(bb)*(((A2nd).sum(axis=2)).sum(axis=1))
    loss = (SSB[v]-dfRi[v-1,1])
    return loss


XX = tf.Variable(0.1)
YY = tf.Variable(0.1)
learning_rate = 0.01
for j in range(100):
    with tf.GradientTape() as tape:
        tape.watch([XX,YY])
        Cost = tf.reduce_mean(tf.square(predictions(XX,YY)))
        print('Cost=',Cost)
    dloss_dparams = tape.gradient(Cost, [XX,YY])
    print('dloss_dparams[0] =',dloss_dparams[0],', dloss_dparams[1] =',dloss_dparams[1])
    XX.assign_sub(learning_rate * dloss_dparams[0])
    YY.aasign_sub(learning_rate * dloss_dparams[1])

    if i%10 ==0 :
        print("{:5} I {:10.4f} I {:10.4} I {:10.6f}".format(i, XX.numpy(), YY.numpy(), cost))    

output is that

Cost= tf.Tensor(2.803658208007937e-17, shape=(), dtype=float64)
dloss_dparams[0] = None , dloss_dparams[1] = None
Traceback (most recent call last):
File "C:/Users/USER/Downloads/tensorflow_gradient descent14.py", line 103, in <module>
XX.assign_sub(learning_rate * dloss_dparams[0])
TypeError: unsupported operand type(s) for *: 'float' and 'NoneType'

the relation plot with Variables(XX,YY) and Cost is below, just in case. enter image description here

Upvotes: 1

Views: 2151

Answers (1)

Lescurel
Lescurel

Reputation: 11631

You are doing calculations outside of TensorFlow. That will result in a gradient of None, see the guide : Getting a gradient of None

The tape can't record the gradient path if the calculation exits TensorFlow. For example:

x = tf.Variable([[1.0, 2.0],
                 [3.0, 4.0]], dtype=tf.float32)

with tf.GradientTape() as tape:
  x2 = x**2

  # This step is calculated with NumPy
  y = np.mean(x2, axis=0)

  # Like most ops, reduce_mean will cast the NumPy array to a constant tensor
  # using `tf.convert_to_tensor`.
  y = tf.reduce_mean(y, axis=0)

print(tape.gradient(y, x))

will print

None

Upvotes: 3

Related Questions