Вычисляйте потери и градиенты для нескольких слоев одновременно в тензорном потоке с tf.GradientTape () - PullRequest
1 голос
/ 10 июля 2020

Если я правильно знаю слои, то Layers используйте tf.Variable в качестве переменной веса, поэтому, если в слое Dense() 3 единицы, это означает, что он использует что-то вроде w = tf.Variable([0.2,5,0.9]) для одного экземпляра и если input_shape равно 2, переменная будет примерно такой: w = tf.Variable([[0.2,5,0.9],[2,3,0.4]])? Пожалуйста, поправьте меня, если я ошибаюсь.

Я изучаю очень глубокие основы тензорного потока и нашел код, который я изменил как

weight = tf.Variable([3.2]) 


def get_lost_loss(w):
    '''
    A very hypothetical function since the name
    '''
    return (w**1.3)/3.1 # just felt like doing it


def calculate_gradient(w):
    with tf.GradientTape() as tape:
        loss = get_lost_loss(w) # calculate loss WITHIN tf.GradientTape()
        
    grad = tape.gradient(loss,w) # gradient of loss wrt. w
    
    return grad


# train and apply the things here
opt = tf.keras.optimizers.Adam(lr=0.01)

losses = []

for i in range(50):
    grad = calculate_gradient(weight)
    opt.apply_gradients(zip([grad],[weight]))
    
    losses.append(get_lost_loss(weight))

Может кто-нибудь, пожалуйста, подскажите мне, что такое происходит здесь, внутри tf.GradientTape(). Также я больше всего хотел спросить, что , если мне нужно сделать это для weight1 и weight2, формы которых [2,3] вместо weight, то какой должна быть модификация кода

Пожалуйста, делайте любые предположения, которые должны быть сделаны. Вы все гораздо более искусны в этой области, чем я.

1 Ответ

1 голос
/ 12 июля 2020

Да, вы правы. У слоев есть две переменные. Тот, который вы упомянули, называется ядром. А другой называется предвзятостью. В приведенном ниже примере это подробно объясняется:

import tensorflow as tf
w=tf.Variable([[3.2,5,6,7,5]],dtype=tf.float32)

d=tf.keras.layers.Dense(3,input_shape=(5,)) # Layer d gets inputs with shape (*,5) and generates outputs with shape (*,3)
                                            # It has kernel variable with shape (5,3) and bias variable with shape (3)
print("Output of applying d on w:", d(w))
print("\nLayer d trainable variables:\n", d.trainable_weights)

Результат будет примерно таким:

Output of applying d on w: tf.Tensor([[ -0.9845681 -10.321521    7.506028 ]], shape=(1, 3), dtype=float32)



Layer d trainable variables:
 [<tf.Variable 'dense_18/kernel:0' shape=(5, 3) dtype=float32, numpy=
array([[-0.8144073 , -0.8408185 , -0.2504158 ],
       [ 0.6073988 ,  0.09965736, -0.32579994],
       [ 0.04219657, -0.33530533,  0.71029276],
       [ 0.33406   , -0.673926  ,  0.77048916],
       [-0.8014116 , -0.27997494,  0.05623555]], dtype=float32)>, <tf.Variable 'dense_18/bias:0' shape=(3,) dtype=float32, numpy=array([0., 0., 0.], dtype=float32)>]

tf.GradientTape () используется для записи операций на обучаемых весах (переменных) в его контексте для автоматического c дифференцирования. Позже мы сможем получить производную переменных.

Предположим, у вас есть две весовые переменные: weight1 и weight2. Сначала вам нужно изменить функцию потерь, чтобы использовать обе переменные (см. Код ниже). Затем на каждом шаге нужно получить производную функции потерь по. переменные и обновите их, чтобы оптимизировать потери. См. Код ниже.

import tensorflow as tf

weight1 = tf.Variable([[3.2,5,6],[2,5,4]],dtype=tf.float32) #modified
weight2= tf.Variable([[1,2,3],[1,4,3]],dtype=tf.float32)    #modified

def get_lost_loss(w1, w2): #modified
    '''
    A very hypothetical function since the name
    '''
    return tf.reduce_sum(tf.math.add(w1**1.2/2,w2**2))  # just felt like doing it


def calculate_gradient(w1,w2):
    with tf.GradientTape() as tape:
        loss = get_lost_loss(w1,w2) # calculate loss WITHIN tf.GradientTape()
        
    dw1,dw2 = tape.gradient(loss,[w1,w2]) # gradient of loss wrt. w1,w2
    
    return dw1,dw2


# train and apply the things here
opt = tf.keras.optimizers.Adam(lr=0.01)

losses = []

for i in range(500):
    grad_weight1, grad_weight2 = calculate_gradient(weight1,weight2)
    opt.apply_gradients(zip([grad_weight1, grad_weight2],[weight1,weight2]))
    
    losses.append(get_lost_loss(weight1,weight2))
    print("loss: "+str(get_lost_loss(weight1,weight2).numpy()))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...