{ "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": [ "មកមើលឧទាហរណ៍នៃរបៀបដែលយើងអាចតំណEncodeអត្ថបទពីឃ្លាដែលយើងមាន៖\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", "![Image showing an example RNN generation of the word 'HELLO'.](../../../../../translated_images/km/rnn-generate.56c54afb52f9781d.webp)\n", "\n", "អាស្រ័យលើសេណារីយ៉ូពិតប្រាកដ យើងអាចចង់បញ្ចូលអក្សរពិសេសមួយចំនួនដូចជា *end-of-sequence* ``។ ក្នុងករណីរបស់យើង គ្រាន់តែចង់បណ្តុះបណ្តាលបណ្តាញសម្រាប់ការបង្កើតអក្សរឥតដាក់ទីបញ្ចប់ ដូច្នេះយើងនឹងកំណត់ទំហំរបស់លំដាប់នីមួយៗឱ្យស្មើនឹង `nchars` tokens។ ដូច្នេះ ឧទាហរណ៍បណ្តុះបណ្តាលនីមួយៗ នឹងមាន `nchars` input និង `nchars` output (ដែលជាលំដាប់បញ្ចូលផ្តិតឆ្វេងមួយសញ្ញា)។ 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": [ "ឥឡូវនេះយើងចាំបាច់កំណត់បណ្តាញអ្នកបង្កើត។ វាអាចផ្អែកលើកោសិកា recurrent មួយណាក៏បានដែលយើងបានពិភាក្សាក្នុងឯកតាមុន (សាមញ្ញ LSTM ឬ GRU)។ ក្នុងឧទាហរណ៍របស់យើង យើងនឹងប្រើ LSTM។\n", "\n", "ដោយសារ​បណ្តាញ​ទទួល​បាន​តួអក្សរ​ជា​អិន​ប៊ុត ហើយ​ទំហំវចនានុក្រមតូច សមរម្យ អ្នកមិនចាំបាច់មានស្រទាប់បញ្ចូល embedding ទេ អ្នកអាចប្រើអ៊ីនប៊ុតកូដ​បែប one-hot ដោយផ្ទាល់ទៅកាន់កោសិកា LSTM។ ទោះយ៉ាងណា ដោយសារ​យើងផ្ញើលេខតួអក្សរជាអិនប៊ុត យើងចាំបាច់ត្រូវបំលែងវាជា one-hot encoding មុនពេលផ្ញើទៅ LSTM។ វាត្រូវបានអនុវត្ត ដោយហៅមុខងារ `one_hot` នៅពេលបញ្ជូន `forward`។ អ្នកអ៊ិនកូដធ្វើការបញ្ចេញនឹងជាស្រទាប់ linear មួយ ដែលបំលែងស្ថានភាពលាក់ឱ្យទៅជាបញ្ចេញ one-hot-encoded។\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 encoded, យើងប្រើ `argmax` ដើម្បីយកលេខសម្គាល់របស់តួអក្សរ `nc` ក្នុងវាកាណូរី ហើយប្រើ `itos` ដើម្បីស្វែងរកតួអក្សរពិតប្រាកដ ហើយបញ្ចូលវាល vào របស់បញ្ជីតួអក្សរ `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": [ "ឥឡូវនេះយើងចាប់ផ្តើមហ្វឹកហាត់! លំនាំហ្វឹកហាត់ស្ទ Loop training នៅជិតស្រដៀងគ្នា ដូចក្នុងឧទាហរណ៍ចាស់ៗទាំងអស់របស់យើង ប៉ុន្តែបម្លែងជំនាញត្រង់គឺយើងបោះពុម្ពអត្ថបទដែលបានបង្កើតឡើងជាគំរូរៀងរាល់ ១០០០ epoch។\n", "\n", "ត្រូវផ្ដល់ការយកចិត្តទុកដាក់ពិសេសចំពោះវិធីដែលយើងគណនា​ការ​បាត់បង់ (loss)។ យើងត្រូវគណនាបាត់បង់ដោយផ្តោតលើឆ្លើយតបដែលបាន encode ជាមួយ one-hot នៅ `out` ហើយអត្ថបទដែលបានរំពឹងទុកគឺ `text_out` ដែលជារបាយការណ៍ក្រុមលេខតួអក្សរ។ ហើយសំណាងល្អគឺមុខងារ `cross_entropy` រងចាំលទ្ធផលអន្តរកម្មមិនបានបញ្ច.Normalize (unnormalized) ជាអាគុយម៉ង់ទីមួយ ហើយលេខថ្នាក់ជាអាគុយម៉ង់ទីពីរ ដែលជាអ្វីដែលយើងមាន។ វាក៏ធ្វើការ averaging ដោយស្វ័យប្រវត្តិបន្ទាប់ពីទំហំ minibatch ផងដែរ។\n", "\n", "យើងក៏ដាក់ដែនកំណត់ការហ្វឹកហាត់ដោយ `samples_to_train` ខ្ទង់ ដើម្បីមិនអោយរង់ចាំយូរពេក។ យើងលើកទឹកចិត្តឲ្យអ្នកសាកល្បង និងព្យាយាមធ្វើហ្វឹកហាត់រយៈពេលវែងជាងនេះ ប្រហែល ជាច្រើន epoch (ក្នុងករណីនោះ អ្នកនឹងត្រូវបង្កើតខ្សែហ្វឹកហាត់បន្ថែមនៅជុំវិញកូដនេះ)។\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", "* **ការបង្កើត minibatch ល្អជាងមុន**។ វិធីដែលយើងបានរៀបចំទិន្នន័យសម្រាប់ការបណ្តុះបណ្តាលគឺបង្កើត minibatch មួយពីគំរូមួយ។ នេះមិនមែនជារឿងល្អទេ ព្រោះ minibatch ទាំងអស់មានទំហំខុសគ្នា ហើយអ្វីមួយខ្លះមិនអាចបង្កើតបានទេ ព្រោះអត្ថបទតូចជាង `nchars`។ ផងដែរ minibatch តូចៗ មិនបានផ្ទុក GPU យ៉ាងគ្រប់គ្រាន់ទេ។ វានឹងមានការយល់ឃើញល្អប្រសើរជាងមុនក្នុងការទទួលយកខ្នាតអត្ថបទធំមួយពីគំរូទាំងអស់ បន្ទាប់មកបង្កើតគូបញ្ចូល-ចេញទាំងអស់ ដម្រៀបតាមចៃដន្យ ហើយបង្កើត minibatch ទំហំស្មើគ្នា។\n", "* **LSTM ពហុស្រទាប់**។ វាមានហេតុផលក្នុងការព្យាយាមស្រទាប់ LSTM 2 ឬ 3។ ដូចដែលយើងបានរាយការណ៍នៅមេរៀនមុន ស្រទាប់ LSTM រៀងរាល់ស្រទាប់យកតំណំខ្ពស់ពីអត្ថបទ ហើយក្នុងករណីទូរស័ព្ទកម្រិតតួអក្សរ យើងអាចរំពឹងថា LSTM កម្រិតទាបមានទំនួលខុសត្រូវក្នុងការដកស្រង់ព្យញ្ជនៈ ហើយកម្រិតខ្ពស់ជាងគេគឺសម្រាប់ពាក្យ និងសមាសភាពពាក្យ។ វាអាចអនុវត្តបានយ៉ាងសាមញ្ញដោយផ្តល់ប៉ារ៉ាម៉ែត្រចំនួនស្រទាប់ទៅឱ្យអ្នកបង្កើត LSTM។\n", "* អ្នកក៏អាចចង់សាកល្បងជាមួយ **ឯកតា GRU** ហើយមើលថាណាមួយសមនឹងប្រសើរជាងទៀត ឬជាមួយ **ទំហំស្រទាប់បានលាក់ខុសគ្នា**។ ទំហំស្រទាប់បានលាក់ធំនឹងបណ្តាលឱ្យមានភាពច្រើនពេក (ឧ. បណ្តាញនឹងរៀនអត្ថបទយ៉ាងតឹងរឹង) ហើយទំហំតូចជាងមិនអាចផ្តល់លទ្ធផលល្អ។\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 យើងធ្វើការជ្រើសរើស multinomial យ៉ាងសមរម្យ ហើយពេលសីតុណ្ហភាពឡើងទៅអនន្តភាព - ប្រprobabilityទាំងអស់ក្លាយជាស្មើគ្នា ហើយយើងជ្រើសរើសតួអក្សរបន្ទាប់ដោយចៃដន្យ។ នៅក្នុងឧទាហរណ៍ខាងក្រោម យើងអាចចាប់អារម្មណ៍បានថាអត្ថបទក្លាយទៅជាឥតមានន័យពេលយើងបង្កើនសីតុណ្ហភាពច្រើនពេក ហើយវាបង្ហាញដូចជា អត្ថបទដែលផលិតឡើងយ៉ាងពិបាកដែលមានលំនាំពិចារណា \"cycled\" ពេលវាឈានកាន់ក្បាលទៅ 0។\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n\n\n**ការបដិសេធ**៖ \nឯកសារនេះត្រូវបានបកប្រែដោយប្រើសេវាបកប្រែ AI [Co-op Translator](https://github.com/Azure/co-op-translator)។ ខណៈដែលយើងខិតខំរកភាពត្រឹមត្រូវ សូមជ្រាបថាការបកប្រែដោយស្វ័យប្រវត្តិអាចមានកំហុស ឬការខុសឆ្គង។ ឯកសារដើមនៅក្នុងភាសារដើមគួរត្រូវបានគេយកជា ប្រភពដែលមានសុពលភាព។ សម្រាប់ព័ត៌មានសំខាន់ សូមណែនាំឲ្យប្រើការបកប្រែដោយមនុស្សដែលជាអ្នកជំនាញ។ យើងមិនទទួលខុសត្រូវចំពោះការយល់ច្រឡំ ឬការបកប្រែខុសៗណាមួយដែលកើតមានពីការប្រើប្រាស់ការបកប្រែនេះដែរ។\n\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" } }, "nbformat": 4, "nbformat_minor": 4 }