Corso
Introduzione a NLP e PyTorch
Il Natural Language Processing (NLP) è una componente fondamentale dell’IA moderna, perché permette alle macchine di comprendere e rispondere al linguaggio umano. Con il proliferare delle interazioni digitali, l’importanza dell’NLP cresce sempre di più. PyTorch, una popolare libreria open-source di machine learning, offre strumenti solidi per i compiti di NLP grazie alla sua flessibilità e all’efficienza nel calcolo sui tensori. Il suo grafo computazionale dinamico facilita inoltre la modifica e la costruzione di modelli complessi, rendendolo ideale per il nostro tutorial.
Se vuoi approfondire l’NLP, dai un’occhiata al nostro percorso di competenze Natural Language Processing in Python; se invece preferisci imparare l’arte dell’NLP in R, consulta il corso Introduction to Natural Language Processing in R su DataCamp.
Configurazione dell’ambiente
Configurare l’ambiente PyTorch può essere talvolta impegnativo a causa di fattori come sistema operativo, gestore di pacchetti preferito, linguaggio di programmazione e piattaforma di calcolo. Il processo di installazione può variare leggermente in base a questi fattori, richiedendo l’esecuzione di comandi specifici.
Per ottenere il comando di installazione appropriato, puoi visitare la pagina ufficiale di PyTorch get started, dove puoi selezionare le tue preferenze e ricevere le istruzioni necessarie.

Per questo tutorial useremo DataLab. Il codice completo per l’addestramento di un modello di analisi del sentiment con PyTorch è disponibile in questo workbook di DataLab se vuoi seguirlo passo passo.
Introduzione ai tensori

I tensori sono strutture dati fondamentali in matematica e fisica che generalizzano scalari, vettori e matrici. Sono array multidimensionali in grado di memorizzare e manipolare grandi quantità di dati numerici in modo efficiente. I tensori hanno una forma, una dimensione e un tipo di dato definiti, il che li rende versatili per diverse operazioni computazionali.
Nel contesto di PyTorch, i tensori sono i principali mattoni e gli oggetti di rappresentazione dei dati. I tensori in PyTorch sono simili agli array di NumPy ma includono funzionalità e ottimizzazioni aggiuntive pensate specificamente per i calcoli di deep learning. Le operazioni sui tensori in PyTorch sfruttano l’accelerazione hardware, come le GPU, per il calcolo efficiente di reti neurali complesse.
I tensori svolgono un ruolo cruciale nei compiti di elaborazione del linguaggio naturale (NLP) a causa della natura intrinsecamente sequenziale e gerarchica dei dati linguistici.
L’NLP implica il processamento e la comprensione di informazioni testuali. I tensori consentono di rappresentare e manipolare i dati testuali codificando parole, frasi o documenti come vettori numerici.
Questa rappresentazione numerica permette ai modelli di deep learning di processare e apprendere efficacemente dai dati testuali. I tensori consentono di gestire in modo efficiente dataset linguistici su larga scala, facilitano l’addestramento di reti neurali e abilitano tecniche avanzate come i meccanismi di attenzione per modelli di NLP più accurati.
Word embedding

I word embedding sono rappresentazioni dense delle parole in uno spazio vettoriale continuo. Mirano a catturare le relazioni semantiche e sintattiche tra le parole, permettendo una migliore comprensione e contestualizzazione dei dati testuali. Rappresentando le parole come vettori numerici, gli embedding catturano somiglianze e differenze semantiche, consentendo agli algoritmi di lavorare con le parole come input numerici significativi.
In parole semplici, gli embedding sono un modo intelligente di rappresentare le parole come numeri. Questi numeri hanno significati particolari che riflettono come le parole sono correlate tra loro. È come un codice segreto che aiuta i computer a capire e lavorare con le parole più facilmente.
Word2Vec e GloVe sono due metodi popolari per generare word embedding. Word2Vec è un modello basato su rete neurale che impara le rappresentazioni delle parole prevedendo le parole circostanti dato un termine target (continuous bag of words - CBOW) oppure prevedendo il termine target in base al suo contesto (skip-gram).
GloVe (Global Vectors for Word Representation) è un metodo basato sul conteggio che costruisce vettori di parole a partire dalle statistiche di co-occorrenza dei termini in un grande corpus. Cattura relazioni globali tra le parole e spesso offre prestazioni migliori nei compiti di analogia.
Architettura del modello NLP

