Merge pull request #287 from robertopauletto/main

Italian translation - Chapter 6 complete
pull/294/head
Jen Looper 3 years ago committed by GitHub
commit 4dbfa4f31d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,165 @@
# Introduzione all'elaborazione del linguaggio naturale
Questa lezione copre una breve storia e concetti importanti dell' *elaborazione del linguaggio naturale*, un sottocampo della *linguistica computazionale*.
## [Quiz Pre-Lezione](https://jolly-sea-0a877260f.azurestaticapps.net/quiz/31/)
## Introduzione
NLP, come è comunemente conosciuto, è una delle aree più note in cui machine learning è stato applicato e utilizzato nei software di produzione.
✅ Si riesce a pensare a un software che si usa tutti i giorni che probabilmente ha NLP incorporato? Che dire dei programmi di elaborazione testi o le app mobili che si usano regolarmente?
Si imparerà a conoscere:
- **L'idea delle lingue**. Come si sono sviluppate le lingue e quali sono state le principali aree di studio.
- **Definizione e concetti**. Si impareranno anche definizioni e concetti su come i computer elaborano il testo, inclusa l'analisi, la grammatica e l'identificazione di nomi e verbi. Ci sono alcune attività di codifica in questa lezione e vengono introdotti diversi concetti importanti che si imparerà a codificare più avanti nelle lezioni successive.
## Linguistica computazionale
La linguistica computazionale è un'area di ricerca e sviluppo che da molti decenni studia come i computer possono lavorare e persino capire, tradurre e comunicare con le lingue. L'elaborazione del linguaggio naturale (NLP) è un campo correlato incentrato su come i computer possono elaborare le lingue "naturali" o umane.
### Esempio: dettatura telefonica
Se si è mai dettato al telefono invece di digitare o posto una domanda a un assistente virtuale, il proprio discorso è stato convertito in formato testuale e quindi elaborato o *analizzato* dalla lingua con la quale si è parlato. Le parole chiave rilevate sono state quindi elaborate in un formato che il telefono o l'assistente possono comprendere e utilizzare.
![comprensione](../images/comprehension.png)
> La vera comprensione linguistica è difficile! Immagine di [Jen Looper](https://twitter.com/jenlooper)
### Come è resa possibile questa tecnologia?
Questo è possibile perché qualcuno ha scritto un programma per computer per farlo. Alcuni decenni fa, alcuni scrittori di fantascienza prevedevano che le persone avrebbero parlato principalmente con i loro computer e che i computer avrebbero sempre capito esattamente cosa intendevano. Purtroppo, si è rivelato essere un problema più difficile di quanto molti immaginavano, e sebbene sia un problema molto meglio compreso oggi, ci sono sfide significative nel raggiungere un'elaborazione del linguaggio naturale "perfetta" quando si tratta di comprendere il significato di una frase. Questo è un problema particolarmente difficile quando si tratta di comprendere l'umore o rilevare emozioni come il sarcasmo in una frase.
A questo punto, si potrebbero ricordare le lezioni scolastiche in cui l'insegnante ha coperto le parti della grammatica in una frase. In alcuni paesi, agli studenti viene insegnata la grammatica e la linguistica come materie dedicate, ma in molti questi argomenti sono inclusi nell'apprendimento di una lingua: o la prima lingua nella scuola primaria (imparare a leggere e scrivere) e forse una seconda lingua in post-primario o liceo. Non occorre preoccuparsi se non si è esperti nel distinguere i nomi dai verbi o gli avverbi dagli aggettivi!
Se si fa fatica a comprendere la differenza tra il *presente semplice* e il *presente progressivo*, non si è soli. Questa è una cosa impegnativa per molte persone, anche madrelingua di una lingua. La buona notizia è che i computer sono davvero bravi ad applicare regole formali e si imparerà a scrivere codice in grado di *analizzare* una frase così come un essere umano. La sfida più grande che si esaminerà in seguito è capire il *significato* e il *sentimento* di una frase.
## Prerequisiti
Per questa lezione, il prerequisito principale è essere in grado di leggere e comprendere la lingua di questa lezione. Non ci sono problemi di matematica o equazioni da risolvere. Sebbene l'autore originale abbia scritto questa lezione in inglese, è anche tradotta in altre lingue, quindi si potrebbe leggere una traduzione. Ci sono esempi in cui vengono utilizzati un numero di lingue diverse (per confrontare le diverse regole grammaticali di lingue diverse). Questi *non* sono tradotti, ma il testo esplicativo lo è, quindi il significato dovrebbe essere chiaro.
Per le attività di codifica, si utilizzerà Python e gli esempi utilizzano Python 3.8.
In questa sezione servirà e si utilizzerà:
- **Comprensione del linguaggio Python 3**. Questa lezione utilizza input, loop, lettura di file, array.
- **Visual Studio Code + estensione**. Si userà Visual Studio Code e la sua estensione Python. Si può anche usare un IDE Python a propria scelta.
- **TextBlob**. [TextBlob](https://github.com/sloria/TextBlob) è una libreria di elaborazione del testo semplificata per Python. Seguire le istruzioni sul sito TextBlob per installarlo sul proprio sistema (installare anche i corpora, come mostrato di seguito):
```bash
pip install -U textblob
python -m textblob.download_corpora
```
> 💡 Suggerimento: si può eseguire Python direttamente negli ambienti VS Code. Controllare la [documentazione](https://code.visualstudio.com/docs/languages/python?WT.mc_id=academic-15963-cxa) per ulteriori informazioni.
## Parlare con le macchine
La storia del tentativo di far capire ai computer il linguaggio umano risale a decenni fa e uno dei primi scienziati a considerare l'elaborazione del linguaggio naturale è stato *Alan Turing*.
### Il Test di Turing.
Quando Turing stava facendo ricerche sull'*intelligenza artificiale* negli anni '50, considerò se un test di conversazione potesse essere somministrato a un essere umano e a un computer (tramite corrispondenza digitata) in cui l'essere umano nella conversazione non era sicuro se stesse conversando con un altro umano o un computer.
Se, dopo una certa durata di conversazione, l'essere umano non è riuscito a determinare se le risposte provenivano da un computer o meno, allora si potrebbe dire che il computer *sta pensando*?
### L'ispirazione - 'il gioco dell'imitazione'
L'idea è nata da un gioco di società chiamato *The Imitation Game* in cui un interrogatore è da solo in una stanza e ha il compito di determinare quale delle due persone (in un'altra stanza) sono rispettivamente maschio e femmina. L'interrogatore può inviare note e deve cercare di pensare a domande in cui le risposte scritte rivelano il sesso della persona misteriosa. Ovviamente, i giocatori nell'altra stanza stanno cercando di ingannare l'interrogatore rispondendo alle domande in modo tale da fuorviare o confondere l'interrogatore, dando anche l'impressione di rispondere onestamente.
### Lo sviluppo di Eliza
Negli anni '60 uno scienziato del MIT chiamato *Joseph* Weizenbaum sviluppò [*Eliza*](https:/wikipedia.org/wiki/ELIZA), un "terapista" informatico che poneva domande a un umano e dava l'impressione di comprendere le loro risposte. Tuttavia, mentre Eliza poteva analizzare una frase e identificare alcuni costrutti grammaticali e parole chiave in modo da dare una risposta ragionevole, non si poteva dire *che capisse* la frase. Se a Eliza viene presentata una frase che segue il formato "**Sono** _triste_", potrebbe riorganizzare e sostituire le parole nella frase per formare la risposta "Da quanto tempo **sei** _triste_".
Questo dava l'impressione che Eliza avesse capito la frase e stesse facendo una domanda successiva, mentre in realtà stava cambiando il tempo e aggiungendo alcune parole. Se Eliza non fosse stata in grado di identificare una parola chiave per la quale aveva una risposta, avrebbe dato invece una risposta casuale che potrebbe essere applicabile a molte frasi diverse. Eliza avrebbe potuto essere facilmente ingannata, ad esempio se un utente avesse scritto "**Sei** una _bicicletta_" avrebbe potuto rispondere con "Da quanto tempo **sono** una _bicicletta_?", invece di una risposta più ragionata.
[![Chiacchierare conEliza](https://img.youtube.com/vi/RMK9AphfLco/0.jpg)](https://youtu.be/RMK9AphfLco " Chiaccherare con Eliza")
> 🎥 Fare clic sull'immagine sopra per un video sul programma ELIZA originale
> Nota: si può leggere la descrizione originale di [Eliza](https://cacm.acm.org/magazines/1966/1/13317-elizaa-computer-program-for-the-study-of-natural-language-communication-between-man-and-machine/abstract) pubblicata nel 1966 se si dispone di un account ACM. In alternativa, leggere di Eliza su [wikipedia](https://it.wikipedia.org/wiki/ELIZA_(chatterbot))
## Esercizio: codificare un bot conversazionale di base
Un bot conversazionale, come Eliza, è un programma che sollecita l'input dell'utente e sembra capire e rispondere in modo intelligente. A differenza di Eliza, questo bot non avrà diverse regole che gli danno l'impressione di avere una conversazione intelligente. Invece, il bot avrà una sola capacità, per mantenere viva la conversazione con risposte casuali che potrebbero funzionare in quasi tutte le conversazioni banali.
### Il piano
I passaggi durante la creazione di un bot conversazionale:
1. Stampare le istruzioni che consigliano all'utente come interagire con il bot
2. Iniziare un ciclo
1. Accettare l'input dell'utente
2. Se l'utente ha chiesto di uscire, allora si esce
3. Elaborare l'input dell'utente e determinare la risposta (in questo caso, la risposta è una scelta casuale da un elenco di possibili risposte generiche)
4. Stampare la risposta
3. Riprendere il ciclo dal passaggio 2
### Costruire il bot
Si crea il bot. Si inizia definendo alcune frasi.
1. Creare questo bot in Python con le seguenti risposte casuali:
```python
random_responses = ["That is quite interesting, please tell me more.",
"I see. Do go on.",
"Why do you say that?",
"Funny weather we've been having, isn't it?",
"Let's change the subject.",
"Did you catch the game last night?"]
```
Ecco un esempio di output come guida (l'input dell'utente è sulle righe che iniziano con `>`):
```output
Hello, I am Marvin, the simple robot.
You can end this conversation at any time by typing 'bye'
After typing each answer, press 'enter'
How are you today?
> I am good thanks
That is quite interesting, please tell me more.
> today I went for a walk
Did you catch the game last night?
> I did, but my team lost
Funny weather we've been having, isn't it?
> yes but I hope next week is better
Let's change the subject.
> ok, lets talk about music
Why do you say that?
> because I like music!
Why do you say that?
> bye
It was nice talking to you, goodbye!
```
Una possibile soluzione al compito è [qui](../solution/bot.py)
✅ Fermarsi e riflettere
1. Si ritiene che le risposte casuali "ingannerebbero" qualcuno facendogli pensare che il bot le abbia effettivamente capite?
2. Di quali caratteristiche avrebbe bisogno il bot per essere più efficace?
3. Se un bot potesse davvero "capire" il significato di una frase, avrebbe bisogno di "ricordare" anche il significato delle frasi precedenti in una conversazione?
---
## 🚀 Sfida
Scegliere uno degli elementi "fermarsi e riflettere" qui sopra e provare a implementarli nel codice o scrivere una soluzione su carta usando pseudocodice.
Nella prossima lezione si impareranno una serie di altri approcci all'analisi del linguaggio naturale e dell'machine learning.
## [Quiz post-lezione](https://jolly-sea-0a877260f.azurestaticapps.net/quiz/32/)
## Revisione e Auto Apprendimento
Dare un'occhiata ai riferimenti di seguito come ulteriori opportunità di lettura.
### Bibliografia
1. Schubert, Lenhart, "Computational Linguistics", *The Stanford Encyclopedia of Philosophy* (Edizione primavera 2020), Edward N. Zalta (a cura di), URL = <https://plato.stanford.edu/archives/spr2020/entries/computational-linguistics/>.
2. Università di Princeton "About WordNet". [WordNet](https://wordnet.princeton.edu/). Princeton University 2010.
## Compito
[Cercare un bot](assignment.it.md)

@ -0,0 +1,11 @@
# Cercare un bot
## Istruzioni
I bot sono ovunque. Il compito: trovarne uno e adottarlo! È possibile trovarli sui siti web, nelle applicazioni bancarie e al telefono, ad esempio quando si chiamano società di servizi finanziari per consigli o informazioni sull'account. Analizzare il bot e vedire se si riesce a confonderlo. Se si riesce a confondere il bot, perché si pensa sia successo? Scrivere un breve articolo sulla propria esperienza.
## Rubrica
| Criteri | Ottimo | Adeguato | Necessita miglioramento |
| -------- | ------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | --------------------- |
| | Viene scritto un documento a pagina intera, che spiega la presunta architettura del bot e delinea l'esperienza con esso | Un documento è incompleto o non ben concepito | Nessun documento inviato |

@ -0,0 +1,214 @@
# Compiti e tecniche comuni di elaborazione del linguaggio naturale
Per la maggior parte delle attività di *elaborazione del linguaggio naturale* , il testo da elaborare deve essere suddiviso, esaminato e i risultati archiviati o incrociati con regole e insiemi di dati. Queste attività consentono al programmatore di derivare il _significato_ o l'_intento_ o solo la _frequenza_ di termini e parole in un testo.
## [Quiz Pre-Lezione](https://jolly-sea-0a877260f.azurestaticapps.net/quiz/33/)
Si esaminano le comuni tecniche utilizzate nell'elaborazione del testo. Combinate con machine learning, queste tecniche aiutano ad analizzare grandi quantità di testo in modo efficiente. Prima di applicare machine learning a queste attività, tuttavia, occorre cercare di comprendere i problemi incontrati da uno specialista in NLP.
## Compiti comuni per NLP
Esistono diversi modi per analizzare un testo su cui si sta lavorando. Ci sono attività che si possono eseguire e attraverso le quali si è in grado di valutare la comprensione del testo e trarre conclusioni. Di solito si eseguono queste attività in sequenza.
### Tokenizzazione
Probabilmente la prima cosa che la maggior parte degli algoritmi di NLP deve fare è dividere il testo in token o parole. Anche se questo sembra semplice, dover tenere conto della punteggiatura e dei delimitatori di parole e frasi di lingue diverse può renderlo complicato. Potrebbe essere necessario utilizzare vari metodi per determinare le demarcazioni.
![Tokenizzazione](../images/tokenization.png)
> Tokenizzazione di una frase da **Orgoglio e Pregiudizio**. Infografica di [Jen Looper](https://twitter.com/jenlooper)
### Embedding
I [word embeddings](https://it.wikipedia.org/wiki/Word_embedding) sono un modo per convertire numericamente i dati di testo. Gli embedding vengono eseguiti in modo tale che le parole con un significato simile o le parole usate insieme vengano raggruppate insieme.
![word embeddings](../images/embedding.png)
> "I have the highest respect for your nerves, they are my old friends." - Incorporazioni di parole per una frase in **Orgoglio e Pregiudizio**. Infografica di [Jen Looper](https://twitter.com/jenlooper)
✅ Provare [questo interessante strumento](https://projector.tensorflow.org/) per sperimentare i word embedding. Facendo clic su una parola vengono visualizzati gruppi di parole simili: gruppi di "toy" con "disney", "lego", "playstation" e "console".
### Analisi e codifica di parti del discorso
Ogni parola che è stata tokenizzata può essere etichettata come parte del discorso: un sostantivo, un verbo o un aggettivo. La frase `the quick red fox jumped over the lazy brown dog` potrebbe essere etichettata come fox = sostantivo, jumped = verbo.
![elaborazione](../images/parse.png)
> Analisi di una frase da **Orgoglio e Pregiudizio**. Infografica di [Jen Looper](https://twitter.com/jenlooper)
L'analisi consiste nel riconoscere quali parole sono correlate tra loro in una frase - per esempio `the quick red fox jumped` è una sequenza aggettivo-sostantivo-verbo che è separata dalla sequenza `lazy brown dog` .
### Frequenze di parole e frasi
Una procedura utile quando si analizza un corpo di testo di grandi dimensioni è creare un dizionario di ogni parola o frase di interesse e con quale frequenza viene visualizzata. La frase `the quick red fox jumped over the lazy brown dog` ha una frequenza di parole di 2 per the.
Si esamina un testo di esempio in cui si conta la frequenza delle parole. La poesia di Rudyard Kipling The Winners contiene i seguenti versi:
```output
What the moral? Who rides may read.
When the night is thick and the tracks are blind
A friend at a pinch is a friend, indeed,
But a fool to wait for the laggard behind.
Down to Gehenna or up to the Throne,
He travels the fastest who travels alone.
```
Poiché le frequenze delle frasi possono essere o meno insensibili alle maiuscole o alle maiuscole, a seconda di quanto richiesto, la frase `a friend` ha una frequenza di 2, `the` ha una frequenza di 6 e `travels` è 2.
### N-grammi
Un testo può essere suddiviso in sequenze di parole di una lunghezza prestabilita, una parola singola (unigramma), due parole (bigrammi), tre parole (trigrammi) o un numero qualsiasi di parole (n-grammi).
Ad esempio, `the quick red fox jumped over the lazy brown dog` con un punteggio n-grammo di 2 produce i seguenti n-grammi:
1. the quick
2. quick red
3. red fox
4. fox jumped
5. jumped over
6. over the
7. the lazy
8. lazy brown
9. brown dog
Potrebbe essere più facile visualizzarlo come una casella scorrevole per la frase. Qui è per n-grammi di 3 parole, l'n-grammo è in grassetto in ogni frase:
1. **the quick red** fox jumped over the lazy brown dog
2. the **quick red fox** jumped over the lazy brown dog
3. the quick **red fox jumped** over the lazy brown dog
4. the quick red **fox jumped over** the lazy brown dog
5. the quick red fox **jumped over the** lazy brown dog
6. the quick red fox jumped **over the lazy** brown dog
7. the quick red fox jumped over **the lazy brown** dog
8. the quick red fox jumped over the **lazy brown dog**
![finestra scorrevole n-grammi](../images/n-grams.gif)
> Valore N-gram di 3: Infografica di [Jen Looper](https://twitter.com/jenlooper)
### Estrazione frase nominale
Nella maggior parte delle frasi, c'è un sostantivo che è il soggetto o l'oggetto della frase. In inglese, è spesso identificabile con "a" o "an" o "the" che lo precede. Identificare il soggetto o l'oggetto di una frase "estraendo la frase nominale" è un compito comune in NLP quando si cerca di capire il significato di una frase.
✅ Nella frase "I cannot fix on the hour, or the spot, or the look or the words, which laid the foundation. It is too long ago. I was in the middle before I knew that I had begun.", si possono identificare i nomi nelle frasi?
Nella frase `the quick red fox jumped over the lazy brown dog` ci sono 2 frasi nominali: **quick red fox** e **lazy brown dog**.
### Analisi del sentiment
Una frase o un testo può essere analizzato per il sentimento, o quanto *positivo* o *negativo* esso sia. Il sentimento si misura in *polarità* e *oggettività/soggettività*. La polarità è misurata da -1,0 a 1,0 (da negativo a positivo) e da 0,0 a 1,0 (dal più oggettivo al più soggettivo).
✅ In seguito si imparerà che ci sono diversi modi per determinare il sentimento usando machine learning ma un modo è avere un elenco di parole e frasi che sono classificate come positive o negative da un esperto umano e applicare quel modello al testo per calcolare un punteggio di polarità. Si riesce a vedere come funzionerebbe in alcune circostanze e meno bene in altre?
### Inflessione
L'inflessione consente di prendere una parola e ottenere il singolare o il plurale della parola.
### Lemmatizzazione
Un *lemma* è la radice o il lemma per un insieme di parole, ad esempio *volò*, *vola*, *volando* ha un lemma del verbo *volare*.
Ci sono anche utili database disponibili per il ricercatore NPL, in particolare:
### WordNet
[WordNet](https://wordnet.princeton.edu/) è un database di parole, sinonimi, contari e molti altri dettagli per ogni parola in molte lingue diverse. È incredibilmente utile quando si tenta di costruire traduzioni, correttori ortografici o strumenti di lingua di qualsiasi tipo.
## Librerie NPL
Fortunatamente, non è necessario creare tutte queste tecniche da soli, poiché sono disponibili eccellenti librerie Python che le rendono molto più accessibili agli sviluppatori che non sono specializzati nell'elaborazione del linguaggio naturale o in machine learning. Le prossime lezioni includono altri esempi di queste, ma qui si impareranno alcuni esempi utili che aiuteranno con il prossimo compito.
### Esercizio: utilizzo della libreria `TextBlob`
Si usa una libreria chiamata TextBlob in quanto contiene API utili per affrontare questi tipi di attività. TextBlob "sta sulle spalle giganti di [NLTK](https://nltk.org) e [pattern](https://github.com/clips/pattern), e si sposa bene con entrambi". Ha una notevole quantità di ML incorporato nella sua API.
> Nota: per TextBlob è disponibile un'utile [guida rapida](https://textblob.readthedocs.io/en/dev/quickstart.html#quickstart), consigliata per sviluppatori Python esperti
Quando si tenta di identificare *le frasi nominali*, TextBlob offre diverse opzioni di estrattori per trovarle.
1. Dare un'occhiata a `ConllExtractor`.
```python
from textblob import TextBlob
from textblob.np_extractors import ConllExtractor
# importa e crea un extrattore Conll da usare successivamente
extractor = ConllExtractor()
# quando serve un estrattore di frasi nominali:
user_input = input("> ")
user_input_blob = TextBlob(user_input, np_extractor=extractor) # notare specificato estrattore non predefinito
np = user_input_blob.noun_phrases
```
> Cosa sta succedendo qui? [ConllExtractor](https://textblob.readthedocs.io/en/dev/api_reference.html?highlight=Conll#textblob.en.np_extractors.ConllExtractor) è "Un estrattore di frasi nominali che utilizza l'analisi dei blocchi addestrata con il corpus di formazione ConLL-2000". ConLL-2000 si riferisce alla Conferenza del 2000 sull'apprendimento computazionale del linguaggio naturale. Ogni anno la conferenza ha ospitato un workshop per affrontare uno spinoso problema della NPL, e nel 2000 è stato lo spezzettamento dei sostantivi. Un modello è stato addestrato sul Wall Street Journal, con "sezioni 15-18 come dati di addestramento (211727 token) e sezione 20 come dati di test (47377 token)". Si possono guardare le procedure utilizzate [qui](https://www.clips.uantwerpen.be/conll2000/chunking/) e i [risultati](https://ifarm.nl/erikt/research/np-chunking.html).
### Sfida: migliorare il bot con NPL
Nella lezione precedente si è creato un bot di domande e risposte molto semplice. Ora si renderà Marvin un po' più comprensivo analizzando l'input per il sentimento e stampando una risposta che corrisponda al sentimento. Si dovrà anche identificare una frase nominale `noun_phrase` e chiedere informazioni su di essa.
I passaggi durante la creazione di un bot conversazionale:
1. Stampare le istruzioni che consigliano all'utente come interagire con il bot
2. Avviare il ciclo
1. Accettare l'input dell'utente
2. Se l'utente ha chiesto di uscire, allora si esce
3. Elaborare l'input dell'utente e determinare la risposta di sentimento appropriata
4. Se viene rilevata una frase nominale nel sentimento, pluralizzala e chiedere ulteriori input su quell'argomento
5. Stampare la risposta
3. Riprendere il ciclo dal passo 2
Ecco il frammento di codice per determinare il sentimento usando TextBlob. Si noti che ci sono solo quattro *gradienti* di risposta al sentimento (se ne potrebbero avere di più se lo si desidera):
```python
if user_input_blob.polarity <= -0.5:
response = "Oh dear, that sounds bad. " # Oh caro, è terribile
elif user_input_blob.polarity <= 0:
response = "Hmm, that's not great. " # Mmm, non è eccezionale
elif user_input_blob.polarity <= 0.5:
response = "Well, that sounds positive. " # Bene, questo è positivo
elif user_input_blob.polarity <= 1:
response = "Wow, that sounds great. " # Wow, sembra eccezionale
```
Ecco un risultato di esempio a scopo di guida (l'input utente è sulle righe che iniziano per >):
```output
Hello, I am Marvin, the friendly robot.
You can end this conversation at any time by typing 'bye'
After typing each answer, press 'enter'
How are you today?
> I am ok
Well, that sounds positive. Can you tell me more?
> I went for a walk and saw a lovely cat
Well, that sounds positive. Can you tell me more about lovely cats?
> cats are the best. But I also have a cool dog
Wow, that sounds great. Can you tell me more about cool dogs?
> I have an old hounddog but he is sick
Hmm, that's not great. Can you tell me more about old hounddogs?
> bye
It was nice talking to you, goodbye!
```
Una possibile soluzione al compito è [qui](../solution/bot.py)
Verifica delle conoscenze
1. Si ritiene che le risposte casuali "ingannerebbero" qualcuno facendogli pensare che il bot le abbia effettivamente capite?
2. Identificare la frase nominale rende il bot più 'credibile'?
3. Perché estrarre una "frase nominale" da una frase sarebbe una cosa utile da fare?
---
Implementare il bot nel controllo delle conoscenze precedenti e testarlo su un amico. Può ingannarlo? Si può rendere il bot più 'credibile?'
## 🚀 Sfida
Prendere un'attività dalla verifica delle conoscenze qui sopra e provare a implementarla. Provare il bot su un amico. Può ingannarlo? Si può rendere il bot più 'credibile?'
## [Quiz post-lezione](https://jolly-sea-0a877260f.azurestaticapps.net/quiz/34/)
## Revisione e Auto Apprendimento
Nelle prossime lezioni si imparerà di più sull'analisi del sentiment. Fare ricerche su questa interessante tecnica in articoli come questi su [KDNuggets](https://www.kdnuggets.com/tag/nlp)
## Compito
[Fare rispondere un bot](assignment.it.md)

@ -0,0 +1,11 @@
# Fare rispondere un bot
## Istruzioni
Nelle ultime lezioni, si è programmato un bot di base con cui chattare. Questo bot fornisce risposte casuali finché non si dice ciao ("bye"). Si possono rendere le risposte un po' meno casuali e attivare le risposte se si dicono cose specifiche, come "perché" o "come"? Si pensi a come machine learning potrebbe rendere questo tipo di lavoro meno manuale mentre si estende il bot. Si possono utilizzare le librerie NLTK o TextBlob per semplificare le attività.
## Rubrica
| Criteri | Ottimo | Adeguato | Necessita miglioramento |
| -------- | --------------------------------------------- | ------------------------------------------------ | ----------------------- |
| | Viene presentato e documentato un nuovo file bot.py | Viene presentato un nuovo file bot ma contiene bug | Non viene presentato un file |

@ -0,0 +1,187 @@
# Traduzione e analisi del sentiment con ML
Nelle lezioni precedenti si è imparato come creare un bot di base utilizzando `TextBlob`, una libreria che incorpora machine learning dietro le quinte per eseguire attività di base di NPL come l'estrazione di frasi nominali. Un'altra sfida importante nella linguistica computazionale è _la traduzione_ accurata di una frase da una lingua parlata o scritta a un'altra.
## [Quiz Pre-Lezione](https://jolly-sea-0a877260f.azurestaticapps.net/quiz/35/)
La traduzione è un problema molto difficile, aggravato dal fatto che ci sono migliaia di lingue e ognuna può avere regole grammaticali molto diverse. Un approccio consiste nel convertire le regole grammaticali formali per una lingua, come l'inglese, in una struttura non dipendente dalla lingua e quindi tradurla convertendola in un'altra lingua. Questo approccio significa che si dovrebbero eseguire i seguenti passaggi:
1. **Identificazione**. Identificare o taggare le parole nella lingua di input in sostantivi, verbi, ecc.
2. **Creare la traduzione**. Produrre una traduzione diretta di ogni parola nel formato della lingua di destinazione.
### Frase di esempio, dall'inglese all'irlandese
In inglese, la frase _I feel happy_ (sono felice) è composta da tre parole nell'ordine:
- **soggetto** (I)
- **verbo** (feel)
- **aggettivo** (happy)
Tuttavia, nella lingua irlandese, la stessa frase ha una struttura grammaticale molto diversa - emozioni come "*felice*" o "*triste*" sono espresse come se fossero *su se stessi*.
La frase inglese `I feel happy` in irlandese sarebbe `Tá athas orm`. Una traduzione *letterale* sarebbe `Happy is upon me` (felicità su di me).
Un oratore irlandese che traduce in inglese direbbe `I feel happy`, non `Happy is upon me`, perché capirebbe il significato della frase, anche se le parole e la struttura della frase sono diverse.
L'ordine formale per la frase in irlandese sono:
- **verbo** (Tá o is)
- **aggettivo** (athas, o happy)
- **soggetto** (orm, o upon me)
## Traduzione
Un programma di traduzione ingenuo potrebbe tradurre solo parole, ignorando la struttura della frase.
✅ Se si è imparato una seconda (o terza o più) lingua da adulto, si potrebbe aver iniziato pensando nella propria lingua madre, traducendo un concetto parola per parola nella propria testa nella seconda lingua, e poi pronunciando la traduzione. Questo è simile a quello che stanno facendo i programmi per computer di traduzione ingenui. È importante superare questa fase per raggiungere la fluidità!
La traduzione ingenua porta a cattive (e talvolta esilaranti) traduzioni errate: `I feel happy` si traduce letteralmente in `Mise bhraitheann athas` in irlandese. Ciò significa (letteralmente) `me feel happy` e non è una frase irlandese valida. Anche se l'inglese e l'irlandese sono lingue parlate su due isole vicine, sono lingue molto diverse con strutture grammaticali diverse.
> E' possibile guardare alcuni video sulle tradizioni linguistiche irlandesi come [questo](https://www.youtube.com/watch?v=mRIaLSdRMMs)
### Approcci di machine learning
Finora, si è imparato a conoscere l'approccio delle regole formali all'elaborazione del linguaggio naturale. Un altro approccio consiste nell'ignorare il significato delle parole e _utilizzare invece machine learning per rilevare i modelli_. Questo può funzionare nella traduzione se si ha molto testo (un *corpus*) o testi (*corpora*) sia nella lingua di origine che in quella di destinazione.
Si prenda ad esempio il caso di *Pride and Prejudice (Orgoglio* e pregiudizio),un noto romanzo inglese scritto da Jane Austen nel 1813. Se si consulta il libro in inglese e una traduzione umana del libro in *francese*, si potrebberoi rilevare frasi in uno che sono tradotte *idiomaticamente* nell'altro. Si farà fra un minuto.
Ad esempio, quando una frase inglese come `I have no money` (non ho denaro) viene tradotta letteralmente in francese, potrebbe diventare `Je n'ai pas de monnaie`. "Monnaie" è un complicato "falso affine" francese, poiché "money" e "monnaie" non sono sinonimi. Una traduzione migliore che un essere umano potrebbe fare sarebbe `Je n'ai pas d'argent`, perché trasmette meglio il significato che non si hanno soldi (piuttosto che "moneta spicciola" che è il significato di "monnaie").
![monnaie](../images/monnaie.png)
> Immagine di [Jen Looper](https://twitter.com/jenlooper)
Se un modello ML ha abbastanza traduzioni umane su cui costruire un modello, può migliorare l'accuratezza delle traduzioni identificando modelli comuni in testi che sono stati precedentemente tradotti da umani esperti parlanti di entrambe le lingue.
### Esercizio - traduzione
Si può usare `TextBlob` per tradurre le frasi. Provare la famosa prima riga di **Orgoglio e Pregiudizio**:
```python
from textblob import TextBlob
blob = TextBlob(
"It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife!"
)
print(blob.translate(to="fr"))
```
`TextBlob` fa un buon lavoro con la traduzione: "C'est une vérité universalllement reconnue, qu'un homme célibataire en possession d'une bonne fortune doit avoir besoin d'une femme!".
Si può sostenere che la traduzione di TextBlob è molto più esatta, infatti, della traduzione francese del 1932 del libro di V. Leconte e Ch. Pressoir:
"C'est une vérité universelle qu'un celibataire pourvu d'une belle fortune doit avoir envie de se marier, et, si peu que l'on sache de son sentiment à cet egard, lorsqu'il arrive dans une nouvelle residence, cette idée est si bien fixée dans l'esprit de ses voisins qu'ils le considèrent sur-le-champ comme la propriété légitime de l'une ou l'autre de leurs filles."
In questo caso, la traduzione informata da ML fa un lavoro migliore del traduttore umano che mette inutilmente parole nella bocca dell'autore originale per "chiarezza".
> Cosa sta succedendo qui? e perché TextBlob è così bravo a tradurre? Ebbene, dietro le quinte, utilizza Google translate, una sofisticata intelligenza artificiale in grado di analizzare milioni di frasi per prevedere le migliori stringhe per il compito da svolgere. Non c'è niente di manuale in corso qui e serve una connessione Internet per usare `blob.translate`.
✅ Provare altre frasi. Qual'è migliore, ML o traduzione umana? In quali casi?
## Analisi del sentiment
Un'altra area in cui l'apprendimento automatico può funzionare molto bene è l'analisi del sentiment. Un approccio non ML al sentiment consiste nell'identificare parole e frasi che sono "positive" e "negative". Quindi, dato un nuovo pezzo di testo, calcolare il valore totale delle parole positive, negative e neutre per identificare il sentimento generale.
Questo approccio è facilmente ingannabile come si potrebbe aver visto nel compito di Marvin: la frase `Great, that was a wonderful waste of time, I'm glad we are lost on this dark road` (Grande, è stata una meravigliosa perdita di tempo, sono contento che ci siamo persi su questa strada oscura) è una frase sarcastica e negativa, ma il semplice algoritmo rileva 'great' (grande), 'wonderful' (meraviglioso), 'glad' (contento) come positivo e 'waste' (spreco), 'lost' (perso) e 'dark' (oscuro) come negativo. Il sentimento generale è influenzato da queste parole contrastanti.
✅ Si rifletta un momento su come si trasmette il sarcasmo come oratori umani. L'inflessione del tono gioca un ruolo importante. Provare a dire la frase "Beh, quel film è stato fantastico" in modi diversi per scoprire come la propria voce trasmette significato.
### Approcci ML
L'approccio ML sarebbe quello di raccogliere manualmente corpi di testo negativi e positivi: tweet, recensioni di film o qualsiasi cosa in cui l'essere umano abbia assegnato un punteggio *e* un parere scritto. Quindi le tecniche di NPL possono essere applicate alle opinioni e ai punteggi, in modo che emergano modelli (ad esempio, le recensioni positive di film tendono ad avere la frase "degno di un Oscar" più delle recensioni di film negative, o le recensioni positive di ristoranti dicono "gourmet" molto più di "disgustoso").
> ⚖️ **Esempio**: se si è lavorato nell'ufficio di un politico e c'era qualche nuova legge in discussione, gli elettori potrebbero scrivere all'ufficio con e-mail a sostegno o e-mail contro la nuova legge specifica. Si supponga che si abbia il compito di leggere le e-mail e ordinarle in 2 pile, *pro* e *contro*. Se ci fossero molte e-mail, si potrebbe essere sopraffatti dal tentativo di leggerle tutte. Non sarebbe bello se un bot potesse leggerle tutte, capirle e dire a quale pila apparteneva ogni email?
>
> Un modo per raggiungere questo obiettivo è utilizzare machine learning. Si addestrerebbe il modello con una parte delle email *contro* e una parte delle email *per* . Il modello tenderebbe ad associare frasi e parole con il lato contro o il lato per, *ma non capirebbe alcun contenuto*, solo che è più probabile che alcune parole e modelli in una email appaiano in un *contro* o in un *pro*. Si potrebbe fare una prova con alcune e-mail non usate per addestrare il modello e vedere se si arriva alla stessa conclusione tratta da un umano. Quindi, una volta soddisfatti dell'accuratezza del modello, si potrebbero elaborare le email future senza doverle leggere tutte.
✅ Questo processo ricorda processi usati nelle lezioni precedenti?
## Esercizio - frasi sentimentali
Il sentimento viene misurato con una *polarità* da -1 a 1, il che significa che -1 è il sentimento più negativo e 1 è il più positivo. Il sentimento viene anche misurato con un punteggio 0 - 1 per oggettività (0) e soggettività (1).
Si dia un'altra occhiata a *Orgoglio e pregiudizio* di Jane Austen. Il testo è disponibile qui su [Project Gutenberg](https://www.gutenberg.org/files/1342/1342-h/1342-h.htm). L'esempio seguente mostra un breve programma che analizza il sentimento della prima e dell'ultima frase del libro e ne mostra la polarità del sentimento e il punteggio di soggettività/oggettività.
Si dovrebbe utilizzare la libreria `TextBlob` (descritta sopra) per determinare il `sentiment` (non si deve scrivere il proprio calcolatore del sentimento) nella seguente attività.
```python
from textblob import TextBlob
quote1 = """It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife."""
quote2 = """Darcy, as well as Elizabeth, really loved them; and they were both ever sensible of the warmest gratitude towards the persons who, by bringing her into Derbyshire, had been the means of uniting them."""
sentiment1 = TextBlob(quote1).sentiment
sentiment2 = TextBlob(quote2).sentiment
print(quote1 + " has a sentiment of " + str(sentiment1))
print(quote2 + " has a sentiment of " + str(sentiment2))
```
Si dovrebbe ottenere il seguente risultato:
```output
It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want # of a wife. has a sentiment of Sentiment(polarity=0.20952380952380953, subjectivity=0.27142857142857146)
Darcy, as well as Elizabeth, really loved them; and they were
both ever sensible of the warmest gratitude towards the persons
who, by bringing her into Derbyshire, had been the means of
uniting them. has a sentiment of Sentiment(polarity=0.7, subjectivity=0.8)
```
## Sfida: controllare la polarità del sentimento
Il compito è determinare, usando la polarità del sentiment, se *Orgoglio e Pregiudizio* ha più frasi assolutamente positive di quelle assolutamente negative. Per questa attività, si può presumere che un punteggio di polarità di 1 o -1 sia rispettivamente assolutamente positivo o negativo.
**Procedura:**
1. Scaricare una [copia di Orgoglio e pregiudizio](https://www.gutenberg.org/files/1342/1342-h/1342-h.htm) dal Progetto Gutenberg come file .txt. Rimuovere i metadati all'inizio e alla fine del file, lasciando solo il testo originale
2. Aprire il file in Python ed estrare il contenuto come una stringa
3. Creare un TextBlob usando la stringa del libro
4. Analizzare ogni frase del libro in un ciclo
1. Se la polarità è 1 o -1, memorizzare la frase in un array o in un elenco di messaggi positivi o negativi
5. Alla fine, stampare tutte le frasi positive e negative (separatamente) e il numero di ciascuna.
Ecco una [soluzione](../solution/notebook.ipynb) di esempio.
✅ Verifica delle conoscenze
1. Il sentimento si basa sulle parole usate nella frase, ma il codice *comprende* le parole?
2. Si ritiene che la polarità del sentimento sia accurata o, in altre parole, si è *d'accordo* con i punteggi?
1. In particolare, si è d'accordo o in disaccordo con l'assoluta polarità **positiva** delle seguenti frasi?
* What an excellent father you have, girls! (Che padre eccellente avete, ragazze!) said she, when the door was shut. (disse lei, non appena si chiuse la porta).
* “Your examination of Mr. Darcy is over, I presume,” said Miss Bingley; “and pray what is the result?” ("Il vostro esame di Mr. Darcy è finito, presumo", disse Miss Bingley; "e vi prego qual è il risultato?") “I am perfectly convinced by it that Mr. Darcy has no defect. (Sono perfettamente convinta che il signor Darcy non abbia difetti).
* How wonderfully these sort of things occur! (Come accadono meravigliosamente questo genere di cose!).
* I have the greatest dislike in the world to that sort of thing. (Ho la più grande antipatia del mondo per quel genere di cose).
* Charlotte is an excellent manager, I dare say (Charlotte è un'eccellente manager, oserei dire).
* “This is delightful indeed! (“Questo è davvero delizioso!)
* I am so happy! (Che gioia!)
* Your idea of the ponies is delightful. (La vostra idea dei pony è deliziosa).
2. Le successive 3 frasi sono state valutate con un sentimento assolutamente positivo, ma a una lettura attenta, non sono frasi positive. Perché l'analisi del sentiment ha pensato che fossero frasi positive?
* Happy shall I be, when his stay at Netherfield is over!” “I wish I could say anything to comfort you,” replied Elizabeth; “but it is wholly out of my power. (Come sarò felice, quando il suo soggiorno a Netherfield sarà finito!» "Vorrei poter dire qualcosa per consolarti", rispose Elizabeth; “ma proprio non ci riesco).
* If I could but see you as happy! (Se solo potessi vederti felice!)
* Our distress, my dear Lizzy, is very great. (La nostra angoscia, mia cara Lizzy, è devvero grande).
3. Sei d'accordo o in disaccordo con la polarità **negativa** assoluta delle seguenti frasi?
- Everybody is disgusted with his pride. (Tutti sono disgustati dal suo orgoglio).
- “I should like to know how he behaves among strangers.” “You shall hear then—but prepare yourself for something very dreadful. ("Vorrei sapere come si comporta in mezzo agli estranei." "Allora sentirete, ma preparatevi a qualcosa di terribile).
- The pause was to Elizabeths feelings dreadful. (La pausa fu terribile per i sentimenti di Elizabeth).
- It would be dreadful! (Sarebbe terribile!)
✅ Qualsiasi appassionato di Jane Austen capirebbe che usa spesso i suoi libri per criticare gli aspetti più ridicoli della società inglese Regency. Elizabeth Bennett, la protagonista di *Orgoglio e pregiudizio,* è un'attenta osservatrice sociale (come l'autrice) e il suo linguaggio è spesso pesantemente sfumato. Anche Mr. Darcy (l'interesse amoroso della storia) nota l'uso giocoso e canzonatorio del linguaggio di Elizabeth: "I have had the pleasure of your acquaintance long enough to know that you find great enjoyment in occasionally professing opinions which in fact are not your own." ("Ho il piacere di conoscervi da abbastanza tempo per sapere quanto vi divertiate a esprimere di tanto in tanto delle opinioni che in realtà non vi appartengono")
---
## 🚀 Sfida
Si può rendere Marvin ancora migliore estraendo altre funzionalità dall'input dell'utente?
## [Quiz post-lezione](https://jolly-sea-0a877260f.azurestaticapps.net/quiz/36/)
## Revisione e Auto Apprendimento
Esistono molti modi per estrarre il sentiment dal testo. Si pensi alle applicazioni aziendali che potrebbero utilizzare questa tecnica. Pensare a cosa potrebbe andare storto. Ulteriori informazioni sui sistemi sofisticati pronti per l'azienda che analizzano il sentiment come l'[analisi del testo di Azure](https://docs.microsoft.com/azure/cognitive-services/Text-Analytics/how-tos/text-analytics-how-to-sentiment-analysis?tabs=version-3-1?WT.mc_id=academic-15963-cxa). Provare alcune delle frasi di Orgoglio e Pregiudizio sopra e vedere se può rilevare sfumature.
## Compito
[Licenza poetica](assignment.it.md)

@ -0,0 +1,11 @@
# Licenza poetica
## Istruzioni
In [questo notebook](https://www.kaggle.com/jenlooper/emily-dickinson-word-frequency) si possono trovare oltre 500 poesie di Emily Dickinson precedentemente analizzate per il sentiment utilizzando l'analisi del testo di Azure. Utilizzando questo insieme di dati, analizzarlo utilizzando le tecniche descritte nella lezione. Il sentimento suggerito di una poesia corrisponde alla decisione più sofisticata del servizio Azure? Perché o perché no, secondo il proprio parere? Cè qualcosa che sorprende?
## Rubrica
| Criteri | Ottimo | Adeguato | Necessita miglioramento |
| -------- | -------------------------------------------------------------------------- | ------------------------------------------------------- | ------------------------ |
| | Un notebook viene presentato con una solida analisi del risultato da un campione di un autore | Il notebook è incompleto o non esegue l'analisi | Nessun notebook presentato |

@ -0,0 +1,412 @@
# Analisi del sentiment con le recensioni degli hotel - elaborazione dei dati
In questa sezione si utilizzeranno le tecniche delle lezioni precedenti per eseguire alcune analisi esplorative dei dati di un grande insieme di dati. Una volta compresa bene l'utilità delle varie colonne, si imparerà:
- come rimuovere le colonne non necessarie
- come calcolare alcuni nuovi dati in base alle colonne esistenti
- come salvare l'insieme di dati risultante per l'uso nella sfida finale
## [Quiz Pre-Lezione](https://jolly-sea-0a877260f.azurestaticapps.net/quiz/37/)
### Introduzione
Finora si è appreso come i dati di testo siano abbastanza diversi dai tipi di dati numerici. Se è un testo scritto o parlato da un essere umano, può essere analizzato per trovare schemi e frequenze, sentiment e significati. Questa lezione entra in un vero insieme di dati con una vera sfida: **[515K dati di recensioni di hotel in Europa](https://www.kaggle.com/jiashenliu/515k-hotel-reviews-data-in-europe)** e include una [licenza CC0: Public Domain](https://creativecommons.org/publicdomain/zero/1.0/). È stato ricavato da Booking.com da fonti pubbliche. Il creatore dell'insieme di dati è stato Jiashen Liu.
### Preparazione
Ecco l'occorrente:
* La possibilità di eseguire notebook .ipynb utilizzando Python 3
* pandas
* NLTK, [che si dovrebbe installare localmente](https://www.nltk.org/install.html)
* L'insieme di dati disponibile su Kaggle [515K Hotel Reviews Data in Europe](https://www.kaggle.com/jiashenliu/515k-hotel-reviews-data-in-europe). Sono circa 230 MB decompressi. Scaricarlo nella cartella radice `/data` associata a queste lezioni di NLP.
## Analisi esplorativa dei dati
Questa sfida presuppone che si stia creando un bot di raccomandazione di hotel utilizzando l'analisi del sentiment e i punteggi delle recensioni degli ospiti. L'insieme di dati da utilizzare include recensioni di 1493 hotel diversi in 6 città.
Utilizzando Python, un insieme di dati di recensioni di hotel e l'analisi del sentiment di NLTK si potrebbe scoprire:
* quali sono le parole e le frasi più usate nelle recensioni?
* i *tag* ufficiali che descrivono un hotel correlato con punteggi di recensione (ad es. sono le più negative per un particolare hotel per *famiglia con bambini piccoli* rispetto a *viaggiatore singolo*, forse indicando che è meglio per i *viaggiatori sinogli*?)
* i punteggi del sentiment NLTK "concordano" con il punteggio numerico del recensore dell'hotel?
#### Insieme di dati
Per esplorare l'insieme di dati scaricato e salvato localmente, aprire il file in un editor tipo VS Code o anche Excel.
Le intestazioni nell'insieme di dati sono le seguenti:
*Hotel_Address, Additional_Number_of_Scoring, Review_Date, Average_Score, Hotel_Name, Reviewer_Nationality, Negative_Review, Review_Total_Negative_Word_Counts, Total_Number_of_Reviews, Positive_Review, Review_Total_Positive_Word_Counts, Total_Number_of_Reviews_Reviewer_Has_Given, Reviewer_Score, Tags, days_since_review, lat, lng*
Qui sono raggruppati in un modo che potrebbe essere più facile da esaminare:
##### Colonne Hotel
* `Hotel_Name` (nome hotel), `Hotel_Address` (indirizzo hotel), `lat` (latitudine)`,` lng (longitudine)
* Usando *lat* e *lng* si può tracciare una mappa con Python che mostra le posizioni degli hotel (forse codificate a colori per recensioni negative e positive)
* Hotel_Address non è ovviamente utile e probabilmente verrà sostituito con una nazione per semplificare l'ordinamento e la ricerca
**Colonne di meta-recensione dell'hotel**
* `Average_Score` (Punteggio medio)
* Secondo il creatore dell'insieme di dati, questa colonna è il *punteggio medio dell'hotel, calcolato in base all'ultimo commento dell'ultimo anno*. Questo sembra un modo insolito per calcolare il punteggio, ma sono i dati recuperati, quindi per ora si potrebbero prendere come valore nominale.
✅ Sulla base delle altre colonne di questi dati, si riesce a pensare a un altro modo per calcolare il punteggio medio?
* `Total_Number_of_Reviews` (Numero totale di recensioni)
* Il numero totale di recensioni ricevute da questo hotel - non è chiaro (senza scrivere del codice) se si riferisce alle recensioni nell'insieme di dati.
* `Additional_Number_of_Scoring` (Numero aggiuntivo di punteggio
* Ciò significa che è stato assegnato un punteggio di recensione ma nessuna recensione positiva o negativa è stata scritta dal recensore
**Colonne di recensione**
- `Reviewer_Score` (Punteggio recensore)
- Questo è un valore numerico con al massimo 1 cifra decimale tra i valori minimo e massimo 2,5 e 10
- Non è spiegato perché 2,5 sia il punteggio più basso possibile
- `Negative_Review` (Recensione Negativa)
- Se un recensore non ha scritto nulla, questo campo avrà "**No Negative" (Nessun negativo)**
- Si tenga presente che un recensore può scrivere una recensione positiva nella colonna delle recensioni negative (ad es. "non c'è niente di negativo in questo hotel")
- `Review_Total_Negative_Word_Counts` (Conteggio parole negative totali per revisione)
- Conteggi di parole negative più alti indicano un punteggio più basso (senza controllare il sentiment)
- `Positive_Review` (Recensioni positive)
- Se un recensore non ha scritto nulla, questo campo avrà "**No Positive" (Nessun positivo)**
- Si tenga presente che un recensore può scrivere una recensione negativa nella colonna delle recensioni positive (ad es. "non c'è niente di buono in questo hotel")
- `Review_Total_Positive_Word_Counts` (Conteggio parole positive totali per revisione)
- Conteggi di parole positive più alti indicano un punteggio più alto (senza controllare il sentiment)
- `Review_Date` e `days_since_review` (Data revisione e giorni trascorsi dalla revisione)
- Una misura di freschezza od obsolescenza potrebbe essere applicata a una recensione (le recensioni più vecchie potrebbero non essere accurate quanto quelle più recenti perché la gestione dell'hotel è cambiata, o sono stati effettuati lavori di ristrutturazione, o è stata aggiunta una piscina, ecc.)
- `Tag`
- Questi sono brevi descrittori che un recensore può selezionare per descrivere il tipo di ospite in cui rientra (ad es. da soli o in famiglia), il tipo di camera che aveva, la durata del soggiorno e come è stata inviata la recensione.
- Sfortunatamente, l'uso di questi tag è problematico, controllare la sezione sottostante che discute la loro utilità
**Colonne dei recensori**
- `Total_Number_of_Reviews_Reviewer_Has_Given` (Numero totale di revisioni per recensore)
- Questo potrebbe essere un fattore in un modello di raccomandazione, ad esempio, se si potesse determinare che i recensori più prolifici con centinaia di recensioni avevano maggiori probabilità di essere negativi piuttosto che positivi. Tuttavia, il recensore di una particolare recensione non è identificato con un codice univoco e quindi non può essere collegato a un insieme di recensioni. Ci sono 30 recensori con 100 o più recensioni, ma è difficile vedere come questo possa aiutare il modello di raccomandazione.
- `Reviewer_Nationality` (Nazionalità recensore)
- Alcune persone potrebbero pensare che alcune nazionalità abbiano maggiore propensione a dare una recensione positiva o negativa a causa di un'inclinazione nazionalista. Fare attenzione a creare tali punti di vista aneddotici nei propri modelli. Questi sono stereotipi nazionalisti (e talvolta razziali) e ogni recensore era un individuo che ha scritto una recensione in base alla propria esperienza. Potrebbe essere stata filtrata attraverso molte lenti come i loro precedenti soggiorni in hotel, la distanza percorsa e la loro indole. Pensare che la loro nazionalità sia stata la ragione per un punteggio di recensione è difficile da giustificare.
##### Esempi
| Average Score | Total Number Reviews | Reviewer Score | Negative <br />Review | Positive Review | Tags |
| -------------- | ---------------------- | ---------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ----------------------------------------------------------------------------------------- |
| 7.8 | 1945 | 2.5 | This is currently not a hotel but a construction site I was terroized from early morning and all day with unacceptable building noise while resting after a long trip and working in the room People were working all day i e with jackhammers in the adjacent rooms I asked for a room change but no silent room was available To make thinks worse I was overcharged I checked out in the evening since I had to leave very early flight and received an appropiate bill A day later the hotel made another charge without my concent in excess of booked price It s a terrible place Don t punish yourself by booking here | Nothing Terrible place Stay away | Business trip Couple Standard Double Room Stayed 2 nights |
Come si può vedere, questo ospite non ha trascorso un soggiorno felice in questo hotel. L'hotel ha un buon punteggio medio di 7,8 e 1945 recensioni, ma questo recensore ha dato 2,5 e ha scritto 115 parole su quanto sia stato negativo il suo soggiorno. Se non è stato scritto nulla nella colonna Positive_Review, si potrebbe supporre che non ci sia stato nulla di positivo, ma purtroppo sono state scritte 7 parole di avvertimento. Se si contassero solo le parole invece del significato o del sentiment delle parole, si potrebbe avere una visione distorta dell'intento dei recensori. Stranamente, il punteggio di 2,5 è fonte di confusione, perché se il soggiorno in hotel è stato così negativo, perché dargli dei punti? Indagando da vicino l'insieme di dati, si vedrà che il punteggio più basso possibile è 2,5, non 0. Il punteggio più alto possibile è 10.
##### Tag
Come accennato in precedenza, a prima vista, l'idea di utilizzare i `tag` per classificare i dati ha senso. Sfortunatamente questi tag non sono standardizzati, il che significa che in un determinato hotel le opzioni potrebbero essere *Camera singola* , *Camera a due letti* e *Camera doppia*, ma nell'hotel successivo potrebbero essere *Camera singola deluxe*, *Camera matrimoniale classica* e *Camera king executive*. Potrebbero essere le stesse cose, ma ci sono così tante varianti che la scelta diventa:
1. Tentare di modificare tutti i termini in un unico standard, il che è molto difficile, perché non è chiaro quale sarebbe il percorso di conversione in ciascun caso (ad es. *Camera singola classica* mappata in *camera singola*, ma *camera Queen Superior con cortile giardino o vista città* è molto più difficile da mappare)
1. Si può adottare un approccio NLP e misurare la frequenza di determinati termini come *Solo*, *Business Traveller* (Viaggiatore d'affari) o *Family with young kids* (Famiglia con bambini piccoli) quando si applicano a ciascun hotel e tenerne conto nella raccomandazione
I tag sono in genere (ma non sempre) un singolo campo contenente un elenco di valori separati da 5 a 6 virgole allineati per *Type of trip* (Tipo di viaggio), *Type of guests* (Tipo di ospiti), *Type of room* (Tipo di camera), *Number of nights* (Numero di notti) e *Type of device* (Tipo di dispositivo con il quale è stata inviata la recensione).Tuttavia, poiché alcuni recensori non compilano ogni campo (potrebbero lasciarne uno vuoto), i valori non sono sempre nello stesso ordine.
Ad esempio, si prenda *Type of group* (Tipo di gruppo). Ci sono 1025 possibilità uniche in questo campo nella colonna `Tag`, e purtroppo solo alcune di esse fanno riferimento a un gruppo (alcune sono il tipo di stanza ecc.). Se si filtra solo quelli che menzionano la famiglia, saranno ricavati molti risultati relativi al tipo di *Family room* . Se si include il termine *with* (con), cioè si conta i valori per *Family with*, i risultati sono migliori, con oltre 80.000 dei 515.000 risultati che contengono la frase "Family with young children" (Famiglia con figli piccoli) o "Family with older children" (Famiglia con figli grandi).
Ciò significa che la colonna dei tag non è completamente inutile allo scopo, ma richiederà del lavoro per renderla utile.
##### Punteggio medio dell'hotel
Ci sono una serie di stranezze o discrepanze con l'insieme di dati che non si riesce a capire, ma sono illustrate qui in modo che ci siano note quando si costruiscono i propri modelli. Se ci si capisce qualcosa, renderlo noto nella sezione discussione!
L'insieme di dati ha le seguenti colonne relative al punteggio medio e al numero di recensioni:
1. Hotel_Name (Nome Hotel)
2. Additional_Number_of_Scoring (Numero aggiuntivo di punteggio
3. Average_Score (Punteggio medio)
4. Total_Number_of_Reviews (Numero totale di recensioni)
5. Reviewer_Score (Punteggio recensore)
L'hotel con il maggior numero di recensioni in questo insieme di dati è *il Britannia International Hotel Canary Wharf* con 4789 recensioni su 515.000. Ma se si guarda al valore `Total_Number_of_Reviews` per questo hotel, è 9086. Si potrebbe supporre che ci siano molti più punteggi senza recensioni, quindi forse si dovrebbe aggiungere il valore della colonna `Additional_Number_of_Scoring` . Quel valore è 2682 e aggiungendolo a 4789 si ottiene 7.471 che è ancora 1615 in meno del valore di `Total_Number_of_Reviews`.
Se si prende la colonna `Average_Score`, si potrebbe supporre che sia la media delle recensioni nell'insieme di dati, ma la descrizione di Kaggle è "*Punteggio medio dellhotel, calcolato in base allultimo commento nellultimo anno*". Non sembra così utile, ma si può calcolare la media in base ai punteggi delle recensioni nell'insieme di dati. Utilizzando lo stesso hotel come esempio, il punteggio medio dell'hotel è 7,1 ma il punteggio calcolato (punteggio medio del recensore nell'insieme di dati) è 6,8. Questo è vicino, ma non lo stesso valore, e si può solo supporre che i punteggi dati nelle recensioni `Additional_Number_of_Scoring` hanno aumentato la media a 7,1. Sfortunatamente, senza alcun modo per testare o dimostrare tale affermazione, è difficile utilizzare o fidarsi di `Average_Score`, `Additional_Number_of_Scoring` e `Total_Number_of_Reviews` quando si basano su o fanno riferimento a dati che non sono presenti.
Per complicare ulteriormente le cose, l'hotel con il secondo numero più alto di recensioni ha un punteggio medio calcolato di 8,12 e l'insieme di dati `Average_Score` è 8,1. Questo punteggio corretto è una coincidenza o il primo hotel è una discrepanza?
Sulla possibilità che questi hotel possano essere un valore anomalo e che forse la maggior parte dei valori coincidano (ma alcuni non lo fanno per qualche motivo) si scriverà un breve programma per esplorare i valori nell'insieme di dati e determinare l'utilizzo corretto (o mancato utilizzo) dei valori.
> 🚨 Una nota di cautela
>
> Quando si lavora con questo insieme di dati, si scriverà un codice che calcola qualcosa dal testo senza dover leggere o analizzare il testo da soli. Questa è l'essenza di NLP, interpretare il significato o il sentiment senza che lo faccia un essere umano. Tuttavia, è possibile che si leggano alcune delle recensioni negative. Non è raccomandabile farlo. Alcune di esse sono recensioni negative sciocche o irrilevanti, come "Il tempo non era eccezionale", qualcosa al di fuori del controllo dell'hotel, o di chiunque, in effetti. Ma c'è anche un lato oscuro in alcune recensioni. A volte le recensioni negative sono razziste, sessiste o antietà. Questo è un peccato, ma è prevedibile in un insieme di dati recuperato da un sito web pubblico. Alcuni recensori lasciano recensioni che si potrebbe trovare sgradevoli, scomode o sconvolgenti. Meglio lasciare che il codice misuri il sentiment piuttosto che leggerle da soli e arrabbiarsi. Detto questo, è una minoranza che scrive queste cose, ma esistono lo stesso.
## Esercizio - Esplorazione dei dati
### Caricare i dati
Per ora l'esame visivo dei dati è sufficiente, adesso si scriverà del codice e si otterranno alcune risposte! Questa sezione utilizza la libreria pandas. Il primo compito è assicurarsi di poter caricare e leggere i dati CSV. La libreria pandas ha un veloce caricatore CSV e il risultato viene inserito in un dataframe, come nelle lezioni precedenti. Il CSV che si sta caricando ha oltre mezzo milione di righe, ma solo 17 colonne. Pandas offre molti modi potenti per interagire con un dataframe, inclusa la possibilità di eseguire operazioni su ogni riga.
Da qui in poi in questa lezione, ci saranno frammenti di codice e alcune spiegazioni del codice e alcune discussioni su cosa significano i risultati. Usare il _notebook.ipynb_ incluso per il proprio codice.
Si inizia con il caricamento del file di dati da utilizzare:
```python
# Carica il CSV con le recensioni degli hotel
import pandas as pd
import time
# importa time per determinare orario di inizio e fine caricamento per poterne calcolare la durata
print("Loading data file now, this could take a while depending on file size")
start = time.time()
# df è un 'DataFrame' - assicurarsi di aver scaricato il file nella cartelle data
df = pd.read_csv('../../data/Hotel_Reviews.csv')
end = time.time()
print("Loading took " + str(round(end - start, 2)) + " seconds")
```
Ora che i dati sono stati caricati, si possono eseguire alcune operazioni su di essi. Tenere questo codice nella parte superiore del programma per la parte successiva.
## Esplorare i dati
In questo caso, i dati sono già *puliti*, il che significa che sono pronti per essere lavorati e non ci sono caratteri in altre lingue che potrebbero far scattare algoritmi che si aspettano solo caratteri inglesi.
✅ Potrebbe essere necessario lavorare con dati che richiedono un'elaborazione iniziale per formattarli prima di applicare le tecniche di NLP, ma non questa volta. Se si dovesse, come si gestirebero i caratteri non inglesi?
Si prenda un momento per assicurarsi che una volta caricati, i dati possano essere esplorarati con il codice. È molto facile volersi concentrare sulle colonne `Negative_Review` e `Positive_Review` . Sono pieni di testo naturale per essere elaborato dagli algoritmi di NLP. Ma non è finita qui! Prima di entrare nel NLP e nel sentiment, si dovrebbe seguire il codice seguente per accertarsi se i valori forniti nell'insieme di dati corrispondono ai valori calcolati con pandas.
## Operazioni con dataframe
Il primo compito di questa lezione è verificare se le seguenti asserzioni sono corrette scrivendo del codice che esamini il dataframe (senza modificarlo).
> Come molte attività di programmazione, ci sono diversi modi per completarla, ma un buon consiglio è farlo nel modo più semplice e facile possibile, soprattutto se sarà più facile da capire quando si riesaminerà questo codice in futuro. Con i dataframe, esiste un'API completa che spesso avrà un modo per fare ciò che serve in modo efficiente.
Trattare le seguenti domande come attività di codifica e provare a rispondere senza guardare la soluzione.
1. Stampare la *forma* del dataframe appena caricato (la forma è il numero di righe e colonne)
2. Calcolare il conteggio della frequenza per le nazionalità dei recensori:
1. Quanti valori distinti ci sono per la colonna `Reviewer_Nationality` e quali sono?
2. Quale nazionalità del recensore è la più comune nell'insieme di dati (stampare nazione e numero di recensioni)?
3. Quali sono le prossime 10 nazionalità più frequenti e la loro frequenza?
3. Qual è stato l'hotel più recensito per ciascuna delle 10 nazionalità più recensite?
4. Quante recensioni ci sono per hotel (conteggio della frequenza dell'hotel) nell'insieme di dati?
5. Sebbene sia presente una colonna `Average_Score` per ogni hotel nell'insieme di dati, si può anche calcolare un punteggio medio (ottenendo la media di tutti i punteggi dei recensori nell'insieme di dati per ogni hotel). Aggiungere una nuova colonna al dataframe con l'intestazione della colonna `Calc_Average_Score` che contiene quella media calcolata.
6. Ci sono hotel che hanno lo stesso (arrotondato a 1 decimale) `Average_Score` e `Calc_Average_Score`?
1. Provare a scrivere una funzione Python che accetta una serie (riga) come argomento e confronta i valori, stampando un messaggio quando i valori non sono uguali. Quindi usare il metodo `.apply()` per elaborare ogni riga con la funzione.
7. Calcolare e stampare quante righe contengono valori di "No Negative" nella colonna `Negative_Review` "
8. Calcolare e stampare quante righe contengono valori di "No Positive" nella colonna `Positive_Review` "
9. Calcolare e stampare quante righe contengono valori di "No Positive" nella colonna `Positive_Review` " **e** valori di "No Negative" nella colonna `Negative_Review`
### Risposte
1. Stampare la *forma* del dataframei appena caricato (la forma è il numero di righe e colonne)
```python
print("The shape of the data (rows, cols) is " + str(df.shape))
> The shape of the data (rows, cols) is (515738, 17)
```
2. Calcolare il conteggio della frequenza per le nazionalità dei recensori:
1. Quanti valori distinti ci sono per la colonna `Reviewer_Nationality` e quali sono?
2. Quale nazionalità del recensore è la più comune nell'insieme di dati (paese di stampa e numero di recensioni)?
```python
# value_counts() crea un oggetto Series con indice e valori, in questo caso la nazione
# e la frequenza con la quale si manifestano nella nazionalità del recensore
nationality_freq = df["Reviewer_Nationality"].value_counts()
print("There are " + str(nationality_freq.size) + " different nationalities")
# stampa la prima e ultima riga della Series. Modificare in nationality_freq.to_string() per stampare tutti i dati
print(nationality_freq)
There are 227 different nationalities
United Kingdom 245246
United States of America 35437
Australia 21686
Ireland 14827
United Arab Emirates 10235
...
Comoros 1
Palau 1
Northern Mariana Islands 1
Cape Verde 1
Guinea 1
Name: Reviewer_Nationality, Length: 227, dtype: int64
```
3. Quali sono le prossime 10 nazionalità più frequenti e la loro frequenza?
```python
print("The highest frequency reviewer nationality is " + str(nationality_freq.index[0]).strip() + " with " + str(nationality_freq[0]) + " reviews.")
# Notare che c'è uno spazio davanti ai valori, strip() lo rimuove per la stampa
# Quale sono le 10 nazionalità più comuni e la loro frequenza?
print("The next 10 highest frequency reviewer nationalities are:")
print(nationality_freq[1:11].to_string())
The highest frequency reviewer nationality is United Kingdom with 245246 reviews.
The next 10 highest frequency reviewer nationalities are:
United States of America 35437
Australia 21686
Ireland 14827
United Arab Emirates 10235
Saudi Arabia 8951
Netherlands 8772
Switzerland 8678
Germany 7941
Canada 7894
France 7296
```
3. Qual è stato l'hotel più recensito per ciascuna delle 10 nazionalità più recensite?
```python
# Qual è stato l'hotel più recensito per ciascuna delle 10 nazionalità più recensite
# In genere con pandas si cerca di evitare un ciclo esplicito, ma si vuole mostrare come si crea un
# nuovo dataframe usando criteri (non fare questo con un grande volume di dati in quanto potrebbe essere molto lento)
for nat in nationality_freq[:10].index:
# Per prima cosa estrarre tutte le righe che corrispondono al criterio in un nuovo dataframe
nat_df = df[df["Reviewer_Nationality"] == nat]
# Ora ottenere la frequenza per l'hotel
freq = nat_df["Hotel_Name"].value_counts()
print("The most reviewed hotel for " + str(nat).strip() + " was " + str(freq.index[0]) + " with " + str(freq[0]) + " reviews.")
The most reviewed hotel for United Kingdom was Britannia International Hotel Canary Wharf with 3833 reviews.
The most reviewed hotel for United States of America was Hotel Esther a with 423 reviews.
The most reviewed hotel for Australia was Park Plaza Westminster Bridge London with 167 reviews.
The most reviewed hotel for Ireland was Copthorne Tara Hotel London Kensington with 239 reviews.
The most reviewed hotel for United Arab Emirates was Millennium Hotel London Knightsbridge with 129 reviews.
The most reviewed hotel for Saudi Arabia was The Cumberland A Guoman Hotel with 142 reviews.
The most reviewed hotel for Netherlands was Jaz Amsterdam with 97 reviews.
The most reviewed hotel for Switzerland was Hotel Da Vinci with 97 reviews.
The most reviewed hotel for Germany was Hotel Da Vinci with 86 reviews.
The most reviewed hotel for Canada was St James Court A Taj Hotel London with 61 reviews.
```
4. Quante recensioni ci sono per hotel (conteggio della frequenza dell'hotel) nell'insieme di dati?
```python
# Per prima cosa creare un nuovo dataframe in base a quello vecchio, togliendo le colonne non necessarie
hotel_freq_df = df.drop(["Hotel_Address", "Additional_Number_of_Scoring", "Review_Date", "Average_Score", "Reviewer_Nationality", "Negative_Review", "Review_Total_Negative_Word_Counts", "Positive_Review", "Review_Total_Positive_Word_Counts", "Total_Number_of_Reviews_Reviewer_Has_Given", "Reviewer_Score", "Tags", "days_since_review", "lat", "lng"], axis = 1)
# Raggruppre le righe per Hotel_Name, conteggiarle e inserire il risultato in una nuova colonna Total_Reviews_Found
hotel_freq_df['Total_Reviews_Found'] = hotel_freq_df.groupby('Hotel_Name').transform('count')
# Eliminare tutte le righe duplicate
hotel_freq_df = hotel_freq_df.drop_duplicates(subset = ["Hotel_Name"])
display(hotel_freq_df)
```
| Hotel_Name (Nome Hotel) | Total_Number_of_Reviews (Numero totale di recensioni) | Total_Reviews_Found |
| :----------------------------------------: | :---------------------: | :-----------------: |
| Britannia International Hotel Canary Wharf | 9086 | 4789 |
| Park Plaza Westminster Bridge Londra | 12158 | 4169 |
| Copthorne Tara Hotel London Kensington | 7105 | 3578 |
| ... | ... | ... |
| Mercure Paris Porte d'Orléans | 110 | 10 |
| Hotel Wagner | 135 | 10 |
| Hotel Gallitzinberg | 173 | 8 |
Si potrebbe notare che il *conteggio nell'insieme di dati* non corrisponde al valore in `Total_Number_of_Reviews`. Non è chiaro se questo valore nell'insieme di dati rappresentasse il numero totale di recensioni che l'hotel aveva, ma non tutte sono state recuperate o qualche altro calcolo. `Total_Number_of_Reviews` non viene utilizzato nel modello a causa di questa non chiarezza.
5. Sebbene sia presente una colonna `Average_Score` per ogni hotel nell'insieme di dati, si può anche calcolare un punteggio medio (ottenendo la media di tutti i punteggi dei recensori nell'insieme di dati per ogni hotel). Aggiungere una nuova colonna al dataframe con l'intestazione della colonna `Calc_Average_Score` che contiene quella media calcolata. Stampare le colonne `Hotel_Name`, `Average_Score` e `Calc_Average_Score`.
```python
# definisce una funzione che ottiene una riga ed esegue alcuni calcoli su di essa
def get_difference_review_avg(row):
return row["Average_Score"] - row["Calc_Average_Score"]
# 'mean' è la definizione matematica per 'average'
df['Calc_Average_Score'] = round(df.groupby('Hotel_Name').Reviewer_Score.transform('mean'), 1)
# Aggiunge una nuova colonna con la differenza tra le due medie di punteggio
df["Average_Score_Difference"] = df.apply(get_difference_review_avg, axis = 1)
# Crea un df senza tutti i duplicati di Hotel_Name (quindi una sola riga per hotel)
review_scores_df = df.drop_duplicates(subset = ["Hotel_Name"])
# Ordina il dataframe per trovare la differnza più bassa e più alta per il punteggio medio
review_scores_df = review_scores_df.sort_values(by=["Average_Score_Difference"])
display(review_scores_df[["Average_Score_Difference", "Average_Score", "Calc_Average_Score", "Hotel_Name"]])
```
Ci si potrebbe anche chiedere del valore `Average_Score` e perché a volte è diverso dal punteggio medio calcolato. Poiché non è possibile sapere perché alcuni valori corrispondano, ma altri hanno una differenza, in questo caso è più sicuro utilizzare i punteggi delle recensioni a disposizione per calcolare autonomamente la media. Detto questo, le differenze sono solitamente molto piccole, ecco gli hotel con la maggiore deviazione dalla media dell'insieme di dati e dalla media calcolata:
| Average_Score_Difference | Average_Score | Calc_Average_Score | Hotel_Name (Nome Hotel) |
| :----------------------: | :-----------: | :----------------: | ------------------------------------------: |
| -0,8 | 7,7 | 8,5 | Best Western Hotel Astoria |
| -0,7 | 8,8 | 9,5 | Hotel Stendhal Place Vend me Parigi MGallery |
| -0,7 | 7,5 | 8.2 | Mercure Paris Porte d'Orléans |
| -0,7 | 7,9 | 8,6 | Renaissance Paris Vendome Hotel |
| -0,5 | 7,0 | 7,5 | Hotel Royal Elys es |
| ... | ... | ... | ... |
| 0.7 | 7,5 | 6.8 | Mercure Paris Op ra Faubourg Montmartre |
| 0,8 | 7,1 | 6.3 | Holiday Inn Paris Montparnasse Pasteur |
| 0,9 | 6.8 | 5,9 | Villa Eugenia |
| 0,9 | 8,6 | 7,7 | MARCHESE Faubourg St Honor Relais Ch teaux |
| 1,3 | 7,2 | 5,9 | Kube Hotel Ice Bar |
Con un solo hotel con una differenza di punteggio maggiore di 1, significa che probabilmente si può ignorare la differenza e utilizzare il punteggio medio calcolato.
6. Calcolare e stampare quante righe hanno la colonna `Negative_Review` valori di "No Negative"
7. Calcolare e stampare quante righe hanno la colonna `Positive_Review` valori di "No Positive"
8. Calcolare e stampare quante righe hanno la colonna `Positive_Review` valori di "No Positive" **e** `Negative_Review` valori di "No Negative"
```python
# con funzini lambda:
start = time.time()
no_negative_reviews = df.apply(lambda x: True if x['Negative_Review'] == "No Negative" else False , axis=1)
print("Number of No Negative reviews: " + str(len(no_negative_reviews[no_negative_reviews == True].index)))
no_positive_reviews = df.apply(lambda x: True if x['Positive_Review'] == "No Positive" else False , axis=1)
print("Number of No Positive reviews: " + str(len(no_positive_reviews[no_positive_reviews == True].index)))
both_no_reviews = df.apply(lambda x: True if x['Negative_Review'] == "No Negative" and x['Positive_Review'] == "No Positive" else False , axis=1)
print("Number of both No Negative and No Positive reviews: " + str(len(both_no_reviews[both_no_reviews == True].index)))
end = time.time()
print("Lambdas took " + str(round(end - start, 2)) + " seconds")
Number of No Negative reviews: 127890
Number of No Positive reviews: 35946
Number of both No Negative and No Positive reviews: 127
Lambdas took 9.64 seconds
```
## Un'altra strada
Un altro modo per contare gli elementi senza Lambda e utilizzare sum per contare le righe:
```python
# senza funzioni lambda (usando un misto di notazioni per mostrare che si possono usare entrambi)
start = time.time()
no_negative_reviews = sum(df.Negative_Review == "No Negative")
print("Number of No Negative reviews: " + str(no_negative_reviews))
no_positive_reviews = sum(df["Positive_Review"] == "No Positive")
print("Number of No Positive reviews: " + str(no_positive_reviews))
both_no_reviews = sum((df.Negative_Review == "No Negative") & (df.Positive_Review == "No Positive"))
print("Number of both No Negative and No Positive reviews: " + str(both_no_reviews))
end = time.time()
print("Sum took " + str(round(end - start, 2)) + " seconds")
Number of No Negative reviews: 127890
Number of No Positive reviews: 35946
Number of both No Negative and No Positive reviews: 127
Sum took 0.19 seconds
```
Si potrebbe aver notato che ci sono 127 righe che hanno entrambi i valori "No Negative" e "No Positive" rispettivamente per le colonne `Negative_Review` e `Positive_Review` . Ciò significa che il recensore ha assegnato all'hotel un punteggio numerico, ma ha rifiutato di scrivere una recensione positiva o negativa. Fortunatamente questa è una piccola quantità di righe (127 su 515738, o 0,02%), quindi probabilmente non distorcerà il modello o i risultati in una direzione particolare, ma si potrebbe non aspettarsi che un insieme di dati di recensioni abbia righe con nessuna recensione, quindi vale la pena esplorare i dati per scoprire righe come questa.
Ora che si è esplorato l'insieme di dati, nella prossima lezione si filtreranno i dati e si aggiungerà un'analisi del sentiment.
---
## 🚀 Sfida
Questa lezione dimostra, come visto nelle lezioni precedenti, quanto sia di fondamentale importanza comprendere i dati e le loro debolezze prima di eseguire operazioni su di essi. I dati basati su testo, in particolare, sono oggetto di un attento esame. Esaminare vari insiemi di dati contenenti principalmente testo e vedere se si riesce a scoprire aree che potrebbero introdurre pregiudizi o sentiment distorti in un modello.
## [Quiz post-lezione](https://jolly-sea-0a877260f.azurestaticapps.net/quiz/38/)
## Revisione e Auto Apprendimento
Seguire [questo percorso di apprendimento su NLP](https://docs.microsoft.com/learn/paths/explore-natural-language-processing/?WT.mc_id=academic-15963-cxa) per scoprire gli strumenti da provare durante la creazione di modelli vocali e di testo.
## Compito
[NLTK](assignment.it.md)

@ -0,0 +1,5 @@
# NLTK
## Instructions
NLTK is a well-known library for use in computational linguistics and NLP. Take this opportunity to read through the '[NLTK book](https://www.nltk.org/book/)' and try out its exercises. In this ungraded assignment, you will get to know this library more deeply.

@ -0,0 +1,376 @@
# Analisi del sentiment con recensioni di hotel
Ora che si è esplorato in dettaglio l'insieme di dati, è il momento di filtrare le colonne e quindi utilizzare le tecniche NLP sull'insieme di dati per ottenere nuove informazioni sugli hotel.
## [Quiz Pre-Lezione](https://jolly-sea-0a877260f.azurestaticapps.net/quiz/39/)
### Operazioni di Filtraggio e Analisi del Sentiment
Come probabilmente notato, l'insieme di dati presenta alcuni problemi. Alcune colonne sono piene di informazioni inutili, altre sembrano errate. Se sono corrette, non è chiaro come sono state calcolate e le risposte non possono essere verificate in modo indipendente dai propri calcoli.
## Esercizio: un po' più di elaborazione dei dati
Occorre pulire un po' di più i dati. Si aggiungono colonne che saranno utili in seguito, si modificano i valori in altre colonne e si eliminano completamente determinate colonne.
1. Elaborazione iniziale colonne
1. Scartare `lat` e `lng`
2. Sostituire i valori `Hotel_Address` con i seguenti valori (se l'indirizzo contiene lo stesso della città e del paese, si cambia solo con la città e la nazione).
Queste sono le uniche città e nazioni nell'insieme di dati:
Amsterdam, Netherlands
Barcelona, Spain
London, United Kingdom
Milan, Italy
Paris, France
Vienna, Austria
```python
def replace_address(row):
if "Netherlands" in row["Hotel_Address"]:
return "Amsterdam, Netherlands"
elif "Barcelona" in row["Hotel_Address"]:
return "Barcelona, Spain"
elif "United Kingdom" in row["Hotel_Address"]:
return "London, United Kingdom"
elif "Milan" in row["Hotel_Address"]:
return "Milan, Italy"
elif "France" in row["Hotel_Address"]:
return "Paris, France"
elif "Vienna" in row["Hotel_Address"]:
return "Vienna, Austria"
# Sostituisce tutti gli indirizzi con una forma ridotta più utile
df["Hotel_Address"] = df.apply(replace_address, axis = 1)
# La somma di value_counts() dovrebbe sommarsi al numero totale recensioni
print(df["Hotel_Address"].value_counts())
```
Ora si possono interrogare i dati a livello di nazione:
```python
display(df.groupby("Hotel_Address").agg({"Hotel_Name": "nunique"}))
```
| Hotel_Address | Hotel_Name (Nome Hotel) |
| :--------------------- | :--------: |
| Amsterdam, Paesi Bassi | 105 |
| Barcellona, Spagna | 211 |
| Londra, Regno Unito | 400 |
| Milano, Italia | 162 |
| Parigi, Francia | 458 |
| Vienna, Austria | 158 |
2. Elaborazione colonne di meta-recensione dell'hotel
1. Eliminare `Additional_Number_of_Scoring`
1. Sostituire `Total_Number_of_Reviews` con il numero totale di recensioni per quell'hotel che sono effettivamente nell'insieme di dati
1. Sostituire `Average_Score` con il punteggio calcolato via codice
```python
# Elimina `Additional_Number_of_Scoring`
df.drop(["Additional_Number_of_Scoring"], axis = 1, inplace=True)
# Sostituisce `Total_Number_of_Reviews` e `Average_Score` con i propri valori calcolati
df.Total_Number_of_Reviews = df.groupby('Hotel_Name').transform('count')
df.Average_Score = round(df.groupby('Hotel_Name').Reviewer_Score.transform('mean'), 1)
```
3. Elaborazione delle colonne di recensione
1. Eliminare `Review_Total_Negative_Word_Counts`, `Review_Total_Positive_Word_Counts`, `Review_Date` e `days_since_review`
2. Mantenere `Reviewer_Score`, `Negative_Review` e `Positive_Review` così come sono
3. Conservare i `Tags` per ora
- Si faranno alcune operazioni di filtraggio aggiuntive sui tag nella prossima sezione, successivamente i tag verranno eliminati
4. Elaborazione delle colonne del recensore
1. Scartare `Total_Number_of_Reviews_Reviewer_Has_Given`
2. Mantenere `Reviewer_Nationality`
### Colonne tag
Le colonne `Tag` sono problematiche in quanto si tratta di un elenco (in formato testo) memorizzato nella colonna. Purtroppo l'ordine e il numero delle sottosezioni in questa colonna non sono sempre gli stessi. È difficile per un essere umano identificare le frasi corrette a cui essere interessato, perché ci sono 515.000 righe e 1427 hotel e ognuno ha opzioni leggermente diverse che un recensore potrebbe scegliere. È qui che la NLP brilla. Si può scansionare il testo, trovare le frasi più comuni e contarle.
Purtroppo non interessano parole singole, ma frasi composte da più parole (es. *Viaggio di lavoro*). L'esecuzione di un algoritmo di distribuzione della frequenza a più parole su così tanti dati (6762646 parole) potrebbe richiedere una quantità straordinaria di tempo, ma senza guardare i dati, sembrerebbe che sia una spesa necessaria. È qui che l'analisi dei dati esplorativi diventa utile, perché si è visto un esempio di tag come `["Business trip", "Solo traveler", "Single Room", "Stayed 5 nights", "Submitted from a mobile device"]` , si può iniziare a chiedersi se è possibile ridurre notevolmente l'elaborazione da fare. Fortunatamente lo è, ma prima occorre seguire alcuni passaggi per accertare i tag di interesse.
### Filtraggio tag
Ricordare che l'obiettivo dell'insieme di dati è aggiungere il sentiment e le colonne che aiuteranno a scegliere l'hotel migliore (per se stessi o forse per un cliente che incarica di creare un bot di raccomandazione dell'hotel). Occorre chiedersi se i tag sono utili o meno nell'insieme di dati finale. Ecco un'interpretazione (se serve l'insieme di dati per altri motivi diversi tag potrebbero rimanere dentro/fuori dalla selezione):
1. Il tipo di viaggio è rilevante e dovrebbe rimanere
2. Il tipo di gruppo di ospiti è importante e dovrebbe rimanere
3. Il tipo di camera, suite o monolocale in cui ha soggiornato l'ospite è irrilevante (tutti gli hotel hanno praticamente le stesse stanze)
4. Il dispositivo su cui è stata inviata la recensione è irrilevante
5. Il numero di notti in cui il recensore ha soggiornato *potrebbe* essere rilevante se si attribuisce a soggiorni più lunghi un gradimento maggiore per l'hotel, ma è una forzatura e probabilmente irrilevante
In sintesi, si **mantengono 2 tipi di tag e si rimuove il resto**.
Innanzitutto, non si vogliono contare i tag finché non sono in un formato migliore, quindi ciò significa rimuovere le parentesi quadre e le virgolette. Si può fare in diversi modi, ma serve il più veloce in quanto potrebbe richiedere molto tempo per elaborare molti dati. Fortunatamente, pandas ha un modo semplice per eseguire ciascuno di questi passaggi.
```Python
# Rimuove le parentesi quadre di apertura e chiusura
df.Tags = df.Tags.str.strip("[']")
# rimuove anche tutte le virgolette
df.Tags = df.Tags.str.replace(" ', '", ",", regex = False)
```
Ogni tag diventa qualcosa come: `Business trip, Solo traveler, Single Room, Stayed 5 nights, Submitted from a mobile device`.
Successivamente si manifesta un problema. Alcune recensioni, o righe, hanno 5 colonne, altre 3, altre 6. Questo è il risultato di come è stato creato l'insieme di dati ed è difficile da risolvere. Si vuole ottenere un conteggio della frequenza di ogni frase, ma sono in ordine diverso in ogni recensione, quindi il conteggio potrebbe essere disattivato e un hotel potrebbe non ricevere un tag assegnato per ciò che meritava.
Si utilizzerà invece l'ordine diverso a proprio vantaggio, perché ogni tag è composto da più parole ma anche separato da una virgola! Il modo più semplice per farlo è creare 6 colonne temporanee con ogni tag inserito nella colonna corrispondente al suo ordine nel tag. Quindi si uniscono le 6 colonne in una grande colonna e si esegue il metodo `value_counts()` sulla colonna risultante. Stampandolo, si vedrà che c'erano 2428 tag univoci. Ecco un piccolo esempio:
| Tag | Count |
| ------------------------------ | ------ |
| Leisure trip | 417778 |
| Submitted from a mobile device | 307640 |
| Couple | 252294 |
| Stayed 1 night | 193645 |
| Stayed 2 nights | 133937 |
| Solo traveler | 108545 |
| Stayed 3 nights | 95821 |
| Business trip | 82939 |
| Group | 65392 |
| Family with young children | 61015 |
| Stayed 4 nights | 47817 |
| Double Room | 35207 |
| Standard Double Room | 32248 |
| Superior Double Room | 31393 |
| Family with older children | 26349 |
| Deluxe Double Room | 24823 |
| Double or Twin Room | 22393 |
| Stayed 5 nights | 20845 |
| Standard Double or Twin Room | 17483 |
| Classic Double Room | 16989 |
| Superior Double or Twin Room | 13570 |
| 2 rooms | 12393 |
Alcuni dei tag comuni come `Submitted from a mobile device` non sono di alcuna utilità, quindi potrebbe essere una cosa intelligente rimuoverli prima di contare l'occorrenza della frase, ma è un'operazione così veloce che si possono lasciare e ignorare.
### Rimozione della durata dai tag di soggiorno
La rimozione di questi tag è il passaggio 1, riduce leggermente il numero totale di tag da considerare. Notare che non si rimuovono dall'insieme di dati, si sceglie semplicemente di rimuoverli dalla considerazione come valori da contare/mantenere nell'insieme di dati delle recensioni.
| Length of stay | Count |
| ---------------- | ------ |
| Stayed 1 night | 193645 |
| Stayed 2 nights | 133937 |
| Stayed 3 nights | 95821 |
| Stayed 4 nights | 47817 |
| Stayed 5 nights | 20845 |
| Stayed 6 nights | 9776 |
| Stayed 7 nights | 7399 |
| Stayed 8 nights | 2502 |
| Stayed 9 nights | 1293 |
| ... | ... |
C'è una grande varietà di camere, suite, monolocali, appartamenti e così via. Significano tutti più o meno la stessa cosa e non sono rilevanti allo scopo, quindi si rimuovono dalla considerazione.
| Type of room | Count |
| ----------------------------- | ----- |
| Double Room | 35207 |
| Standard Double Room | 32248 |
| Superior Double Room | 31393 |
| Deluxe Double Room | 24823 |
| Double or Twin Room | 22393 |
| Standard Double or Twin Room | 17483 |
| Classic Double Room | 16989 |
| Superior Double or Twin Room | 13570 |
Infine, e questo è delizioso (perché non ha richiesto molta elaborazione), rimarranno i seguenti tag *utili*:
| Tag | Count |
| --------------------------------------------- | ------ |
| Leisure trip | 417778 |
| Couple | 252294 |
| Solo traveler | 108545 |
| Business trip | 82939 |
| Group (combined with Travellers with friends) | 67535 |
| Family with young children | 61015 |
| Family with older children | 26349 |
| With a pet | 1405 |
Si potrebbe obiettare che `Travellers with friends` (Viaggiatori con amici) è più o meno lo stesso di `Group` (Gruppo), e sarebbe giusto combinare i due come fatto sopra. Il codice per identificare i tag corretti è [il notebook Tags](../solution/1-notebook.ipynb).
Il passaggio finale consiste nel creare nuove colonne per ciascuno di questi tag. Quindi, per ogni riga di recensione, se la colonna `Tag` corrisponde a una delle nuove colonne, aggiungere 1, in caso contrario aggiungere 0. Il risultato finale sarà un conteggio di quanti recensori hanno scelto questo hotel (in aggregato) per, ad esempio, affari o piacere, o per portare un animale domestico, e questa è un'informazione utile quando consiglia un hotel.
```python
# Elabora Tags in nuove colonne
# Il file Hotel_Reviews_Tags.py, identifica i tag più importanti
# Leisure trip, Couple, Solo traveler, Business trip, Group combinato con Travelers with friends,
# Family with young children, Family with older children, With a pet
df["Leisure_trip"] = df.Tags.apply(lambda tag: 1 if "Leisure trip" in tag else 0)
df["Couple"] = df.Tags.apply(lambda tag: 1 if "Couple" in tag else 0)
df["Solo_traveler"] = df.Tags.apply(lambda tag: 1 if "Solo traveler" in tag else 0)
df["Business_trip"] = df.Tags.apply(lambda tag: 1 if "Business trip" in tag else 0)
df["Group"] = df.Tags.apply(lambda tag: 1 if "Group" in tag or "Travelers with friends" in tag else 0)
df["Family_with_young_children"] = df.Tags.apply(lambda tag: 1 if "Family with young children" in tag else 0)
df["Family_with_older_children"] = df.Tags.apply(lambda tag: 1 if "Family with older children" in tag else 0)
df["With_a_pet"] = df.Tags.apply(lambda tag: 1 if "With a pet" in tag else 0)
```
### Salvare il file.
Infine, salvare l'insieme di dati così com'è ora con un nuovo nome.
```python
df.drop(["Review_Total_Negative_Word_Counts", "Review_Total_Positive_Word_Counts", "days_since_review", "Total_Number_of_Reviews_Reviewer_Has_Given"], axis = 1, inplace=True)
# Salvataggio del nuovo file dati con le colonne calcolate
print("Saving results to Hotel_Reviews_Filtered.csv")
df.to_csv(r'../data/Hotel_Reviews_Filtered.csv', index = False)
```
## Operazioni di Analisi del Sentiment
In questa sezione finale, si applicherà l'analisi del sentiment alle colonne di recensione e si salveranno i risultati in un insieme di dati.
## Esercizio: caricare e salvare i dati filtrati
Tenere presente che ora si sta caricando l'insieme di dati filtrato che è stato salvato nella sezione precedente, **non** quello originale.
```python
import time
import pandas as pd
import nltk as nltk
from nltk.corpus import stopwords
from nltk.sentiment.vader import SentimentIntensityAnalyzer
nltk.download('vader_lexicon')
# Carica le recensioni di hotel filtrate dal CSV
df = pd.read_csv('../../data/Hotel_Reviews_Filtered.csv')
# Il proprio codice andrà aggiunto qui
# Infine ricordarsi di salvare le recensioni di hotel con i nuovi dati NLP aggiunti
print("Saving results to Hotel_Reviews_NLP.csv")
df.to_csv(r'../data/Hotel_Reviews_NLP.csv', index = False)
```
### Rimozione delle stop word
Se si dovesse eseguire l'analisi del sentiment sulle colonne delle recensioni negative e positive, potrebbe volerci molto tempo. Testato su un potente laptop di prova con CPU veloce, ci sono voluti 12 - 14 minuti a seconda della libreria di sentiment utilizzata. È un tempo (relativamente) lungo, quindi vale la pena indagare se può essere accelerato.
Il primo passo è rimuovere le stop word, o parole inglesi comuni che non cambiano il sentiment di una frase. Rimuovendole, l'analisi del sentiment dovrebbe essere eseguita più velocemente, ma non essere meno accurata (poiché le stop word non influiscono sul sentiment, ma rallentano l'analisi).
La recensione negativa più lunga è stata di 395 parole, ma dopo aver rimosso le stop word, è di 195 parole.
Anche la rimozione delle stop word è un'operazione rapida, poiché la rimozione di esse da 2 colonne di recensione su 515.000 righe ha richiesto 3,3 secondi sul dispositivo di test. Potrebbe volerci un po' più o meno tempo a seconda della velocità della CPU del proprio dispositivo, della RAM, del fatto che si abbia o meno un SSD e alcuni altri fattori. La relativa brevità dell'operazione significa che se migliora il tempo di analisi del sentiment, allora vale la pena farlo.
```python
from nltk.corpus import stopwords
# Carica le recensioni di hotel da CSV
df = pd.read_csv("../../data/Hotel_Reviews_Filtered.csv")
# Rimuove le stop word - potrebbe essere lento quando c'è molto testo!
# Ryan Han (ryanxjhan su Kaggle) ha un gran post riguardo al misurare le prestazioni di diversi approcci per la rimozione delle stop word
# https://www.kaggle.com/ryanxjhan/fast-stop-words-removal # si usa l'approccio raccomandato da Ryan
start = time.time()
cache = set(stopwords.words("english"))
def remove_stopwords(review):
text = " ".join([word for word in review.split() if word not in cache])
return text
# Rimuove le stop word da entrambe le colonne
df.Negative_Review = df.Negative_Review.apply(remove_stopwords)
df.Positive_Review = df.Positive_Review.apply(remove_stopwords)
```
### Esecuzione dell'analisi del sentiment
Ora si dovrebbe calcolare l'analisi del sentiment per le colonne di recensioni negative e positive e memorizzare il risultato in 2 nuove colonne. Il test del sentiment sarà quello di confrontarlo con il punteggio del recensore per la stessa recensione. Ad esempio, se il sentiment ritiene che la recensione negativa abbia avuto un sentiment pari a 1 (giudizio estremamente positivo) e un sentiment positivo della recensione pari a 1, ma il recensore ha assegnato all'hotel il punteggio più basso possibile, allora il testo della recensione non corrisponde al punteggio, oppure l'analizzatore del sentiment non è stato in grado di riconoscere correttamente il sentiment. Ci si dovrebbe aspettare che alcuni punteggi del sentiment siano completamente sbagliati, e spesso ciò sarà spiegabile, ad esempio la recensione potrebbe essere estremamente sarcastica "Certo che mi è piaciuto dormire in una stanza senza riscaldamento" e l'analizzatore del sentimento pensa che sia un sentimento positivo, anche se un un lettore umano avrebbe rilevato il sarcasmo.
NLTK fornisce diversi analizzatori di sentiment con cui imparare e si possono sostituire e vedere se il sentiment è più o meno accurato. Qui viene utilizzata l'analisi del sentiment di VADER.
> Hutto, CJ & Gilbert, EE (2014). VADER: A Parsimonious Rule-based Model for Sentiment Analysis of Social Media Text. Ottava Conferenza Internazionale su Weblog e Social Media (ICWSM-14). Ann Arbor, MI, giugno 2014.
```python
from nltk.sentiment.vader import SentimentIntensityAnalyzer
# Crea l'analizzatore di sentiment vader (ce ne sono altri in NLTK che si possono provare)
vader_sentiment = SentimentIntensityAnalyzer()
# Hutto, C.J. & Gilbert, E.E. (2014). VADER: A Parsimonious Rule-based Model for Sentiment Analysis of Social Media Text. Eighth International Conference on Weblogs and Social Media (ICWSM-14). Ann Arbor, MI, June 2014.
# Ci sono tre possibilità di input per un recensore:
# Potrebbe essere "No Negative", nel qual caso ritorna 0
# Potrebbe essere "No Positive", nel qual caso ritorna 0
# Potrebbe essere una recensione, nel qual caso calcola il sentiment
def calc_sentiment(review):
if review == "No Negative" or review == "No Positive":
return 0
return vader_sentiment.polarity_scores(review)["compound"]
```
Più avanti nel programma, quando si è pronti per calcolare il sentiment, lo si può applicare a ciascuna recensione come segue:
```python
# Aggiunge una colonna di sentiment negativa e positiva
print("Calculating sentiment columns for both positive and negative reviews")
start = time.time()
df["Negative_Sentiment"] = df.Negative_Review.apply(calc_sentiment)
df["Positive_Sentiment"] = df.Positive_Review.apply(calc_sentiment)
end = time.time()
print("Calculating sentiment took " + str(round(end - start, 2)) + " seconds")
```
Questo richiede circa 120 secondi sul computer utilizzato, ma varierà per ciascun computer. Se si vogliono stampare i risultati e vedere se il sentiment corrisponde alla recensione:
```python
df = df.sort_values(by=["Negative_Sentiment"], ascending=True)
print(df[["Negative_Review", "Negative_Sentiment"]])
df = df.sort_values(by=["Positive_Sentiment"], ascending=True)
print(df[["Positive_Review", "Positive_Sentiment"]])
```
L'ultima cosa da fare con il file prima di utilizzarlo nella sfida è salvarlo! Si dovrrebbe anche considerare di riordinare tutte le nuove colonne in modo che sia facile lavorarci (per un essere umano, è un cambiamento estetico).
```python
# Riordina le colonne (E' un estetismo ma facilita l'esplorazione successiva dei dati)
df = df.reindex(["Hotel_Name", "Hotel_Address", "Total_Number_of_Reviews", "Average_Score", "Reviewer_Score", "Negative_Sentiment", "Positive_Sentiment", "Reviewer_Nationality", "Leisure_trip", "Couple", "Solo_traveler", "Business_trip", "Group", "Family_with_young_children", "Family_with_older_children", "With_a_pet", "Negative_Review", "Positive_Review"], axis=1)
print("Saving results to Hotel_Reviews_NLP.csv")
df.to_csv(r"../data/Hotel_Reviews_NLP.csv", index = False)
```
Si dovrebbe eseguire l'intero codice per [il notebook di analisi](../solution/3-notebook.ipynb) (dopo aver eseguito [il notebook di filtraggio](../solution/1-notebook.ipynb) per generare il file Hotel_Reviews_Filtered.csv).
Per riepilogare, i passaggi sono:
1. Il file del'insieme di dati originale **Hotel_Reviews.csv** è stato esplorato nella lezione precedente con [il notebook explorer](../../4-Hotel-Reviews-1/solution/notebook.ipynb)
2. Hotel_Reviews.csv viene filtrato [dal notebook di filtraggio](../solution/1-notebook.ipynb) risultante in **Hotel_Reviews_Filtered.csv**
3. Hotel_Reviews_Filtered.csv viene elaborato dal [notebook di analisi del sentiment](../solution/3-notebook.ipynb) risultante in **Hotel_Reviews_NLP.csv**
4. Usare Hotel_Reviews_NLP.csv nella Sfida NLP di seguito
### Conclusione
Quando si è iniziato, si disponeva di un insieme di dati con colonne e dati, ma non tutto poteva essere verificato o utilizzato. Si sono esplorati i dati, filtrato ciò che non serve, convertito i tag in qualcosa di utile, calcolato le proprie medie, aggiunto alcune colonne di sentiment e, si spera, imparato alcune cose interessanti sull'elaborazione del testo naturale.
## [Quiz post-lezione](https://jolly-sea-0a877260f.azurestaticapps.net/quiz/40/)
## Sfida
Ora che si è analizzato il proprio insieme di dati per il sentiment, vedere se si possono usare le strategie apprese in questo programma di studi (clustering, forse?) per determinare modelli intorno al sentiment.
## recensione e Auto Apprendimento
Seguire [questo modulo di apprendimento](https://docs.microsoft.com/en-us/learn/modules/classify-user-feedback-with-the-text-analytics-api/?WT.mc_id=academic-15963-cxa) per saperne di più e utilizzare diversi strumenti per esplorare il sentiment nel testo.
## Compito
[Provare un insieme di dati diverso](assignment.it.md)

@ -0,0 +1,11 @@
# Provare un insieme di dati diverso
## Istruzioni
Ora che si è imparato a usare NLTK per assegnare sentiment al testo, provare un insieme di dati diverso. Probabilmente si dovranno elaborare dei dati attorno ad esso, quindi creare un notebook e documentare il proprio processo di pensiero. Cosa si è scoperto?
## Rubrica
| Criteri | Ottimo | Adeguato | Necessita miglioramento |
| -------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------- | ---------------------- |
| | Vengono presentati un notebook completo e un insieme di dati con celle ben documentate che spiegano come viene assegnato il sentiment | Il notebook manca di buone spiegazioni | Il notebook è difettoso |

@ -0,0 +1,24 @@
# Iniziare con l'elaborazione del linguaggio naturale
L'elaborazione del linguaggio naturale, NLP, è un sottocampo dell'intelligenza artificiale. L'intero campo è volto ad aiutare le macchine a comprendere ed elaborare il linguaggio umano. Questo può quindi essere utilizzato per eseguire attività come il controllo ortografico o la traduzione automatica.
## Argomento regionale: lingue e letterature europee e hotel romantici d'Europa ❤️
In questa sezione del programma di studi, verrà presentato uno degli usi più diffusi di machine learning: l'elaborazione del linguaggio naturale (NLP). Derivato dalla linguistica computazionale, questa categoria di intelligenza artificiale è il ponte tra umani e macchine tramite la comunicazione vocale o testuale.
In queste lezioni si impareranno le basi di NLP costruendo piccoli bot conversazionali per imparare come machine learning aiuti a rendere queste conversazioni sempre più "intelligenti". Si viaggerà indietro nel tempo, chiacchierando con Elizabeth Bennett e Mr. Darcy dal romanzo classico di Jane Austen, **Orgoglio e pregiudizio**, pubblicato nel 1813. Quindi, si approfondiranno le proprie conoscenze imparando l'analisi del sentiment tramite le recensioni di hotel in Europa.
![Libro e tè di Orgoglio e Pregiudizio](../images/p&p.jpg)
> Foto di <a href="https://unsplash.com/@elaineh?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Elaine Howlin</a> su <a href="https://unsplash.com/s/photos/pride-and-prejudice?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>
## Lezioni
1. [Introduzione all'elaborazione del linguaggio naturale](../1-Introduction-to-NLP/translations/README.it.md)
2. [Compiti e tecniche comuni di NLP](../2-Tasks/translations/README.it.md)
3. [Traduzione e analisi del sentiment con machine learning](../3-Translation-Sentiment/translations/README.it.md)
4. [Preparazione dei dati](../4-Hotel-Reviews-1/translations/README.it.md)
5. [NLTK per l'analisi del sentiment](../5-Hotel-Reviews-2/translations/README.it.md)
## Crediti
Queste lezioni sull'elaborazione del linguaggio naturale sono state scritte con ☕ da [Stephen Howell](https://twitter.com/Howell_MSFT)
Loading…
Cancel
Save