{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# เครือข่ายการสร้างสรรค์\n", "\n", "Recurrent Neural Networks (RNNs) และรูปแบบเซลล์ที่มีการควบคุม เช่น Long Short Term Memory Cells (LSTMs) และ Gated Recurrent Units (GRUs) ได้มอบกลไกสำหรับการสร้างแบบจำลองภาษา กล่าวคือ พวกมันสามารถเรียนรู้การเรียงลำดับคำและให้การคาดการณ์คำถัดไปในลำดับได้ สิ่งนี้ทำให้เราสามารถใช้ RNNs สำหรับ **งานสร้างสรรค์** เช่น การสร้างข้อความทั่วไป การแปลภาษา และแม้กระทั่งการสร้างคำบรรยายภาพ\n", "\n", "ในสถาปัตยกรรม RNN ที่เราได้พูดถึงในหน่วยก่อนหน้า แต่ละหน่วย 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", "ในการสร้างเครือข่ายแบบสร้างระดับตัวอักษร เราจำเป็นต้องแยกข้อความออกเป็นตัวอักษรแต่ละตัวแทนที่จะเป็นคำ วิธีนี้สามารถทำได้โดยการกำหนดตัวแบ่งคำแบบใหม่:\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/th/rnn-generate.56c54afb52f9781d.webp)\n", "\n", "ขึ้นอยู่กับสถานการณ์จริง เราอาจต้องการเพิ่มตัวอักษรพิเศษบางตัว เช่น *end-of-sequence* `` ในกรณีของเรา เราต้องการฝึกเครือข่ายเพื่อสร้างข้อความแบบไม่มีที่สิ้นสุด ดังนั้นเราจะกำหนดขนาดของแต่ละลำดับให้เท่ากับโทเค็น `nchars` ดังนั้น ตัวอย่างการฝึกแต่ละตัวจะประกอบด้วยอินพุต `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 กัน เครือข่ายนี้สามารถอ้างอิงจาก recurrent cell ใด ๆ ที่เราได้พูดถึงในหน่วยก่อนหน้านี้ (เช่น simple, LSTM หรือ GRU) ในตัวอย่างนี้เราจะใช้ LSTM\n", "\n", "เนื่องจากเครือข่ายนี้รับตัวอักษรเป็นอินพุต และขนาดของคำศัพท์ค่อนข้างเล็ก เราจึงไม่จำเป็นต้องมี embedding layer อินพุตที่ถูกเข้ารหัสแบบ one-hot สามารถส่งตรงไปยัง LSTM cell ได้เลย อย่างไรก็ตาม เนื่องจากเราส่งหมายเลขของตัวอักษรเป็นอินพุต เราจำเป็นต้องเข้ารหัสแบบ one-hot ก่อนที่จะส่งไปยัง LSTM ซึ่งสามารถทำได้โดยการเรียกใช้ฟังก์ชัน `one_hot` ในระหว่างการทำ `forward` pass ส่วน output encoder จะเป็น linear layer ที่จะแปลง hidden state ให้กลายเป็นผลลัพธ์ที่ถูกเข้ารหัสแบบ 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", "สิ่งที่ต้องให้ความสนใจเป็นพิเศษคือวิธีการคำนวณค่า loss เราจำเป็นต้องคำนวณค่า loss โดยใช้ผลลัพธ์ที่ถูกเข้ารหัสแบบ 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 หนึ่งชุดจากตัวอย่างหนึ่งชุด ซึ่งไม่ใช่วิธีที่เหมาะสมที่สุด เนื่องจาก minibatch มีขนาดแตกต่างกัน และบางชุดไม่สามารถสร้างได้เพราะข้อความมีขนาดเล็กกว่า `nchars` นอกจากนี้ minibatch ขนาดเล็กยังไม่สามารถใช้ประโยชน์จาก GPU ได้อย่างเต็มที่ จะดีกว่าหากรวบรวมข้อความขนาดใหญ่จากตัวอย่างทั้งหมด สร้างคู่ข้อมูล input-output ทั้งหมด สุ่มข้อมูล และสร้าง minibatch ที่มีขนาดเท่ากัน\n", "\n", "* **LSTM หลายชั้น** การลองใช้ LSTM cells 2 หรือ 3 ชั้นเป็นสิ่งที่น่าสนใจ ดังที่เราได้กล่าวถึงในหน่วยก่อนหน้า แต่ละชั้นของ LSTM จะดึงรูปแบบบางอย่างจากข้อความออกมา และในกรณีของตัวสร้างข้อความระดับตัวอักษร เราสามารถคาดหวังให้ LSTM ชั้นล่างสุดรับผิดชอบการดึงรูปแบบของพยางค์ และชั้นที่สูงขึ้นรับผิดชอบคำและการรวมคำ สิ่งนี้สามารถทำได้ง่าย ๆ โดยการส่งพารามิเตอร์จำนวนชั้นไปยังตัวสร้าง LSTM\n", "\n", "* คุณอาจต้องการทดลองใช้ **GRU units** และดูว่าแบบไหนทำงานได้ดีกว่า รวมถึง **ขนาดของ hidden layer ที่แตกต่างกัน** ขนาด hidden layer ที่ใหญ่เกินไปอาจทำให้เกิด 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": [ "เราได้แนะนำพารามิเตอร์อีกตัวหนึ่งที่เรียกว่า **temperature** ซึ่งใช้เพื่อบ่งบอกว่าเราควรยึดติดกับความน่าจะเป็นสูงสุดมากแค่ไหน หาก temperature เท่ากับ 1.0 เราจะทำการสุ่มแบบ multinomial อย่างยุติธรรม และเมื่อ temperature เพิ่มขึ้นจนถึงค่าอนันต์ ความน่าจะเป็นทั้งหมดจะเท่ากัน และเราจะสุ่มเลือกตัวอักษรถัดไปแบบสุ่ม ในตัวอย่างด้านล่าง เราสามารถสังเกตได้ว่าข้อความจะไม่มีความหมายเมื่อเราเพิ่มค่า temperature มากเกินไป และจะคล้ายกับข้อความที่ถูกสร้างขึ้นแบบ \"วนซ้ำ\" เมื่อค่า temperature เข้าใกล้ 0\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n---\n\n**ข้อจำกัดความรับผิดชอบ**: \nเอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI [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:40:33+00:00", "source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativePyTorch.ipynb", "language_code": "th" } }, "nbformat": 4, "nbformat_minor": 4 }