Esempio di architettura di modello per il compito di analisi del sentiment.
L’analisi del sentiment è un compito comune in NLP in cui l’obiettivo è capire il sentimento espresso in un testo, spesso classificato come positivo, negativo o neutro. Per affrontare questo compito, si può usare una semplice recurrent neural network (RNN) o una versione più avanzata chiamata long short-term memory (LSTM).
RNN
L’architettura RNN elabora il testo in sequenza, inserendo le parole una dopo l’altra. La rete mantiene uno stato nascosto che cambia con ogni parola in input, catturando le informazioni dalla sequenza elaborata fino a quel momento.
Questo stato nascosto funge da memoria della rete. Tuttavia, le RNN standard faticano con sequenze lunghe a causa del cosiddetto problema del gradiente che svanisce: il contributo delle informazioni decade geometricamente nel tempo, facendo sì che la rete “dimentichi” gli input precedenti. Puoi saperne di più sulle reti neurali ricorrenti nel nostro tutorial sulle RNN.
LSTM
Per ovviare a ciò, è stata sviluppata l’LSTM, una variante delle RNN. Un’LSTM mantiene un contesto o “memoria” più lungo grazie a una struttura interna più complessa del suo stato nascosto. Dispone di una serie di “gate” (gate di input, di dimenticanza e di output) che controllano il flusso di informazioni dentro e fuori dallo stato di memoria.
Il gate di input determina quanto delle informazioni in arrivo deve essere memorizzato. Il gate di dimenticanza decide quali informazioni scartare e il gate di output definisce quanta parte dello stato interno viene esposta all’unità LSTM successiva nella sequenza.
Un modello RNN o LSTM prende in input una sequenza di parole di una frase o di un documento. Ogni parola è in genere rappresentata come un vettore denso, o embedding, che cattura il significato semantico della parola.
La rete elabora la sequenza parola per parola, aggiornando il suo stato interno in base alla parola corrente e allo stato precedente.
Lo stato finale della rete viene poi usato per prevedere il sentiment. Viene passato attraverso uno strato completamente connesso, seguito da una funzione di attivazione softmax per produrre una distribuzione di probabilità sulle classi di sentiment (ad esempio, positivo, negativo, neutro).
La classe con la probabilità più alta viene scelta come previsione del modello.
Questa è un’impostazione di base che può essere ulteriormente migliorata con tecniche come le LSTM bidirezionali (che elaborano la sequenza in entrambe le direzioni) e i meccanismi di attenzione (che permettono al modello di concentrarsi sulle parti importanti della sequenza), tra le altre.
Addestrare un modello LSTM in PyTorch per l’analisi del sentiment
Esempio di codice Python end-to-end per costruire un modello di analisi del sentiment usando PyTorch
1. Caricare il dataset
In questo esempio useremo l’IMDB dataset of 50K Movie reviews. L’obiettivo è addestrare un modello LSTM per prevedere il sentiment. Sono possibili due valori: "positive" e "negative". Si tratta quindi di un compito di classificazione binaria.
file_name = 'IMDB Dataset.csv'
df = pd.read_csv(file_name)
df.head()

2. Analisi esplorativa dei dati
X,y = df['review'].values,df['sentiment'].values
x_train,x_test,y_train,y_test = train_test_split(X,y,stratify=y)
print(f'train data shape: {x_train.shape}')
print(f'test data shape: {x_test.shape}')
dd = pd.Series(y_train).value_counts()
sns.barplot(x=np.array(['negative','positive']),y=dd.values)
plt.show()
Output:
>>> train data shape: (37500,)
>>> test data shape: (12500,)

