mirror of
https://github.com/Steffo99/unimore-bda-6.git
synced 2024-11-21 23:44:19 +00:00
Pong
This commit is contained in:
parent
7645596007
commit
bc0b5345b8
1 changed files with 106 additions and 1 deletions
107
README.md
107
README.md
|
@ -924,13 +924,116 @@ Attraverso di essi, la classe è in grado di costruire il [`tensorflow.data.Data
|
||||||
|
|
||||||
#### Lookup delle stringhe
|
#### Lookup delle stringhe
|
||||||
|
|
||||||
|
I modelli di deep learning di Tensorflow non sono in grado di processare direttamente stringhe; esse devono essere prima convertite in formato numerico.
|
||||||
|
|
||||||
|
All'inizializzazione, la struttura base crea un layer di tipo [`tensorflow.keras.layers.StringLookup`], che prende in input una lista di token e la converte in una lista di numeri interi, assegnando a ciascun token un numero diverso:
|
||||||
|
|
||||||
|
```python
|
||||||
|
...
|
||||||
|
|
||||||
|
def __init__(self, *, tokenizer: BaseTokenizer):
|
||||||
|
...
|
||||||
|
self.string_lookup_layer = tensorflow.keras.layers.StringLookup(max_tokens=TENSORFLOW_MAX_FEATURES)
|
||||||
|
...
|
||||||
|
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Prima dell'addestramento del modello, il layer deve essere adattato, ovvero deve costruire un vocabolario che associa ogni possibile termine ad un numero; qualsiasi token al di fuori da questo vocabolario verrà convertito in `0`.
|
||||||
|
|
||||||
|
Per esempio, `["ciao", "come", "stai", "?"]` potrebbe essere convertito in `[1, 2, 0, 3]` se il modello non è stato adattato con il token `"stai"`.
|
||||||
|
|
||||||
#### Addestramento
|
#### Addestramento
|
||||||
|
|
||||||
|
La struttura base `TensorflowSentimentAnalyzer` uniforma la fase di addestramento per tutti i modelli realizzandola attraverso le seguenti fasi:
|
||||||
|
|
||||||
|
1. Creazione di `tensorflow.data.Dataset` dalla cache del training set e del validation set
|
||||||
|
2. Adattamento del layer di string lookup
|
||||||
|
3. Fitting del modello per `TENSORFLOW_EPOCHS` epoche
|
||||||
|
|
||||||
|
```python
|
||||||
|
...
|
||||||
|
|
||||||
|
def train(self, training_dataset_func: CachedDatasetFunc, validation_dataset_func: CachedDatasetFunc) -> None:
|
||||||
|
training_set = self._build_dataset(training_dataset_func)
|
||||||
|
validation_set = self._build_dataset(validation_dataset_func)
|
||||||
|
|
||||||
|
vocabulary = training_set.map(lambda tokens, rating: tokens)
|
||||||
|
self.string_lookup_layer.adapt(vocabulary)
|
||||||
|
|
||||||
|
self.history: tensorflow.keras.callbacks.History | None = self.model.fit(
|
||||||
|
training_set,
|
||||||
|
validation_data=validation_set,
|
||||||
|
epochs=TENSORFLOW_EPOCHS.__wrapped__,
|
||||||
|
callbacks=[
|
||||||
|
tensorflow.keras.callbacks.TerminateOnNaN()
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(self.history.epoch) < TENSORFLOW_EPOCHS.__wrapped__:
|
||||||
|
self.failed = True
|
||||||
|
raise TrainingFailedError()
|
||||||
|
else:
|
||||||
|
self.trained = True
|
||||||
|
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Esplosione del gradiente
|
||||||
|
|
||||||
|
Il metodo `train` si occupa anche di gestire una situazione particolare: quella in cui l'errore del modello sul training set diventi `NaN` per via del fenomeno di [esplosione del gradiente].
|
||||||
|
|
||||||
|
Grazie al callback `tensorflow.keras.callbacks.TerminateOnNaN`, nel momento in cui viene riconosciuto che l'errore è diventato `NaN`, l'addestramento viene interrotto, e viene sollevato un `TrainingFailedError`.
|
||||||
|
|
||||||
|
Si è quindi aggiornato il main per gestire l'eccezione e ricominciare l'addestramento da capo qualora essa si verificasse:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Pseudo-codice non corrispondente al main finale
|
||||||
|
if __name__ == "__main__":
|
||||||
|
for sample_func in [sample_reviews_polar, sample_reviews_varied]:
|
||||||
|
for SentimentAnalyzer in [ThreeCheat, NLTKSentimentAnalyzer, ...]:
|
||||||
|
for Tokenizer in [PlainTokenizer, LowercaseTokenizer, PottsTokenizer, PottsTokenizerWithNegation, ...]:
|
||||||
|
runs = 0
|
||||||
|
successful_runs = 0
|
||||||
|
while True:
|
||||||
|
if runs >= MAXIMUM_RUNS or successful_runs >= TARGET_RUNS:
|
||||||
|
break
|
||||||
|
runs += 1
|
||||||
|
model = SentimentAnalyzer(tokenizer=Tokenizer())
|
||||||
|
try:
|
||||||
|
model.train(training_set=sample_func(amount=TRAINING_SET_SIZE), validation_set=sample_func(amount=VALIDATION_SET_SIZE))
|
||||||
|
except TrainingFailedError:
|
||||||
|
continue
|
||||||
|
model.evaluate(evaluation_set=sample_func(amount=EVALUATION_SET_SIZE))
|
||||||
|
successful_runs += 1
|
||||||
|
```
|
||||||
|
|
||||||
#### Utilizzo
|
#### Utilizzo
|
||||||
|
|
||||||
|
Anche l'utilizzo del modello è uniformato da `TensorflowSentimentAnalyzer`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
...
|
||||||
|
|
||||||
|
def use(self, text: str) -> float:
|
||||||
|
tokens = self.tokenizer.tokenize(text)
|
||||||
|
tokens = self._tokens_to_tensor(tokens)
|
||||||
|
prediction = self.model.predict(tokens, verbose=False)
|
||||||
|
prediction = self._prediction_to_rating(prediction)
|
||||||
|
return prediction
|
||||||
|
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Il testo passato in input viene tokenizzato dal tokenizzatore selezionato;
|
||||||
|
2. i token vengono trasformati in un tensore di stringhe;
|
||||||
|
3. il tensore di stringhe viene passato al modello, il primo layer del quale effettua string lookup;
|
||||||
|
4. il modello emette un output in forma di tensore;
|
||||||
|
5. il tensore viene convertito nel numero di stelle predetto.
|
||||||
|
|
||||||
### Creazione di un modello di regressione - `.analysis.tf_text.TensorflowPolarSentimentAnalyzer`
|
### Creazione di un modello di regressione - `.analysis.tf_text.TensorflowPolarSentimentAnalyzer`
|
||||||
|
|
||||||
### Creazione di un modello di categorizzazione - `.analysis.tf_text.TensorflowCategorySentimentAnalyzer`
|
### Creazione di un modello di categorizzazione - `.analysis.tf_text.TensorflowCategorySentimentAnalyzer`
|
||||||
### Esplosione del gradiente
|
|
||||||
|
|
||||||
## Implementazione di tokenizzatori di HuggingFace - `.tokenizer.hugging`
|
## Implementazione di tokenizzatori di HuggingFace - `.tokenizer.hugging`
|
||||||
|
|
||||||
|
@ -958,3 +1061,5 @@ Attraverso di essi, la classe è in grado di costruire il [`tensorflow.data.Data
|
||||||
[`tensorflow.data.Dataset`]: https://www.tensorflow.org/api_docs/python/tf/data/Dataset
|
[`tensorflow.data.Dataset`]: https://www.tensorflow.org/api_docs/python/tf/data/Dataset
|
||||||
[Keras]: https://www.tensorflow.org/api_docs/python/tf/keras
|
[Keras]: https://www.tensorflow.org/api_docs/python/tf/keras
|
||||||
[`tensorflow.Tensor`]: https://www.tensorflow.org/api_docs/python/tf/Tensor
|
[`tensorflow.Tensor`]: https://www.tensorflow.org/api_docs/python/tf/Tensor
|
||||||
|
[`tensorflow.keras.layers.StringLookup`]: https://www.tensorflow.org/api_docs/python/tf/keras/layers/StringLookup
|
||||||
|
[esplosione del gradiente]: https://towardsdatascience.com/the-vanishing-exploding-gradient-problem-in-deep-neural-networks-191358470c11
|
||||||
|
|
Loading…
Reference in a new issue