Verificação numérica de gradiente: Quão perto está o suficiente?

8

Eu fiz uma rede neural convolucional e queria verificar se meus gradientes estão sendo calculados corretamente usando a verificação numérica de gradiente. A questão é, quão perto está o suficiente?

Minha função de verificação apenas cospe a derivada calculada, a derivada numericamente aproximada, a diferença entre os dois e se os dois valores têm ou não o mesmo sinal (um sendo positivo e o outro negativo é um grande não-não) para cada peso.

A principal preocupação que tenho é que, para todas as camadas totalmente conectadas e todas as camadas convolucionais, exceto a primeira, as diferenças são semelhantes - os primeiros 9-13 caracteres dos dois números corresponderão. Parece bom o suficiente, certo? Mas, para pesos da primeira camada convolucional, às vezes recebo até 12 casas decimais para corresponder, mas também pode ser tão baixo quanto apenas 3. É o suficiente ou pode haver um possível erro?

Uma coisa boa a se notar é que o sinal dos dois valores está sempre correspondendo ao que é bom, portanto a rede sempre fará movimentos na direção certa, mesmo que a magnitude do movimento esteja um pouco fora. Mas essa é a questão ... há uma chance de que esteja desligado?

Frobot
fonte

Respostas:

9

O mais próximo que vi de abordar isso foi no tutorial da Stanford UFLDL, na seção de regressão softmax . Copiando a declaração principal:

A norma da diferença entre o gradiente numérica e seu gradiente analítico deve ser pequeno, da ordem de .109

Em python, o código seria algo parecido com isto:

norm(gradients - numericalGradients)/norm(gradients + numericalGradients)

onde gradientsvocê é o resultado da derivada e numericalGradientsos gradientes aproximados.

cdeterman
fonte
Obrigado, e se meus gradientes forem armazenados em uma matriz de matriz 2D? Depois de subtrair 2 matrizes uma da outra, como devo avaliar a norma da matriz "diferença" resultante?
Kari
1
@Kari Eu os achataria em vetores e usaria o mesmo código mostrado acima. Por exemplo, se você tiver uma matriz numpy, poderá usar o flattenmétodo
cdeterman
7

Teoria de fundo útil

Um pequeno fato que você pode usar para ajudar a entender se uma derivada numérica é corretamente calculada ou não é o restante de Cauchy da expansão de Taylor. Isso é,

ξ[x,x+H]f(x+h)=f(x)+hf(x)+h22f(ξ)ξ[x,x+h]

Isso é útil, porque você provavelmente aproximou sua primeira derivada

f(x)f(x+h)f(xh)2h

com algum pequeno (normalmente uso , mas tenho certeza de que algum dia encontrarei um caso em que isso não é apropriado).10 - 4h104

Após um pouco de álgebra, podemos usar o restante de Cauchy para ver que nossa aproximação numérica teoricamente deve estar dentro de de .f ' ( x )hf(ξ),ξ[xh,x+h]f(x)

Na verdade, é possível lo por , onde e ... o que é equivalente a , .ξ 1[ x - h , X ] ξ 2[ x , x + H ] h 2 f ( ξ ) ξ [ x - h , x + h ]h(f(ξ1)f(ξ2))ξ1[xh,x]ξ2[x,x+h]h2f(ξ)ξ[xh,x+h]

Problemas na Prática

Ok, temos uma teoria legal delimitando o erro da derivada numérica. Mas existem dois buracos na tentativa direta de usar esses resultados:

1.) Não sabemos (e provavelmente não queremos gastar o tempo aproximando-o)f(x)

2.) como , sofre instabilidade numéricaf ( x + h ) - f ( x - h )h0f(x+h)f(xh)2h

Então, usando o que sabemos de mais cedo o caminho que eu verificar meus derivados analíticas (que pode não ser a melhor maneira) é que eu escrever a função derivada numérica em função da . Se não souber se a diferença entre as derivadas numéricas e analíticas se deve a um erro de codificação ou apenas à aproximação numérica, posso reduzir e ver se minha derivada numérica se aproxima da derivada analítica antes de sofrer instabilidade numérica (quando isso acontece, suas aproximações numéricas se tornarão menos consistentes à medida que ficar menor). Observe que o termo deve estar desaparecendo quadraticamente, portanto, se o erro for de comh h f ( ξ ) 0,01 h = 10 - 4 0,0001 h = 10 - 5hhhf(ξ)0.01h=104 , deve estar em torno de com assumindo que a instabilidade numérica ainda não foi ativada .0.0001h=105

Infelizmente, não há diretrizes rígidas e rápidas para sempre determinar essas coisas; depende muito de quão estável é a função (e eu quero dizer, tanto em termos de estabilidade numérica quanto de derivadas mais altas). Mas nas minhas experiências, nunca vi um caso em que o erro de não estivesse definitivamente indo para 0 (ou seja, usar deu praticamente a mesma resposta que ) no momento em que a instabilidade numérica de entrou em ação.h = 10 - 4 h = 10 - 5 h 0h2f(ξ)h=104h=105h0

Cliff AB
fonte
5

Consulte este tutorial http://cs231n.github.io/neural-networks-3/#ensemble . A seção "Verificação de gradiente" é muito detalhada e útil.

Como sugerido pelo gung, eu incluo os principais pontos deste link:

  • Use aproximação, onde .f(w+h)f(wh)2hh105

  • Monitore a fração de , onde é o gradiente analítico e é o gradiente numericamente aproximado. Geralmente, o intervalo preferido dessa fração deve . fa (w)fn (w)<10-2|fa(w)fn(w)|max(|fa(w)|,|fn(w)|)fa(w)fn(w)<102

  • Use precisão dupla em vez de flutuar.

  • Mente de distorção (s) nas funções de ativação, por exemplo, quando alguém usa ReLU. Quando houver dobras, é necessário monitorar os valores de e . Se esses dois valores estiverem nos dois lados de uma torção, deve-se excluir essa verificação de gradiente.x - h x + hx=0xhx+h

  • Use alguns pontos de dados.

  • Não faça a verificação de gradiente no estágio inicial do processo de treinamento.

  • Primeiro verifique o modelo sem regularização e depois com ele.

  • Desative o abandono e o abandono invertido ao fazer a verificação de gradiente.

  • Apenas verifique aleatoriamente poucas dimensões.

Fengchong Wang
fonte