3. Preprocessing del testo
Il preprocessing del testo e la tokenizzazione sono un primo passo fondamentale. Per iniziare, puliamo i dati testuali rimuovendo punteggiatura, spazi extra e numeri.
Poi trasformiamo le frasi in parole singole, rimuoviamo le parole comuni (note come "stop word") e teniamo traccia delle 1000 parole più frequenti nel dataset. A queste parole viene quindi assegnato un identificatore univoco, formando un dizionario per la one-hot encoding.
In sostanza, il codice converte le frasi di testo originali in sequenze di questi identificatori univoci, traducendo il linguaggio umano in un formato comprensibile da un modello di machine learning.
def preprocess_string(s):
# Remove all non-word characters (everything except numbers and letters)
s = re.sub(r"[^\w\s]", '', s)
# Replace all runs of whitespaces with no space
s = re.sub(r"\s+", '', s)
# replace digits with no space
s = re.sub(r"\d", '', s)
return s
def tokenize(x_train,y_train,x_val,y_val):
word_list = []
stop_words = set(stopwords.words('english'))
for sent in x_train:
for word in sent.lower().split():
word = preprocess_string(word)
if word not in stop_words and word != '':
word_list.append(word)
corpus = Counter(word_list)
# sorting on the basis of most common words
corpus_ = sorted(corpus,key=corpus.get,reverse=True)[:1000]
# creating a dict
onehot_dict = {w:i+1 for i,w in enumerate(corpus_)}
# tokenize
final_list_train,final_list_test = [],[]
for sent in x_train:
final_list_train.append([onehot_dict[preprocess_string(word)] for word in sent.lower().split()
if preprocess_string(word) in onehot_dict.keys()])
for sent in x_val:
final_list_test.append([onehot_dict[preprocess_string(word)] for word in sent.lower().split()
if preprocess_string(word) in onehot_dict.keys()])
encoded_train = [1 if label =='positive' else 0 for label in y_train]
encoded_test = [1 if label =='positive' else 0 for label in y_val]
return np.array(final_list_train), np.array(encoded_train),np.array(final_list_test), np.array(encoded_test),onehot_dict
x_train,y_train,x_test,y_test,vocab = tokenize(x_train,y_train,x_test,y_test)
Analizziamo la lunghezza dei token in x_train.
rev_len = [len(i) for i in x_train]
pd.Series(rev_len).hist()

4. Preparare i dati per il modello
Data la lunghezza variabile dei token in ogni recensione, è necessario standardizzarle per coerenza. Poiché la maggior parte delle recensioni contiene meno di 500 token, imposteremo 500 come lunghezza fissa per tutte le recensioni.
def padding_(sentences, seq_len):
features = np.zeros((len(sentences), seq_len),dtype=int)
for ii, review in enumerate(sentences):
if len(review) != 0:
features[ii, -len(review):] = np.array(review)[:seq_len]
return features
x_train_pad = padding_(x_train,500)
x_test_pad = padding_(x_test,500)
Successivamente, usiamo la classe DataLoader per creare il dataset finale per l’addestramento del modello.
# create Tensor datasets
train_data = TensorDataset(torch.from_numpy(x_train_pad), torch.from_numpy(y_train))
valid_data = TensorDataset(torch.from_numpy(x_test_pad), torch.from_numpy(y_test))
# dataloaders
batch_size = 50
# make sure to SHUFFLE your data
train_loader = DataLoader(train_data, shuffle=True, batch_size=batch_size)
valid_loader = DataLoader(valid_data, shuffle=True, batch_size=batch_size)
# obtain one batch of training data
dataiter = iter(train_loader)
sample_x, sample_y = next(dataiter)
print('Sample input size: ', sample_x.size()) # batch_size, seq_length
print('Sample input: \n', sample_x)
print('Sample output: \n', sample_y)
Output:

