Il s'agit d'un article sur l'écrêtage de chaque valeur détenue par le tenseur géré par TensorFlow.
Plus précisément, ce sera une explication et un exemple d'implémentation des méthodes système tf.clip_by ...
.
Je pense qu'il y a différentes utilisations, mais dans les calculs liés à l'apprentissage automatique (en particulier le calcul de gradient), qui est l'objectif principal de TensorFlow, il existe de nombreux cas où le sentiment d'échelle des variables à gérer est différent et il n'est pas possible de bien calculer. L'écrêtage et la normalisation sont utilisés dans de tels cas.
Dans TensorFlow, le traitement conventionnel qui représente des variables, des constantes et diverses opérations est appelé un nœud Op (Article de référence). En exécutant (run) dans la session, le nœud Op contient un ensemble (tenseur) de la valeur du résultat de l'opération et le transmet au nœud Op suivant. Dans cet article, l'ensemble numérique une fois le traitement terminé est appelé ** nœud **.
Image de la suppression de la valeur d'un nœud lorsqu'il remplit les conditions d'une norme fixe
tf.clip_by_value
tf.clip_by_value(
t,
clip_value_min,
clip_value_max,
name=None
)
Pour chaque valeur détenue par le nœud, changez la valeur supérieure à la valeur maximale clip_value_max
en clip_value_max
et la valeur inférieure à la valeur minimale clip_value_min
en clip_value_min
.
example1.py
p1 = tf.placeholder(tf.int32, 6, name='p1')
p2 = tf.placeholder(tf.float32, 6, name='p2')
clip_value1 = tf.clip_by_value(p1, clip_value_max=2, clip_value_min=-2, name='clip_value1')
clip_value2 = tf.clip_by_value(p2, clip_value_max=2., clip_value_min=-2., name='clip_value2')
num1 = np.linspace(-4, 6, 6)
with tf.Session() as sess:
print(p1.eval(feed_dict={p1: num1}, session=sess))
print(p2.eval(feed_dict={p2: num1}, session=sess))
print(clip_value1.eval(feed_dict={p1: num1}, session=sess))
print(clip_value2.eval(feed_dict={p2: num1}, session=sess))
console
[-4 -2 0 2 4 6]
[-4. -2. 0. 2. 4. 6.]
[-2 -2 0 2 2 2]
[-2. -2. 0. 2. 2. 2.]
** Vous obtiendrez une erreur si le nœud et les types clip_value
ne correspondent pas. ** **
example1.py
print(clip_error1.eval(feed_dict={p1: num1}, session=sess))
console
TypeError: Expected int32 passed to parameter 'y' of op 'Minimum', got 2.0 of type 'float' instead.
tf.clip_by_norm
tf.clip_by_norm(
t,
clip_norm,
axes=None,
name=None
)
Si la norme L2 du nœud est supérieure à clip_norm
, changez chaque valeur pour passer à cette norme. S'il est inférieur à clip_norm
, il ne sera pas modifié.
example2.py
p3 = tf.placeholder(tf.float32, [2, 3], name='p3')
clip_norm1 = tf.clip_by_norm(p3, clip_norm=4, name='clip_norm1')
clip_norm2 = tf.clip_by_norm(p3, clip_norm=5, name='clip_norm2')
num2 = np.linspace(-2, 3, 6).reshape((2, 3))
with tf.Session() as sess:
print(p3.eval(feed_dict={p3: num2}, session=sess))
print(clip_norm1.eval(feed_dict={p3: num2}, session=sess))
print(clip_norm2.eval(feed_dict={p3: num2}, session=sess))
console
[[-2. -1. 0.]
[ 1. 2. 3.]] #La norme L2 totale est de 4.358 ...
[[-1.8353258 -0.9176629 0. ]
[ 0.9176629 1.8353258 2.7529888]]
[[-2. -1. 0.]
[ 1. 2. 3.]]
Vous pouvez spécifier des axes dans tf.clip_by_norm
.
Normalise la valeur avec la norme L2 pour chaque axe spécifié par les axes.
example3.py
clip_norm3 = tf.clip_by_norm(p3, clip_norm=3, axes=1, name='clip_norm3')
with tf.Session() as sess:
print(p3.eval(feed_dict={p3: num2}, session=sess))
print(clip_norm3.eval(feed_dict={p3: num2}, session=sess))
console
[[-2. -1. 0.] #La norme L2 dans la colonne 0 est 2.236 ...
[ 1. 2. 3.]] #La norme L2 dans la première rangée est 3.741 ...
[[-2. -1. 0. ]
[ 0.8017837 1.6035674 2.4053512]]
De plus, tf.clip_by_norm
provoquera une TypeError si le nœud à mordre ne peut pas gérer le point décimal.
Veuillez utiliser le type float ◯◯ ou complexe ◯◯.
tf.clip_by_global_norm
tf.clip_by_global_norm(
t_list,
clip_norm,
use_norm=None,
name=None
)
Contrairement à tf.clip_by_norm, il passe ** une liste de nœuds ** au lieu de nœuds. Si vous passez le nœud lui-même, vous obtiendrez une TypeError.
Soit la norme L2 du nœud entier stocké dans la liste global_norm
, et si cette valeur est supérieure à clip_norm
, change toutes les valeurs de la liste de sorte que la norme L2 soit clip_norm
. S'il est inférieur à clip_norm
, il ne sera pas modifié.
De plus, il y a deux valeurs de retour: une liste contenant ** nœuds après le découpage ** list_clipped
et une global_norm
calculée.
example4.py
c1 = tf.constant([[0, 1, 2], [3, 4, 5]], dtype=tf.float32, name='c1')
c2 = tf.constant([[-2, -4], [2, 4]], dtype=tf.float32, name='c2')
C = [c1, c2]
clip_global_norm, global_norm = tf.clip_by_global_norm(C, clip_norm=9, name='clip_global_norm')
with tf.Session() as sess:
for c in C:
print(c.eval(session=sess))
print(global_norm.eval(session=sess))
for cgn in clip_global_norm1:
print(cgn.eval(session=sess))
console
[[0. 1. 2.]
[3. 4. 5.]]
[[-2. -4.]
[ 2. 4.]]
9.746795
[[0. 0.9233805 1.846761 ]
[2.7701416 3.693522 4.6169024]]
[[-1.846761 -3.693522]
[ 1.846761 3.693522]]
Les méthodes tf.clip_by_norm
et tf.clip_by_global_norm
elles-mêmes sont simples, mais peuvent être utilisées, par exemple, pour traiter les contre-mesures d'explosion de gradient" coupure de gradient "dans les RNN.
Ce qui suit sera utile.
- Pascanu et al., (2012), On the difficulty of training Recurrent Neural Networks (pdf)
- [Comprendre le dégradé de découpage LSTM avec #rnn et le dégradé avec les tendances récentes](https://qiita.com/t_Signull/items/21b82be280b46f467d1b#rnn%E3%81%A8%E5%8B%BE%E9 % 85% 8D% E3% 81% AE% E3% 82% AF% E3% 83% AA% E3% 83% 83% E3% 83% 94% E3% 83% B3% E3% 82% B0 gradient-cliping)
Après avoir construit le modèle, si vous souhaitez l'entraîner, vous pourrez peut-être le résoudre en utilisant cette méthode lorsque vous passez à inf par calcul de propagation d'erreur, etc.
L'écrêtage a en fait changé la valeur de possession du nœud, mais il est également possible de calculer la norme uniquement.
tf.norm
tf.norm(
tensor,
ord='euclidean',
axis=None,
keepdims=None,
name=None
)
Le paramètre ʻord` détermine la valeur de p dans la norme Lp. Pour la norme L∞, spécifiez np.inf.
example4.py
p4 = tf.placeholder(tf.float32, [3, 4], name='p4')
normalize1 = tf.norm(p4, name='normalize1')
normalize2 = tf.norm(p4, ord=1.5, axis=0, name='normalize2')
normalize3 = tf.norm(p4, ord=np.inf, axis=1, name='normalize3')
num3 = np.linspace(-10, 8, 12).reshape((3, 4))
with tf.Session() as sess:
print(p4.eval(feed_dict={p4: num3}, session=sess))
print(normalize1.eval(feed_dict={p4: num3}, session=sess))
print(normalize2.eval(feed_dict={p4: num3}, session=sess))
print(normalize3.eval(feed_dict={p4: num3}, session=sess))
console
[[-10. -8.363636 -6.7272725 -5.090909 ]
[ -3.4545455 -1.8181819 -0.18181819 1.4545455 ]
[ 3.090909 4.7272725 6.3636365 8. ]]
19.87232
[12.364525 11.0871725 10.408293 10.876119 ]
[10. 3.4545455 8. ]
TensorFlow > API > TensorFlow Core r2.0 > Python > tf.cilp_by_value TensorFlow > API > TensorFlow Core r2.0 > Python > tf.clip_by_norm TensorFlow > API > TensorFlow Core r2.0 > Python > tf.clip_by_global_norm TensorFlow > API > TensorFlow Core r2.0 > Python > tf.norm
Demain, c'est "Pirater le système de réservation avec Ruby" par @yoshishin. Veuillez continuer à profiter du Calendrier de l'Avent GMO Ad Marketing 2019!
Recommended Posts