Очень низкая производительность при оценке ранее рассчитанной функции градиента - PullRequest
0 голосов
/ 31 октября 2019

Я пытаюсь выполнить оптимизацию, используя суррогатную модель вместо реальной функции, и для этого мне нужен градиент моей модели LSTM относительно входных данных. В этом случае у меня есть 3 функции, которые меняются со временем. LSTM вычисляет из начального значения этих 3 признаков следующие 100 временных шагов, следовательно, матрица Якоби имеет форму 100x3x3. Оказывается, мой код для оценки градиента медленнее (235 секунд на итерацию), чем код, который вычисляет функцию градиента (18 секунд на итерацию). Не могли бы вы помочь мне ускорить оценку градиента, чтобы я мог выполнить оптимизацию с помощью функции оценки? Коды для двух функций приведены ниже:

def get_grad_func(model,n_feat,n_output):
grad_func1=[]
grad_func2=[]
grad_func3=[]
grad_func=[]
for i in range(n_output):
    start_time = datetime.datetime.now()    
    print('Calculating dx'+str(i+1)+'/dx0')
    grad_func1.append(tf.gradients(model.output[:,i,0], model.input))
    grad_func2.append(tf.gradients(model.output[:,i,1], model.input))
    grad_func3.append(tf.gradients(model.output[:,i,2], model.input))   
    end_time = datetime.datetime.now()
    diff = (end_time - start_time).total_seconds()
    print(diff)
grad_func1= tf.reshape(grad_func1,[n_output,1,n_feat])    
output1=tf.stack(grad_func1)   
grad_func2= tf.reshape(grad_func2,[n_output,1,n_feat])       
output2=tf.stack(grad_func2) 
grad_func3= tf.reshape(grad_func3,[n_output,1,n_feat])  
output3=tf.stack(grad_func3) 
grad_func.append(output1)
grad_func.append(output2)
grad_func.append(output3)
return grad_func


def eval_grad(model,x0,n_feat,n_output,sess,grad_func):
jacobian_matrix = []
for i in range(n_output):
    print('Calculating dx'+str(i+1)+'/dx0')
    start_time = datetime.datetime.now()
    for n in range(n_feat):
        for m in range(n_feat):
            gradients = sess.run(grad_func[n][i,:,m], feed_dict={model.input: x0})
            jacobian_matrix.append(gradients)        
    end_time = datetime.datetime.now()
    diff = (end_time - start_time).total_seconds()
    print("time")
    print(diff)
J_matrix=zeros((n_output,n_feat,n_feat))
count=0
for i in range(n_output):
    for j in range(n_feat):
        J_matrix[i,j,:]=jacobian_matrix[count:count+n_feat]
        count=count+n_feat
return J_matrix
...