5. Definire il modello LSTM
Questa parte del codice definisce un modello di analisi del sentiment usando un’architettura di rete neurale ricorrente (RNN), in particolare una variante chiamata Long Short-Term Memory (LSTM) come menzionato sopra. La classe SentimentRNN è un modello PyTorch che inizia con uno strato di embedding, che trasforma gli indici delle parole in una rappresentazione densa che cattura il significato semantico dei termini. Segue poi uno strato LSTM che elabora la sequenza degli embedding delle parole.
Lo stato nascosto dell’LSTM viene passato attraverso uno strato di dropout (per regolarizzare il modello e prevenire l’overfitting) e uno strato completamente connesso, che mappa gli output dell’LSTM sulla previsione finale. La previsione viene poi passata attraverso una funzione di attivazione sigmoid, che converte i valori grezzi in probabilità. Il metodo forward definisce il passaggio in avanti dei dati attraverso la rete, mentre il metodo init_hidden inizializza a zero gli stati nascosti dello strato LSTM.
class SentimentRNN(nn.Module):
def __init__(self,no_layers,vocab_size,hidden_dim,embedding_dim,drop_prob=0.5):
super(SentimentRNN,self).__init__()
self.output_dim = output_dim
self.hidden_dim = hidden_dim
self.no_layers = no_layers
self.vocab_size = vocab_size
# embedding and LSTM layers
self.embedding = nn.Embedding(vocab_size, embedding_dim)
#lstm
self.lstm = nn.LSTM(input_size=embedding_dim,hidden_size=self.hidden_dim,
num_layers=no_layers, batch_first=True)
# dropout layer
self.dropout = nn.Dropout(0.3)
# linear and sigmoid layer
self.fc = nn.Linear(self.hidden_dim, output_dim)
self.sig = nn.Sigmoid()
def forward(self,x,hidden):
batch_size = x.size(0)
# embeddings and lstm_out
embeds = self.embedding(x) # shape: B x S x Feature since batch = True
#print(embeds.shape) #[50, 500, 1000]
lstm_out, hidden = self.lstm(embeds, hidden)
lstm_out = lstm_out.contiguous().view(-1, self.hidden_dim)
# dropout and fully connected layer
out = self.dropout(lstm_out)
out = self.fc(out)
# sigmoid function
sig_out = self.sig(out)
# reshape to be batch_size first
sig_out = sig_out.view(batch_size, -1)
sig_out = sig_out[:, -1] # get last batch of labels
# return last sigmoid output and hidden state
return sig_out, hidden
def init_hidden(self, batch_size):
''' Initializes hidden state '''
# Create two new tensors with sizes n_layers x batch_size x hidden_dim,
# initialized to zero, for hidden state and cell state of LSTM
h0 = torch.zeros((self.no_layers,batch_size,self.hidden_dim)).to(device)
c0 = torch.zeros((self.no_layers,batch_size,self.hidden_dim)).to(device)
hidden = (h0,c0)
return hidden
Ora inizializzeremo la classe SentimentRNN definita sopra con i parametri richiesti.
no_layers = 2
vocab_size = len(vocab) + 1 #extra 1 for padding
embedding_dim = 64
output_dim = 1
hidden_dim = 256
model = SentimentRNN(no_layers,vocab_size,hidden_dim,embedding_dim,drop_prob=0.5)
#moving to gpu
model.to(device)
print(model)

