AI-For-Beginners/translations/el/lessons/5-NLP/17-GenerativeNetworks/GenerativePyTorch.ipynb

414 lines
29 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Γενετικά δίκτυα\n",
"\n",
"Τα Επαναλαμβανόμενα Νευρωνικά Δίκτυα (RNNs) και οι παραλλαγές τους με πύλες, όπως τα Κύτταρα Μνήμης Μακράς και Βραχείας Διάρκειας (LSTMs) και οι Μονάδες Επαναλαμβανόμενης Πύλης (GRUs), παρέχουν έναν μηχανισμό για τη μοντελοποίηση γλώσσας, δηλαδή μπορούν να μάθουν τη σειρά των λέξεων και να δώσουν προβλέψεις για την επόμενη λέξη σε μια ακολουθία. Αυτό μας επιτρέπει να χρησιμοποιούμε τα RNNs για **γενετικές εργασίες**, όπως η απλή δημιουργία κειμένου, η μηχανική μετάφραση και ακόμη και η περιγραφή εικόνων.\n",
"\n",
"Στην αρχιτεκτονική RNN που συζητήσαμε στην προηγούμενη ενότητα, κάθε μονάδα RNN παρήγαγε την επόμενη κρυφή κατάσταση ως έξοδο. Ωστόσο, μπορούμε επίσης να προσθέσουμε μια άλλη έξοδο σε κάθε επαναλαμβανόμενη μονάδα, η οποία θα μας επιτρέπει να παράγουμε μια **ακολουθία** (που είναι ίση σε μήκος με την αρχική ακολουθία). Επιπλέον, μπορούμε να χρησιμοποιήσουμε μονάδες RNN που δεν δέχονται είσοδο σε κάθε βήμα, αλλά απλώς λαμβάνουν κάποιο αρχικό διάνυσμα κατάστασης και στη συνέχεια παράγουν μια ακολουθία εξόδων.\n",
"\n",
"Σε αυτό το σημειωματάριο, θα επικεντρωθούμε σε απλά γενετικά μοντέλα που μας βοηθούν να δημιουργούμε κείμενο. Για απλότητα, ας κατασκευάσουμε ένα **δίκτυο σε επίπεδο χαρακτήρων**, το οποίο δημιουργεί κείμενο γράμμα προς γράμμα. Κατά τη διάρκεια της εκπαίδευσης, πρέπει να πάρουμε κάποιο σώμα κειμένου και να το χωρίσουμε σε ακολουθίες γραμμάτων.\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading dataset...\n",
"Building vocab...\n"
]
}
],
"source": [
"import torch\n",
"import torchtext\n",
"import numpy as np\n",
"from torchnlp import *\n",
"train_dataset,test_dataset,classes,vocab = load_dataset()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Δημιουργία λεξιλογίου χαρακτήρων\n",
"\n",
"Για να δημιουργήσουμε ένα γενετικό δίκτυο σε επίπεδο χαρακτήρων, πρέπει να διαχωρίσουμε το κείμενο σε μεμονωμένους χαρακτήρες αντί για λέξεις. Αυτό μπορεί να γίνει ορίζοντας έναν διαφορετικό tokenizer:\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Vocabulary size = 82\n",
"Encoding of 'a' is 1\n",
"Character with code 13 is c\n"
]
}
],
"source": [
"def char_tokenizer(words):\n",
" return list(words) #[word for word in words]\n",
"\n",
"counter = collections.Counter()\n",
"for (label, line) in train_dataset:\n",
" counter.update(char_tokenizer(line))\n",
"vocab = torchtext.vocab.vocab(counter)\n",
"\n",
"vocab_size = len(vocab)\n",
"print(f\"Vocabulary size = {vocab_size}\")\n",
"print(f\"Encoding of 'a' is {vocab.get_stoi()['a']}\")\n",
"print(f\"Character with code 13 is {vocab.get_itos()[13]}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ας δούμε το παράδειγμα του πώς μπορούμε να κωδικοποιήσουμε το κείμενο από το σύνολο δεδομένων μας:\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([ 0, 1, 2, 2, 3, 4, 5, 6, 3, 7, 8, 1, 9, 10, 3, 11, 2, 1,\n",
" 12, 3, 7, 1, 13, 14, 3, 15, 16, 5, 17, 3, 5, 18, 8, 3, 7, 2,\n",
" 1, 13, 14, 3, 19, 20, 8, 21, 5, 8, 9, 10, 22, 3, 20, 8, 21, 5,\n",
" 8, 9, 10, 3, 23, 3, 4, 18, 17, 9, 5, 23, 10, 8, 2, 2, 8, 9,\n",
" 10, 24, 3, 0, 1, 2, 2, 3, 4, 5, 9, 8, 8, 5, 25, 10, 3, 26,\n",
" 12, 27, 16, 26, 2, 27, 16, 28, 29, 30, 1, 16, 26, 3, 17, 31, 3, 21,\n",
" 2, 5, 9, 1, 23, 13, 32, 16, 27, 13, 10, 24, 3, 1, 9, 8, 3, 10,\n",
" 8, 8, 27, 16, 28, 3, 28, 9, 8, 8, 16, 3, 1, 28, 1, 27, 16, 6])"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def enc(x):\n",
" return torch.LongTensor(encode(x,voc=vocab,tokenizer=char_tokenizer))\n",
"\n",
"enc(train_dataset[0][1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Εκπαίδευση ενός γενετικού RNN\n",
"\n",
"Ο τρόπος με τον οποίο θα εκπαιδεύσουμε το RNN για να δημιουργεί κείμενο είναι ο εξής. Σε κάθε βήμα, θα παίρνουμε μια ακολουθία χαρακτήρων μήκους `nchars` και θα ζητάμε από το δίκτυο να παράγει τον επόμενο χαρακτήρα εξόδου για κάθε χαρακτήρα εισόδου:\n",
"\n",
"![Εικόνα που δείχνει ένα παράδειγμα δημιουργίας της λέξης 'HELLO' από RNN.](../../../../../translated_images/el/rnn-generate.56c54afb52f9781d.webp)\n",
"\n",
"Ανάλογα με το συγκεκριμένο σενάριο, μπορεί να θέλουμε να συμπεριλάβουμε και ειδικούς χαρακτήρες, όπως το *τέλος ακολουθίας* `<eos>`. Στην περίπτωσή μας, θέλουμε απλώς να εκπαιδεύσουμε το δίκτυο για ατελείωτη δημιουργία κειμένου, επομένως θα ορίσουμε το μέγεθος κάθε ακολουθίας να είναι ίσο με `nchars` tokens. Συνεπώς, κάθε παράδειγμα εκπαίδευσης θα αποτελείται από `nchars` εισόδους και `nchars` εξόδους (που είναι η ακολουθία εισόδου μετατοπισμένη κατά ένα σύμβολο προς τα αριστερά). Το minibatch θα αποτελείται από αρκετές τέτοιες ακολουθίες.\n",
"\n",
"Ο τρόπος με τον οποίο θα δημιουργούμε τα minibatches είναι να παίρνουμε κάθε κείμενο ειδήσεων μήκους `l` και να δημιουργούμε όλους τους δυνατούς συνδυασμούς εισόδου-εξόδου από αυτό (θα υπάρχουν `l-nchars` τέτοιοι συνδυασμοί). Αυτοί θα σχηματίζουν ένα minibatch, και το μέγεθος των minibatches θα είναι διαφορετικό σε κάθε βήμα εκπαίδευσης.\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(tensor([[ 0, 1, 2, ..., 28, 29, 30],\n",
" [ 1, 2, 2, ..., 29, 30, 1],\n",
" [ 2, 2, 3, ..., 30, 1, 16],\n",
" ...,\n",
" [20, 8, 21, ..., 1, 28, 1],\n",
" [ 8, 21, 5, ..., 28, 1, 27],\n",
" [21, 5, 8, ..., 1, 27, 16]]),\n",
" tensor([[ 1, 2, 2, ..., 29, 30, 1],\n",
" [ 2, 2, 3, ..., 30, 1, 16],\n",
" [ 2, 3, 4, ..., 1, 16, 26],\n",
" ...,\n",
" [ 8, 21, 5, ..., 28, 1, 27],\n",
" [21, 5, 8, ..., 1, 27, 16],\n",
" [ 5, 8, 9, ..., 27, 16, 6]]))"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"nchars = 100\n",
"\n",
"def get_batch(s,nchars=nchars):\n",
" ins = torch.zeros(len(s)-nchars,nchars,dtype=torch.long,device=device)\n",
" outs = torch.zeros(len(s)-nchars,nchars,dtype=torch.long,device=device)\n",
" for i in range(len(s)-nchars):\n",
" ins[i] = enc(s[i:i+nchars])\n",
" outs[i] = enc(s[i+1:i+nchars+1])\n",
" return ins,outs\n",
"\n",
"get_batch(train_dataset[0][1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Τώρα ας ορίσουμε το δίκτυο του generator. Μπορεί να βασίζεται σε οποιοδήποτε επαναλαμβανόμενο κύτταρο που συζητήσαμε στην προηγούμενη ενότητα (απλό, LSTM ή GRU). Στο παράδειγμά μας θα χρησιμοποιήσουμε LSTM.\n",
"\n",
"Επειδή το δίκτυο λαμβάνει χαρακτήρες ως είσοδο και το μέγεθος του λεξιλογίου είναι αρκετά μικρό, δεν χρειαζόμαστε επίπεδο ενσωμάτωσης (embedding layer), καθώς η είσοδος σε μορφή one-hot μπορεί να περάσει απευθείας στο κύτταρο LSTM. Ωστόσο, επειδή περνάμε αριθμούς χαρακτήρων ως είσοδο, πρέπει να τους μετατρέψουμε σε μορφή one-hot πριν τους περάσουμε στο LSTM. Αυτό γίνεται καλώντας τη συνάρτηση `one_hot` κατά τη διάρκεια της μεθόδου `forward`. Ο κωδικοποιητής εξόδου θα είναι ένα γραμμικό επίπεδο που θα μετατρέπει την κρυφή κατάσταση σε έξοδο σε μορφή one-hot.\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"class LSTMGenerator(torch.nn.Module):\n",
" def __init__(self, vocab_size, hidden_dim):\n",
" super().__init__()\n",
" self.rnn = torch.nn.LSTM(vocab_size,hidden_dim,batch_first=True)\n",
" self.fc = torch.nn.Linear(hidden_dim, vocab_size)\n",
"\n",
" def forward(self, x, s=None):\n",
" x = torch.nn.functional.one_hot(x,vocab_size).to(torch.float32)\n",
" x,s = self.rnn(x,s)\n",
" return self.fc(x),s"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Κατά τη διάρκεια της εκπαίδευσης, θέλουμε να μπορούμε να δειγματοληπτούμε παραγόμενο κείμενο. Για να το κάνουμε αυτό, θα ορίσουμε τη συνάρτηση `generate`, η οποία θα παράγει μια συμβολοσειρά εξόδου μήκους `size`, ξεκινώντας από την αρχική συμβολοσειρά `start`.\n",
"\n",
"Ο τρόπος που λειτουργεί είναι ο εξής. Πρώτα, θα περάσουμε ολόκληρη την αρχική συμβολοσειρά μέσω του δικτύου και θα πάρουμε την κατάσταση εξόδου `s` και τον επόμενο προβλεπόμενο χαρακτήρα `out`. Επειδή το `out` είναι κωδικοποιημένο σε μορφή one-hot, παίρνουμε το `argmax` για να βρούμε τον δείκτη του χαρακτήρα `nc` στο λεξιλόγιο και χρησιμοποιούμε το `itos` για να εντοπίσουμε τον πραγματικό χαρακτήρα και να τον προσθέσουμε στη λίστα χαρακτήρων `chars`. Αυτή η διαδικασία παραγωγής ενός χαρακτήρα επαναλαμβάνεται `size` φορές για να παραχθεί ο απαιτούμενος αριθμός χαρακτήρων.\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"def generate(net,size=100,start='today '):\n",
" chars = list(start)\n",
" out, s = net(enc(chars).view(1,-1).to(device))\n",
" for i in range(size):\n",
" nc = torch.argmax(out[0][-1])\n",
" chars.append(vocab.get_itos()[nc])\n",
" out, s = net(nc.view(1,-1),s)\n",
" return ''.join(chars)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ας ξεκινήσουμε την εκπαίδευση! Ο βρόχος εκπαίδευσης είναι σχεδόν ίδιος με όλα τα προηγούμενα παραδείγματα, αλλά αντί για ακρίβεια, εκτυπώνουμε δείγματα παραγόμενου κειμένου κάθε 1000 εποχές.\n",
"\n",
"Ιδιαίτερη προσοχή πρέπει να δοθεί στον τρόπο που υπολογίζουμε την απώλεια. Πρέπει να υπολογίσουμε την απώλεια με δεδομένη την έξοδο που είναι κωδικοποιημένη σε one-hot, `out`, και το αναμενόμενο κείμενο `text_out`, που είναι η λίστα με τους δείκτες χαρακτήρων. Ευτυχώς, η συνάρτηση `cross_entropy` αναμένει ως πρώτο όρισμα την μη κανονικοποιημένη έξοδο του δικτύου και ως δεύτερο τον αριθμό της κλάσης, που είναι ακριβώς αυτό που έχουμε. Επιπλέον, εκτελεί αυτόματα μέσο όρο με βάση το μέγεθος του minibatch.\n",
"\n",
"Περιορίζουμε επίσης την εκπαίδευση σε `samples_to_train` δείγματα, ώστε να μην περιμένουμε υπερβολικά πολύ. Σας ενθαρρύνουμε να πειραματιστείτε και να δοκιμάσετε μεγαλύτερη διάρκεια εκπαίδευσης, πιθανώς για αρκετές εποχές (σε αυτή την περίπτωση θα χρειαστεί να δημιουργήσετε έναν επιπλέον βρόχο γύρω από αυτόν τον κώδικα).\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Current loss = 4.398899078369141\n",
"today sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr s\n",
"Current loss = 2.161320447921753\n",
"today and to the tor to to the tor to to the tor to to the tor to to the tor to to the tor to to the tor t\n",
"Current loss = 1.6722588539123535\n",
"today and the court to the could to the could to the could to the could to the could to the could to the c\n",
"Current loss = 2.423795223236084\n",
"today and a second to the conternation of the conternation of the conternation of the conternation of the \n",
"Current loss = 1.702607274055481\n",
"today and the company to the company to the company to the company to the company to the company to the co\n",
"Current loss = 1.692358136177063\n",
"today and the company to the company to the company to the company to the company to the company to the co\n",
"Current loss = 1.9722288846969604\n",
"today and the control the control the control the control the control the control the control the control \n",
"Current loss = 1.8705692291259766\n",
"today and the second to the second to the second to the second to the second to the second to the second t\n",
"Current loss = 1.7626899480819702\n",
"today and a security and a security and a security and a security and a security and a security and a secu\n",
"Current loss = 1.5574463605880737\n",
"today and the company and the company and the company and the company and the company and the company and \n",
"Current loss = 1.5620026588439941\n",
"today and the be that the be the be that the be the be that the be the be that the be the be that the be t\n"
]
}
],
"source": [
"net = LSTMGenerator(vocab_size,64).to(device)\n",
"\n",
"samples_to_train = 10000\n",
"optimizer = torch.optim.Adam(net.parameters(),0.01)\n",
"loss_fn = torch.nn.CrossEntropyLoss()\n",
"net.train()\n",
"for i,x in enumerate(train_dataset):\n",
" # x[0] is class label, x[1] is text\n",
" if len(x[1])-nchars<10:\n",
" continue\n",
" samples_to_train-=1\n",
" if not samples_to_train: break\n",
" text_in, text_out = get_batch(x[1])\n",
" optimizer.zero_grad()\n",
" out,s = net(text_in)\n",
" loss = torch.nn.functional.cross_entropy(out.view(-1,vocab_size),text_out.flatten()) #cross_entropy(out,labels)\n",
" loss.backward()\n",
" optimizer.step()\n",
" if i%1000==0:\n",
" print(f\"Current loss = {loss.item()}\")\n",
" print(generate(net))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Αυτό το παράδειγμα ήδη παράγει αρκετά καλό κείμενο, αλλά μπορεί να βελτιωθεί περαιτέρω με διάφορους τρόπους:\n",
"\n",
"* **Καλύτερη δημιουργία minibatch**. Ο τρόπος που προετοιμάσαμε τα δεδομένα για εκπαίδευση ήταν να δημιουργούμε ένα minibatch από ένα δείγμα. Αυτό δεν είναι ιδανικό, επειδή τα minibatches έχουν διαφορετικά μεγέθη, και κάποια από αυτά δεν μπορούν καν να δημιουργηθούν, επειδή το κείμενο είναι μικρότερο από `nchars`. Επίσης, τα μικρά minibatches δεν αξιοποιούν επαρκώς την GPU. Θα ήταν πιο σοφό να πάρουμε ένα μεγάλο κομμάτι κειμένου από όλα τα δείγματα, να δημιουργήσουμε όλα τα ζεύγη εισόδου-εξόδου, να τα ανακατέψουμε και να δημιουργήσουμε minibatches ίσου μεγέθους.\n",
"\n",
"* **Πολυεπίπεδο LSTM**. Έχει νόημα να δοκιμάσουμε 2 ή 3 επίπεδα κυττάρων LSTM. Όπως αναφέραμε στην προηγούμενη ενότητα, κάθε επίπεδο του LSTM εξάγει συγκεκριμένα μοτίβα από το κείμενο, και στην περίπτωση ενός γεννήτορα σε επίπεδο χαρακτήρων μπορούμε να περιμένουμε ότι τα χαμηλότερα επίπεδα LSTM θα είναι υπεύθυνα για την εξαγωγή συλλαβών, ενώ τα υψηλότερα επίπεδα - για λέξεις και συνδυασμούς λέξεων. Αυτό μπορεί να υλοποιηθεί απλά περνώντας την παράμετρο αριθμού επιπέδων στον constructor του LSTM.\n",
"\n",
"* Μπορεί επίσης να θέλετε να πειραματιστείτε με **μονάδες GRU** και να δείτε ποιες αποδίδουν καλύτερα, καθώς και με **διαφορετικά μεγέθη κρυφών επιπέδων**. Πολύ μεγάλο κρυφό επίπεδο μπορεί να οδηγήσει σε overfitting (π.χ. το δίκτυο θα μάθει το ακριβές κείμενο), ενώ μικρότερο μέγεθος μπορεί να μην παράγει καλό αποτέλεσμα.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Γενιά μαλακού κειμένου και θερμοκρασία\n",
"\n",
"Στον προηγούμενο ορισμό της `generate`, πάντα επιλέγαμε τον χαρακτήρα με τη μεγαλύτερη πιθανότητα ως τον επόμενο χαρακτήρα στο παραγόμενο κείμενο. Αυτό είχε ως αποτέλεσμα το κείμενο συχνά να \"κυκλώνει\" ανάμεσα στις ίδιες ακολουθίες χαρακτήρων ξανά και ξανά, όπως σε αυτό το παράδειγμα:\n",
"```\n",
"today of the second the company and a second the company ...\n",
"```\n",
"\n",
"Ωστόσο, αν κοιτάξουμε την κατανομή πιθανοτήτων για τον επόμενο χαρακτήρα, μπορεί να διαπιστώσουμε ότι η διαφορά ανάμεσα σε μερικές από τις υψηλότερες πιθανότητες δεν είναι μεγάλη, π.χ. ένας χαρακτήρας μπορεί να έχει πιθανότητα 0.2, ενώ ένας άλλος 0.19, κ.λπ. Για παράδειγμα, όταν ψάχνουμε τον επόμενο χαρακτήρα στη σειρά '*play*', ο επόμενος χαρακτήρας μπορεί εξίσου να είναι είτε κενό, είτε **e** (όπως στη λέξη *player*).\n",
"\n",
"Αυτό μας οδηγεί στο συμπέρασμα ότι δεν είναι πάντα \"δίκαιο\" να επιλέγουμε τον χαρακτήρα με τη μεγαλύτερη πιθανότητα, γιατί η επιλογή του δεύτερου μεγαλύτερου μπορεί επίσης να οδηγήσει σε ουσιαστικό κείμενο. Είναι πιο σοφό να **δειγματοληπτούμε** χαρακτήρες από την κατανομή πιθανοτήτων που δίνεται από την έξοδο του δικτύου.\n",
"\n",
"Αυτή η δειγματοληψία μπορεί να γίνει χρησιμοποιώντας τη συνάρτηση `multinomial`, η οποία υλοποιεί τη λεγόμενη **πολυωνυμική κατανομή**. Μια συνάρτηση που υλοποιεί αυτή τη **μαλακή** γενιά κειμένου ορίζεται παρακάτω:\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--- Temperature = 0.3\n",
"Today and a company and complete an all the land the restrational the as a security and has provers the pay to and a report and the computer in the stand has filities and working the law the stations for a company and with the company and the final the first company and refight of the state and and workin\n",
"\n",
"--- Temperature = 0.8\n",
"Today he oniis its first to Aus bomblaties the marmation a to manan boogot that pirate assaid a relaid their that goverfin the the Cappets Ecrotional Assonia Cition targets it annight the w scyments Blamity #39;s TVeer Diercheg Reserals fran envyuil that of ster said access what succers of Dour-provelith\n",
"\n",
"--- Temperature = 1.0\n",
"Today holy they a 11 will meda a toket subsuaties, engins for Chanos, they's has stainger past to opening orital his thempting new Nattona was al innerforder advan-than #36;s night year his religuled talitatian what the but with Wednesday to Justment will wemen of Mark CCC Camp as Timed Nae wome a leaders\n",
"\n",
"--- Temperature = 1.3\n",
"Today gpone 2.5 fech atcusion poor cocles toparsdorM.cht Line Pamage put 43 his calt lowed to the book, that has authh-the silia rruch ailing to'ory andhes beutirsimi- Aefffive heading offil an auf eacklets is charged evis, Gunymy oy) Mony has it after-sloythyor loveId out filme, the Natabl -Najuntaxiggs \n",
"\n",
"--- Temperature = 1.8\n",
"Today plary, P.slan chly\\401 mardregationly #39;t 8.1Mide) closes ,filtcon alfly playin roven!\\grea.-QFBEP: Iss onfarchQ/itilia CCf Zivesigntwasta orce.-Peul-aw.uicrin of fuglinfsut aftaningwo, MIEX awayew Aice Woiduar Corvagiugge oppo esig ThusBratourid canthly-RyI.co lagitems\\eexciaishes.conBabntusmor I\n",
"\n"
]
}
],
"source": [
"def generate_soft(net,size=100,start='today ',temperature=1.0):\n",
" chars = list(start)\n",
" out, s = net(enc(chars).view(1,-1).to(device))\n",
" for i in range(size):\n",
" #nc = torch.argmax(out[0][-1])\n",
" out_dist = out[0][-1].div(temperature).exp()\n",
" nc = torch.multinomial(out_dist,1)[0]\n",
" chars.append(vocab.get_itos()[nc])\n",
" out, s = net(nc.view(1,-1),s)\n",
" return ''.join(chars)\n",
" \n",
"for i in [0.3,0.8,1.0,1.3,1.8]:\n",
" print(f\"--- Temperature = {i}\\n{generate_soft(net,size=300,start='Today ',temperature=i)}\\n\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Έχουμε εισαγάγει μία ακόμη παράμετρο που ονομάζεται **θερμοκρασία**, η οποία χρησιμοποιείται για να υποδείξει πόσο αυστηρά πρέπει να ακολουθούμε την υψηλότερη πιθανότητα. Αν η θερμοκρασία είναι 1.0, κάνουμε δίκαιη δειγματοληψία πολυωνύμου, και όταν η θερμοκρασία τείνει στο άπειρο - όλες οι πιθανότητες γίνονται ίσες, και επιλέγουμε τυχαία τον επόμενο χαρακτήρα. Στο παρακάτω παράδειγμα μπορούμε να παρατηρήσουμε ότι το κείμενο γίνεται χωρίς νόημα όταν αυξάνουμε υπερβολικά τη θερμοκρασία, και μοιάζει με \"κυκλικό\" κείμενο που παράγεται δύσκολα όταν πλησιάζει το 0.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Αποποίηση Ευθύνης**: \nΑυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.\n"
]
}
],
"metadata": {
"interpreter": {
"hash": "16af2a8bbb083ea23e5e41c7f5787656b2ce26968575d8763f2c4b17f9cd711f"
},
"kernelspec": {
"display_name": "Python 3.8.12 ('py38')",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.12"
},
"coopTranslator": {
"original_hash": "7673cd150d96c74c6d6011460094efb4",
"translation_date": "2025-08-29T10:39:34+00:00",
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativePyTorch.ipynb",
"language_code": "el"
}
},
"nbformat": 4,
"nbformat_minor": 4
}