Ml

negatívny odber vzoriek a celková strata

Negative Sampling Nce Loss



1. Kontrastný odhad šumu (NCE)

V jazykovom modeli posledná vrstva často vyžaduje: Podľa kontextu c predikujte pravdepodobnosť slova w v celom korpuse V, zvyčajne vo forme softmaxu

obrázok


Účelom funkcie rozdelenia Z (c) je normalizovať tak, aby p bolo rozdelenie pravdepodobnosti. Vyššie uvedené parametre sa vo všeobecnosti odhadujú podľa metódy maximálnej pravdepodobnosti, ale výpočtová veľkosť tohto vzorca je obrovská, pretože musí prechádzať všetkými slovami vo V.

V tejto dobe je na pódiu NCE. Aby sa zabránilo obrovskému množstvu výpočtov, myšlienka NCE je Problém odhadu parametrov softmaxu sa transformuje do dvoch klasifikácií. Dva typy vzoriek sú skutočné vzorky a vzorky šumu: pozitívne vzorky sú empiricky rozdelené



obrázok
Generovaná značka (tj skutočná distribúcia) D = 0 a negatívna vzorka je šum generovaný q (w) zodpovedajúci značke D = 1. Za predpokladu, že c predstavuje kontext, sú vzorky šumu k extrahované z distribúcie šumu a w predstavuje predpovedané cieľové slovo v celkovej vzorke (skutočná vzorka + vzorka šumu).
Potom je spoločné rozdelenie pravdepodobnosti (d, w) nasledovné:



obrázok
Nie je ťažké získať z vyššie uvedeného vzorca: P (w / c) = p (d = 0, w / c) + p (d = 1, w / c) v celkovej vzorke

Tipy: P označuje celkové rozdelenie pozitívnych a negatívnych vzoriek, ktoré je rovnaké ako predchádzajúce empirické rozdelenie pozitívnych vzoriek obrázokrôzne

Pokračujte podľa vzorca podmieneného spoločného pravdepodobnosti, môžeme získať: p (d = 0 / w, c) = p (d = 0, w / c) / p (w / c)

p (d = 1 / hmot., c) podobné

je nasledujúci vzorec:



obrázok
Tento vzorec sa v skutočnosti chápe priamo na základe podmienenej pravdepodobnosti.

Distribúcia modelu využitia NCE obrázok
namiesto distribúcie skúseností obrázokV tomto okamihu je spojená so softmaxom spomenutým na začiatku a optimálny parameter theta sa získa maximalizáciou pravdepodobnosti. Ale problém tu stále nie je vyriešený, pretože obrázokRovnako ako počiatočný vzorec je potrebné prekonať celé V a vypočítať funkciu rozdelenia Z ©.

    NCE ďalej navrhla dve hypotézy:
  1. Funkciu rozdelenia Z (c) nie je potrebné získať prechodom V, ale je odhadnutá parametrom Zc
  2. Pretože neurónová sieť má veľa parametrov, Zc je možné nastaviť na pevnú hodnotu Zc = 1, toto nastavenie platí pre všetky c ([Mnih and Teh2012])

Na základe vyššie uvedených predpokladov možno vzorec ďalej napísať ako:




Potom sa parametre trénujú podľa maximalizácie pravdepodobnosti logu, kde je vybraných k negatívnych vzoriek, potom je funkcia straty:


Druhý termín je stále ťažké vypočítať, pretože zahŕňa k Očakávanie (E), Preto sa tu na odhad aproximácie Monte Carlo používa aproximácia Monte Carlo a namiesto k sa odoberajú vzorky k očakávať:

2. Negatívne vzorkovanie

Negatívny výber je variantom NCE a definícia pravdepodobnosti je iná:


Pre vzorec pravdepodobnosti NCE: Ak k = | V | a q je rovnomerne rozdelené, potom k * q = 1 a dva pravdepodobnostné vzorce sú rovnaké.

Okrem vyššie uvedeného sú však dva vzorce pravdepodobnosti odlišné. Aj keď negatívne vzorkovanie funguje dobre vo vektoroch slov, negatívne vzorkovanie stále nemôže mať vlastnosti NCE (napríklad záruky asymptotickej konzistencie).