L’ultimo passaggio prima di iniziare l’addestramento è definire le funzioni di loss e di ottimizzazione. Questa parte si concentra sulla definizione della funzione di perdita, del metodo di ottimizzazione e di una funzione di utilità per il calcolo dell’accuratezza del nostro modello di analisi del sentiment.
La funzione di perdita usata è la Binary Cross-Entropy Loss (nn.BCELoss), comunemente utilizzata per compiti di classificazione binaria come questo. Il metodo di ottimizzazione è Adam (torch.optim.Adam), una scelta popolare per efficienza e basso consumo di memoria. Il learning rate per Adam è impostato a 0,001.
La funzione acc è un helper pensato per calcolare l’accuratezza delle previsioni del nostro modello. Arrotonda le probabilità previste all’intero più vicino (0 o 1), confronta queste previsioni con le etichette reali e calcola la percentuale di previsioni corrette.
# loss and optimization functions
lr=0.001
criterion = nn.BCELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=lr)
# function to predict accuracy
def acc(pred,label):
pred = torch.round(pred.squeeze())
return torch.sum(pred == label.squeeze()).item()
6. Avviare l’addestramento
Questa è la parte del codice in cui il modello di analisi del sentiment viene addestrato e validato. Ogni epoca (iterazione) comprende una fase di training e una di validazione. Durante il training, il modello impara regolando i propri parametri per minimizzare la loss.
Nella fase di validazione, le prestazioni del modello vengono valutate su un dataset separato per assicurarsi che stia imparando pattern generalizzabili e non solo memorizzando i dati di training.
Il ciclo di training inizia inizializzando gli stati nascosti dell’LSTM e impostando il modello in modalità training. Per ogni batch di dati, le previsioni del modello vengono confrontate con le etichette reali per calcolare la loss, che viene poi retropropagata per aggiornare i parametri del modello.
I gradienti vengono troncati a un valore massimo per evitare che diventino troppo grandi, un problema comune nell’addestramento di RNN e LSTM.
Nel ciclo di validazione, il modello viene impostato in modalità evaluation e le sue prestazioni vengono valutate usando i dati di validazione senza aggiornare alcun parametro. Per entrambe le fasi, il codice traccia loss e accuratezza per ogni epoca.
Se la loss di validazione migliora, i parametri del modello corrente vengono salvati, catturando il miglior modello trovato durante l’addestramento.
Infine, dopo ogni epoca, vengono stampate la loss media e l’accuratezza di quell’epoca, fornendo un quadro dei progressi di apprendimento del modello.
clip = 5
epochs = 5
valid_loss_min = np.Inf
# train for some number of epochs
epoch_tr_loss,epoch_vl_loss = [],[]
epoch_tr_acc,epoch_vl_acc = [],[]
for epoch in range(epochs):
train_losses = []
train_acc = 0.0
model.train()
# initialize hidden state
h = model.init_hidden(batch_size)
for inputs, labels in train_loader:
inputs, labels = inputs.to(device), labels.to(device)
# Creating new variables for the hidden state, otherwise
# we'd backprop through the entire training history
h = tuple([each.data for each in h])
model.zero_grad()
output,h = model(inputs,h)
# calculate the loss and perform backprop
loss = criterion(output.squeeze(), labels.float())
loss.backward()
train_losses.append(loss.item())
# calculating accuracy
accuracy = acc(output,labels)
train_acc += accuracy
#`clip_grad_norm` helps prevent the exploding gradient problem in RNNs / LSTMs.
nn.utils.clip_grad_norm_(model.parameters(), clip)
optimizer.step()
val_h = model.init_hidden(batch_size)
val_losses = []
val_acc = 0.0
model.eval()
for inputs, labels in valid_loader:
val_h = tuple([each.data for each in val_h])
inputs, labels = inputs.to(device), labels.to(device)
output, val_h = model(inputs, val_h)
val_loss = criterion(output.squeeze(), labels.float())
val_losses.append(val_loss.item())
accuracy = acc(output,labels)
val_acc += accuracy
epoch_train_loss = np.mean(train_losses)
epoch_val_loss = np.mean(val_losses)
epoch_train_acc = train_acc/len(train_loader.dataset)
epoch_val_acc = val_acc/len(valid_loader.dataset)
epoch_tr_loss.append(epoch_train_loss)
epoch_vl_loss.append(epoch_val_loss)
epoch_tr_acc.append(epoch_train_acc)
epoch_vl_acc.append(epoch_val_acc)
print(f'Epoch {epoch+1}')
print(f'train_loss : {epoch_train_loss} val_loss : {epoch_val_loss}')
print(f'train_accuracy : {epoch_train_acc*100} val_accuracy : {epoch_val_acc*100}')
if epoch_val_loss <= valid_loss_min:
torch.save(model.state_dict(), 'state_dict.pt')
print('Validation loss decreased ({:.6f} --> {:.6f}). Saving model ...'.format(valid_loss_min,epoch_val_loss))
valid_loss_min = epoch_val_loss
print(25*'==')
Output:

7. Valutazione del modello
Questa parte del codice genera due grafici per rappresentare visivamente l’andamento di accuratezza e loss di training e validazione durante l’addestramento del modello. Il primo sottografico mostra, con una linea, l’accuratezza di training e di validazione dopo ogni epoca. Questo grafico è utile per osservare quanto bene il modello sta imparando e generalizzando nel tempo.
Il secondo sottografico mostra, sempre con una linea, la loss di training e di validazione. Questo ci aiuta a capire se il nostro modello sta overfittando, underfittando o se è ben tarato.
fig = plt.figure(figsize = (20, 6))
plt.subplot(1, 2, 1)
plt.plot(epoch_tr_acc, label='Train Acc')
plt.plot(epoch_vl_acc, label='Validation Acc')
plt.title("Accuracy")
plt.legend()
plt.grid()
plt.subplot(1, 2, 2)
plt.plot(epoch_tr_loss, label='Train loss')
plt.plot(epoch_vl_loss, label='Validation loss')
plt.title("Loss")
plt.legend()
plt.grid()
plt.show()
Output:

8. Inferenza / Predizione
In questa parte, creiamo una funzione predict_text per prevedere il sentiment di un testo dato e mostriamo come usarla. La funzione predict_text prende in input una stringa di testo, la trasforma in una sequenza di indici di parole (secondo un vocabolario predefinito) e la prepara per l’input nel modello tramite padding e reshaping. La funzione poi inizializza gli stati nascosti dell’LSTM, fornisce l’input al modello e restituisce la probabilità di output del testo grezzo.
def predict_text(text):
word_seq = np.array([vocab[preprocess_string(word)] for word in text.split()
if preprocess_string(word) in vocab.keys()])
word_seq = np.expand_dims(word_seq,axis=0)
pad = torch.from_numpy(padding_(word_seq,500))
inputs = pad.to(device)
batch_size = 1
h = model.init_hidden(batch_size)
h = tuple([each.data for each in h])
output, h = model(inputs, h)
return(output.item())
index = 30
print(df['review'][index])
print('='*70)
print(f'Actual sentiment is : {df["sentiment"][index]}')
print('='*70)
pro = predict_text(df['review'][index])
status = "positive" if pro > 0.5 else "negative"
pro = (1 - pro) if status == "negative" else pro
print(f'Predicted sentiment is {status} with a probability of {pro}')
Output:

Questo notebook completo è stato sviluppato con DataLab ed è accessibile in questo workbook. Ricorda che l’esecuzione del codice potrebbe richiedere molto tempo se stai usando una CPU. L’uso di una GPU, invece, può ridurre sensibilmente i tempi di training.
Prossimi passi / Migliorare il modello
Migliorare un modello di NLP spesso richiede strategie multiple, adattate ai requisiti e ai vincoli specifici del compito. L’hyperparameter tuning è un approccio comune che prevede l’ottimizzazione di parametri come learning rate, batch size o il numero di layer in una rete neurale.
Questi iperparametri possono influenzare significativamente le prestazioni del modello e vengono tipicamente ottimizzati tramite tecniche come grid search o random search.
Il transfer learning, in particolare con modelli come BERT o GPT, ha mostrato un grande potenziale nel migliorare i compiti di NLP. Questi modelli sono pre-addestrati su grandi corpora di testo e poi fine-tuned su un compito specifico, permettendo di sfruttare la comprensione linguistica generale acquisita durante il pretraining. Questo approccio ha portato costantemente a risultati all’avanguardia in un’ampia gamma di compiti NLP, inclusa l’analisi del sentiment.
Applicazioni reali dell’NLP con PyTorch
L’uso di modelli di Natural Language Processing (NLP), in particolare quelli implementati con framework come PyTorch, ha visto un’adozione diffusa nelle applicazioni reali, rivoluzionando vari aspetti della nostra vita digitale.
I chatbot sono diventati una parte integrante delle piattaforme di assistenza clienti, sfruttando modelli NLP per comprendere e rispondere alle richieste degli utenti. Questi modelli possono processare input in linguaggio naturale, inferire l’intento e generare risposte simili a quelle umane, offrendo esperienze d’interazione fluide.
Nel campo dei sistemi di raccomandazione, i modelli NLP aiutano ad analizzare recensioni e commenti degli utenti per comprenderne le preferenze, migliorando così la personalizzazione delle raccomandazioni.
Anche gli strumenti di analisi del sentiment si basano fortemente sull’NLP. Questi strumenti possono esaminare post sui social media, recensioni dei clienti o qualunque dato testuale e inferire il sentiment sottostante. Le aziende usano spesso queste informazioni per ricerche di mercato o per valutare il sentiment pubblico sui propri prodotti o servizi, prendendo decisioni basate sui dati.
Scopri altri casi d’uso reali di Google BERT in questo tutorial di Natural Language Processing.
Conclusione
PyTorch offre una piattaforma potente e flessibile per costruire modelli di NLP. In questo tutorial abbiamo visto il processo di sviluppo di un modello di analisi del sentiment usando un’architettura LSTM, evidenziando passaggi chiave come il preprocessing del testo, la costruzione del modello, l’addestramento e la validazione, e infine le previsioni su dati mai visti.
Questo è solo la punta dell’iceberg di ciò che è possibile fare con NLP e PyTorch. L’NLP ha applicazioni vastissime, dai chatbot ai sistemi di raccomandazione, fino agli strumenti di analisi del sentiment e oltre.
La continua evoluzione del campo, soprattutto con l’avvento di modelli di transfer learning come BERT e GPT, apre possibilità ancora più interessanti per le esplorazioni future. Padroneggiare l’NLP con PyTorch è impegnativo ma gratificante, perché apre una nuova dimensione di comprensione e interazione con il mondo che ci circonda.
Se vuoi approfondire PyTorch, dai un’occhiata al nostro corso Deep Learning with PyTorch. Partirai da un’introduzione a PyTorch, esplorando la libreria e le sue applicazioni per reti neurali e deep learning. In seguito, affronterai le reti neurali artificiali e imparerai come addestrarle usando dati reali.


