Java >> Java tutorial >  >> Tag >> return

Neuralt netværk returnerer NaN som output

Med et hurtigt kig og baseret på analysen af ​​dine multiplikatorvarianter ser det ud som om NaN er produceret af et aritmetisk underløb, forårsaget af at dine gradienter er for små (for tæt på absolut 0 ).

Dette er den mest mistænkelige del af koden:

 f[j + i * 7] = (rows[j][i] == 0 ? .5f : rows[j][i] == 1 ? 0f : 1f);

Hvis rows[j][i] == 1 derefter 0f er gemt. Jeg ved ikke, hvordan dette styres af det neurale netværk (eller endda java ), men matematisk set kan en float med begrænset størrelse ikke inkludere nul .

Også selvom din kode ville ændre 0f med noget ekstra salt ville disse matrixværdiers resultanter have en vis risiko for at blive for tæt på nul. På grund af begrænset præcision ved repræsentation af reelle tal kan værdier meget tæt på nul ikke repræsenteres , deraf NaN .

Disse værdier har et meget venligt navn:subnormale tal .

Ethvert tal, der ikke er nul, med størrelse mindre end det mindste normaltal er subnormalt .

IEEE_754

Som med IEEE 754-1985, anbefaler standarden 0 til signalering af NaN'er , 1 for stille NaN'er, så en signalerende NaN'er kan dæmpes ved kun at ændre denne bit til 1, mens det omvendte kunne give indkodningen af ​​en uendelighed.

Ovenstående tekst er vigtig her:ifølge standarden angiver du faktisk en NaN med en hvilken som helst 0f værdi gemt.

Selvom navnet er vildledende, Float.MIN_VALUE er en positiv værdi højere end 0 :

Det rigtige minimum float værdien er faktisk:-Float.MAX_VALUE .

Er matematik med flydende komma subnormalt?

Normalisering af gradienterne

Hvis du tjekker, er problemet kun på grund af 0f værdier, du kan bare ændre dem til andre værdier, der repræsenterer noget lignende; Float.MIN_VALUE , Float.MIN_NORMAL , og så videre. Noget som dette, også i andre mulige dele af koden, hvor dette scenarie kunne ske. Tag disse bare som eksempler, og leg med disse områder:

rows[j][i] == 1 ? Float.MIN_VALUE : 1f;

rows[j][i] == 1 ?  Float.MIN_NORMAL : Float.MAX_VALUE/2;

rows[j][i] == 1 ? -Float.MAX_VALUE/2 : Float.MAX_VALUE/2;

Alligevel kan dette også føre til en NaN , baseret på hvordan disse værdier ændres. Hvis det er tilfældet, bør du normalisere værdierne. Du kan prøve at anvende en GradientNormalizer for det. I din netværksinitialisering bør noget som dette defineres for hvert lag (eller for dem, der er problematiske ):

new NeuralNetConfiguration
  .Builder()
  .weightInit(WeightInit.XAVIER)
  (...)
  .layer(new DenseLayer.Builder().nIn(42).nOut(30).activation(Activation.RELU)
        .weightInit(WeightInit.XAVIER)
        .gradientNormalization(GradientNormalization.RenormalizeL2PerLayer) //this   
        .build())
  
  (...)

Der er forskellige normalisatorer, så vælg hvilken der passer bedst til dit skema, og hvilke lag der skal indeholde et. Mulighederne er:

Gradientnormalisering

  • RenormalizeL2PerLayer

    Omskaler gradienter ved at dividere med L2-normen for alle gradienter for laget.

  • RenormalizeL2PerParamType

    Omskaler gradienter ved at dividere med L2-normen for gradienterne, separat for hver type parameter i laget. Dette adskiller sig fra RenormalizeL2PerLayer ved, at hver parametertype (vægt, bias osv.) her normaliseres separat. Eksempelvis i et MLP/FeedForward-netværk (hvor G er gradientvektoren) er outputtet som følger:

    GOut_weight =G_weight / l2(G_weight) GOut_bias =G_bias / l2(G_bias)

  • ClipElementWiseAbsoluteValue

    Klip gradienterne på en per-element basis. Indstil g <- tegn(g) for hver gradient g max(maxAllowedValue,|g|).dvs., hvis en parametergradient har en absolut værdi, der er større end tærsklen, skal du afkorte den. For eksempel, hvis tærskel =5, så er værdier i området -55 er sat til 5.

  • ClipL2PerLayer

    Betinget renormalisering. Lidt magen til RenormalizeL2PerLayer skalerer denne strategi gradienterne, hvis og kun hvis L2-normen for gradienterne (for hele laget) overstiger en specificeret tærskel. Specifikt, hvis G er gradientvektor for laget, så:

    GOut =G hvis l2Norm(G) (dvs. ingen ændring) GOud =tærskel * G / l2Norm(G)

  • ClipL2PerParamType

    Betinget renormalisering. Meget lig ClipL2PerLayer, men i stedet for at klippe pr. lag, doclipping på hver parametertype separat. For eksempel i et tilbagevendende neuralt netværk klippes inputvægtgradienter, tilbagevendende vægtgradienter og biasgradient alle sammen separat.

Her du kan finde et komplet eksempel på anvendelsen af ​​disse GradientNormalizers .


Java tag