Tri, nce strata v tensorflow

Jeden, výpočet straty

Po získaní k negatívnych vzoriek negatívnym vzorkovaním, potom pre každú vzorku buď štítok pozitívnej vzorky = 1, alebo štítok negatívnej vzorky = 0. Zmeňte maximálny log poslednej straty NCE vyššie tak, aby sa minimalizoval log, potom sa stratová funkcia NCE dá vyjadriť ako dvojtriedna logistická strata (krížová entropia):

    používa symboly v tensorflow:
  1. x = logits znamená u (w, c) vo vyššie uvedenom, ktorý je produktom poslednej vrstvy (zodpovedajúcej slovu w) sieťových parametrov a slova vektora c
  2. z = označí pozitívnu vzorku = 1, negatívnu vzorku = 0
  3. Vyššie uvedené logity a značky sú vektory a matice, ktoré reprezentujú všetky vzorky (vrátane pozitívnych vzoriek a vzorkovaných negatívnych vzoriek)

    Potom možno stratovú funkciu vyjadriť ako:
    L = z * -log (sigmoid (x)) + (1 - z) * -log (1 - sigmoid (x))
Aby sa zabránilo pretečeniu spôsobenému výpočtom exp, vykoná sa jednoduchá transformácia v tensorflow:
 z * -log(sigmoid(x)) + (1 - z) * -log(1 - sigmoid(x)) = z * -log(1 / (1 + exp(-x))) + (1 - z) * -log(exp(-x) / (1 + exp(-x))) = z * log(1 + exp(-x)) + (1 - z) * (-log(exp(-x)) + log(1 + exp(-x))) = z * log(1 + exp(-x)) + (1 - z) * (x + log(1 + exp(-x)) = (1 - z) * x + log(1 + exp(-x)) = x - x * z + log(1 + exp(-x)) When x<0: For x 0 and x<0, the following formula is obtained: Hence, to ensure stability and avoid overflow, the implementation uses this equivalent formulation max(x, 0) - x * z + log(1 + exp(-abs(x))) 

Po druhé, zdrojový kód na výpočet krížovej entropie

Kód na výpočet straty na základe štítkov a logitov: https: //github.com/tensorflow/tensorflow/blob/r1.13/tensorflow/python/ops/nn_impl.py def sigmoid_cross_entropy_with_logits( # pylint: disable=invalid-name _sentinel=None, labels=None, logits=None, name=None): '''Computes sigmoid cross entropy given `logits`. Args: _sentinel: Used to prevent positional parameters. Internal, do not use. labels: A `Tensor` of the same type and shape as `logits`. logits: A `Tensor` of type `float32` or `float64`. name: A name for the operation (optional). Returns: A `Tensor` of the same shape as `logits` with the componentwise logistic losses. nn_ops._ensure_xent_args('sigmoid_cross_entropy_with_logits', _sentinel, labels, logits) # pylint: enable=protected-access with ops.name_scope(name, 'logistic_loss', [logits, labels]) as name: logits = ops.convert_to_tensor(logits, name='logits') labels = ops.convert_to_tensor(labels, name='labels') try: labels.get_shape().merge_with(logits.get_shape()) except ValueError: raise ValueError('logits and labels must have the same shape (%s vs %s)' % (logits.get_shape(), labels.get_shape())) # The logistic loss formula from above is # x - x * z + log(1 + exp(-x)) # For x <0, a more numerically stable formula is # -x * z + log(1 + exp(x)) # Note that these two expressions can be combined into the following: # max(x, 0) - x * z + log(1 + exp(-abs(x))) # To allow computing gradients at zero, we define custom versions of max and # abs functions. zeros = array_ops.zeros_like(logits, dtype=logits.dtype) cond = (logits>= zeros) relu_logits = array_ops.where(cond, logits, zeros) neg_abs_logits = array_ops.where(cond, -logits, logits) return math_ops.add( relu_logits - logits * labels, math_ops.log1p(math_ops.exp(neg_abs_logits)), name=name)

Tri, negatívny odber vzoriek, výpočet logitov a štítok

Prvá vzorka podľa tf.nn.log_uniform_candidate_sampler (bežná metóda vzorkovania) a získajte počet negatívnych vzoriek:

V lingvistike sa slová podľa ich frekvencie výskytu riadia podľa Zipfianovej distribúcie, (ale či sú rovnako vhodné aj iné scenáre, ktoré sa majú preskúmať), na vzorkovanie použite logicko-uniformné (Zipfianove) rozdelenie, takže slová musia byť vysoká až nízka frekvencia Nízka úroveň, to znamená, že pri konštrukcii vkladania sa zostavuje podľa frekvencie slov.
nn.log_uniform_candidate_sampler používa tento vzorec na vzorkovanie P (trieda) = (log (trieda + 2) -log (trieda + 1)) / log (rozsah_max + 1), hodnota triedy Čím väčšia je pravdepodobnosť P, tým menšia je je, takže túto metódu nemožno použiť, ak nie je zoradená podľa frekvencie.

    Ďalším krokom je výpočet logitov a označení všetkých vzoriek. Je potrebné poznamenať nasledujúce body:
  1. logity: vektor * vstupy zodpovedajúce vzorkám v hmotnostných maticových hmotnostiach poslednej vrstvy
  2. štítok: (1) Negatívna vzorka vo vzorke je 0 (2) V predvolenom nastavení vstupy zodpovedajú iba pozitívnej vzorke a štítku = 1, ale ak je počet_množstiev> 0, potom štítok = 1 / počet_množstiev každej pozitívnej vzorky
def _compute_sampled_logits(weights, biases, labels, inputs, num_sampled, num_classes, num_true=1, sampled_values=None, subtract_log_q=True, remove_accidental_hits=False, partition_strategy='mod', name=None, seed=None): '''Helper function for nce_loss and sampled_softmax_loss functions. Computes sampled output training logits and labels suitable for implementing e.g. noise-contrastive estimation (see nce_loss) or sampled softmax (see sampled_softmax_loss). Note: In the case where num_true > 1, we assign to each target class the target probability 1 / num_true so that the target probabilities sum to 1 per-example. Args: weights: A `Tensor` of shape `[num_classes, dim]`, or a list of `Tensor` objects whose concatenation along dimension 0 has shape `[num_classes, dim]`. The (possibly-partitioned) class embeddings. biases: A `Tensor` of shape `[num_classes]`. The (possibly-partitioned) class biases. labels: A `Tensor` of type `int64` and shape `[batch_size, num_true]`. The target classes. Note that this format differs from the `labels` argument of `nn.softmax_cross_entropy_with_logits_v2`. inputs: A `Tensor` of shape `[batch_size, dim]`. The forward activations of the input network. num_sampled: An `int`. The number of classes to randomly sample per batch. num_classes: An `int`. The number of possible classes. num_true: An `int`. The number of target classes per training example. sampled_values: a tuple of (`sampled_candidates`, `true_expected_count`, `sampled_expected_count`) returned by a `*_candidate_sampler` function. (if None, we default to `log_uniform_candidate_sampler`) subtract_log_q: A `bool`. whether to subtract the log expected count of the labels in the sample to get the logits of the true labels. Default is True. Turn off for Negative Sampling. remove_accidental_hits: A `bool`. whether to remove 'accidental hits' where a sampled class equals one of the target classes. Default is False. partition_strategy: A string specifying the partitioning strategy, relevant if `len(weights) > 1`. Currently `'div'` and `'mod'` are supported. Default is `'mod'`. See `tf.nn.embedding_lookup` for more details. name: A name for the operation (optional). seed: random seed for candidate sampling. Default to None, which doesn't set the op-level random seed for candidate sampling. Returns: out_logits: `Tensor` object with shape `[batch_size, num_true + num_sampled]`, for passing to either `nn.sigmoid_cross_entropy_with_logits` (NCE) or `nn.softmax_cross_entropy_with_logits_v2` (sampled softmax). out_labels: A Tensor object with the same shape as `out_logits`. '''

Štyri, zdrojový kód straty NCE

Kombináciou vyššie uvedených dvoch častí môžete priamo vypočítať stratu NCE: najskôr vypočítajte logity a štítky všetkých vzoriek (tretí krok) a potom vypočítajte stratu krížovej entropie (druhý krok). def nce_loss(weights, biases, labels, inputs, num_sampled, num_classes, num_true=1, sampled_values=None, remove_accidental_hits=False, partition_strategy='mod', name='nce_loss'): '''Computes and returns the noise-contrastive estimation training loss. See [Noise-contrastive estimation: A new estimation principle for unnormalized statistical models](http://www.jmlr.org/proceedings/papers/v9/gutmann10a/gutmann10a.pdf). Also see our [Candidate Sampling Algorithms Reference](https://www.tensorflow.org/extras/candidate_sampling.pdf) A common use case is to use this method for training, and calculate the full sigmoid loss for evaluation or inference. In this case, you must set `partition_strategy='div'` for the two losses to be consistent, as in the Note: In the case where `num_true` > 1, we assign to each target class the target probability 1 / `num_true` so that the target probabilities sum to 1 per-example. Note: It would be useful to allow a variable number of target classes per example. We hope to provide this functionality in a future release. For now, if you have a variable number of target classes, you can pad them out to a constant number by either repeating them or by padding with an otherwise unused class. Args: weights: A `Tensor` of shape `[num_classes, dim]`, or a list of `Tensor` objects whose concatenation along dimension 0 has shape [num_classes, dim]. The (possibly-partitioned) class embeddings. biases: A `Tensor` of shape `[num_classes]`. The class biases. labels: A `Tensor` of type `int64` and shape `[batch_size, num_true]`. The target classes. inputs: A `Tensor` of shape `[batch_size, dim]`. The forward activations of the input network. num_sampled: An `int`. The number of negative classes to randomly sample per batch. This single sample of negative classes is evaluated for each element in the batch. num_classes: An `int`. The number of possible classes. num_true: An `int`. The number of target classes per training example. sampled_values: a tuple of (`sampled_candidates`, `true_expected_count`, `sampled_expected_count`) returned by a `*_candidate_sampler` function. (if None, we default to `log_uniform_candidate_sampler`) remove_accidental_hits: A `bool`. Whether to remove 'accidental hits' where a sampled class equals one of the target classes. If set to `True`, this is a 'Sampled Logistic' loss instead of NCE, and we are learning to generate log-odds instead of log probabilities. See our [Candidate Sampling Algorithms Reference] (https://www.tensorflow.org/extras/candidate_sampling.pdf). Default is False. partition_strategy: A string specifying the partitioning strategy, relevant if `len(weights) > 1`. Currently `'div'` and `'mod'` are supported. Default is `'mod'`. See `tf.nn.embedding_lookup` for more details. name: A name for the operation (optional). Returns: A `batch_size` 1-D tensor of per-example NCE losses. ''' logits, labels = _compute_sampled_logits( weights=weights, biases=biases, labels=labels, inputs=inputs, num_sampled=num_sampled, num_classes=num_classes, num_true=num_true, sampled_values=sampled_values, subtract_log_q=True, remove_accidental_hits=remove_accidental_hits, partition_strategy=partition_strategy, name=name) sampled_losses = sigmoid_cross_entropy_with_logits( labels=labels, logits=logits, name='sampled_losses') # sampled_losses is batch_size x {true_loss, sampled_losses...} # We sum out true and sampled losses. return _sum_rows(sampled_losses)

referencie:

[Mnih and Teh2012] Andriy Mnih a Yee Whye Teh. 2012. Rýchly a jednoduchý algoritmus na trénovanie neurálnych probabilistických jazykových modelov. V Proc. ICML.

Poznámky k odhadu kontrastu a negatívnemu vzorkovaniu ( https://arxiv.org/pdf/1410.8251.pdf)

https://knet.readthedocs.io/en/v0.7.3/deprecated/nce.html