Bonjour. L'autre jour
Lire l'article
Si vous n'utilisez pas la normalisation par lots, vous perdrez la vie If you aren't using batch normalization you should
J'ai donc essayé d'implémenter et de vérifier (?) La normalisation des lots par Theano.
Est en partie mentionné.
Batch Normalization
Normaliser chaque lot de sorte que la moyenne soit 0 et la variance 1. Soit $ B $ un ensemble d'entrées pour le mini-lot et $ m $ une taille de lot.
B = \{x_{1...m}\}\\
Ci-dessous, $ \ epsilon $ semble être un paramètre de stabilisation.
\epsilon = 10^{-5}\\
\mu_{B} \leftarrow \frac{1}{m} \sum_{i=1}^{m} x_i\\
\sigma^2_{B} \leftarrow \frac{1}{m} \sum_{i=1}^{m} (x_i - \mu_{B})^2\\
\hat{x_i} \leftarrow \frac{x_i - \mu_{B}}{\sqrt{\sigma^2_{B} + \epsilon}}\\
y_i \leftarrow \gamma \hat{x_i} + \beta
Concernant la formule ci-dessus, il semble que $ \ gamma $ et $ \ beta $ servent respectivement à mettre à l'échelle et à décaler les valeurs normalisées par les paramètres. Il est nécessaire d'apprendre chacun par la méthode de propagation des erreurs, mais ici nous omettons la dérivation d'équations détaillées.
Dans une couche entièrement connectée normale, il est nécessaire de calculer la moyenne et la variance de la dimension d'entrée.
En d'autres termes, si la forme d'entrée est (BacthSize, 784)
, il est nécessaire de calculer la moyenne et la variance de 784 pièces.
Par contre, en couche convolutionnelle, il est nécessaire de calculer la moyenne et la dispersion pour le nombre de canaux.
En d'autres termes, si la forme d'entrée est (BatchSize, 64 (nombre de canaux), 32, 32)
, il est nécessaire de calculer la moyenne et la variance de 64 pièces.
En tant que mérite de la normalisation par lots, il semble qu'un coefficient d'apprentissage élevé puisse être défini et l'apprentissage peut être accéléré.
class BatchNormalizationLayer(object):
def __init__(self, input, shape=None):
self.shape = shape
if len(shape) == 2: # for fully connnected
gamma = theano.shared(value=np.ones(shape[1], dtype=theano.config.floatX), name="gamma", borrow=True)
beta = theano.shared(value=np.zeros(shape[1], dtype=theano.config.floatX), name="beta", borrow=True)
mean = input.mean((0,), keepdims=True)
var = input.var((0,), keepdims=True)
elif len(shape) == 4: # for cnn
gamma = theano.shared(value=np.ones(shape[1:], dtype=theano.config.floatX), name="gamma", borrow=True)
beta = theano.shared(value=np.zeros(shape[1:], dtype=theano.config.floatX), name="beta", borrow=True)
mean = input.mean((0,2,3), keepdims=True)
var = input.var((0,2,3), keepdims=True)
mean = self.change_shape(mean)
var = self.change_shape(var)
self.params = [gamma, beta]
self.output = gamma * (input - mean) / T.sqrt(var + 1e-5) + beta
def change_shape(self, vec):
ret = T.repeat(vec, self.shape[2]*self.shape[3])
ret = ret.reshape(self.shape[1:])
return ret
Un exemple d'utilisation (principalement du pseudo-code) est
...
input = previous_layer.output #Variable de symbole, sortie du calque précédent, forme=(batchsize, 784)
h = BatchNormalizationLayer(input, shape=(batchsize, 784))
#Lors de l'activation
h.output = activation(h.output) # activation=Une fonction d'activation
...
params = ... + h.params + ... #Utilisé lors de la mise à jour des paramètres réseau.
Les données ont été expérimentées avec un simple réseau neuronal multicouche utilisant MNIST.
--Nombre de couches intermédiaires: 10 --Nombre d'unités dans la couche intermédiaire: 784 au total
bien Couche d'entrée → (Couche entièrement connectée → Couche de normalisation par lots → Activation) * 10 → Couche de sortie C'est comme ça.
Il a peut-être été un peu difficile de mettre en place l'expérience, mais vous avez peut-être constaté qu'elle serait endommagée si vous n'utilisiez pas la normalisation par lots.
Recommended Posts