φυβλαςのβλογ
บล็อกของ phyblas



pytorch เบื้องต้น บทที่ ๑๓: การแยกข้อมูลฝึกและข้อมูลตรวจสอบ
เขียนเมื่อ 2018/09/19 09:05
>> ต่อจาก บทที่ ๑๒



ในบทที่ ๑๑ ได้อธิบายการนำรูปมาใช้เป็นข้อมูล และบทที่ ๑๒ ได้แสดงตัวอย่างการนำมาใช้ในโครงข่ายประสาทเทียมแบบคอนโวลูชัน (CNN)

แต่ว่าในนั้นใช้ข้อมูลตัวอย่างของ MNIST ซึ่งถูกเตรียมไว้โดยแยกชุดข้อมูลฝึกกับข้อมูลตรวจสอบไว้คนละชุดกันอยู่แล้ว จึงนำมาใช้ได้เลย

แต่ถ้าหากเราต้องการเตรียมภาพไว้ใช้เอง โดยไม่ได้แยกข้อมูลออกเป็นชุดข้อมูลฝึกกับข้อมูลตรวจสอบไว้ หรือต้องการสุ่มสับเปลี่ยนใช้ฝึกและทดสอบในแต่ละครั้ง แบบนี้จะต้องเปลี่ยนวิธีการ

น่าเสียดายว่า pytorch ไม่ได้เตรียมคำสั่งที่สะดวกในการแบ่งชุดข้อมูลเอาไว้ ทำให้มีความยุ่งยากเล็กน้อยในการเขียน

การสุ่มแบ่งชุดข้อมูลอาจทำได้โดยใช้ SubsetRandomSampler ภายในมอดูลย่อย torch.utils.data

SubsetRandomSampler เป็นคลาสที่จะเก็บเลขดัชนีแล้วจะทำการสุ่มลำดับให้ค่าออกมา
from torch.utils.data import SubsetRandomSampler as Sarasa
srs = Sarasa([1,3,5,9])
print([x for x in srs])
print([x for x in srs])

ได้ค่าที่สุ่มลำดับต่างกันไปใน ๒ ครั้ง
[3, 5, 9, 1]
[9, 5, 1, 3]

(เนื่องจากชื่อยาว ในที่นี้ขอย่อเป็น Sarasa)

เวลาที่นำมาใช้กับ DataLoader จะใส่ในคีย์เวิร์ด sampler เพื่อเป็นตัวบอกว่าจะเอาข้อมูลลำดับที่เท่าไหร่บ้าง
import numpy as np
import matplotlib.pyplot as plt
import torchvision.datasets as ds
import torchvision.transforms as tf
from torch.utils.data import DataLoader as Dalo

data = ds.MNIST('pytorchdata/mnist',transform=tf.ToTensor(),download=1)
sampler = Sarasa(np.arange(0,31,2))
plt.figure(figsize=[6.4,0.4])
rup = Dalo(data,batch_size=16,sampler=sampler)
plt.axes([0,0,1,1]).imshow(np.hstack([x for x,z in rup][0][:,0]),cmap='gray')
sampler = Sarasa(np.arange(1,32,2))
plt.figure(figsize=[6.4,0.4])
rup = Dalo(data,batch_size=16,sampler=sampler)
plt.axes([0,0,1,1]).imshow(np.hstack([x for x,z in rup][0][:,0]),cmap='gray')
plt.show()





จะเห็นว่าถ้าใช้ sampler ที่ใส่ดัชนีต่างกันก็จะได้ข้อมูลที่เป็นคนละกลุ่มกัน การทำแบบนี้จึงสามารถแบ่งแยกข้อมูลได้



ต่อมาเพื่อทดสอบ ขอลองใช้กับข้อมูลรูปต่างๆ (วงกลม, สามเหลี่ยม, สี่เหลี่ยม, ดาว, กากบาท) ที่ตัวเองสร้างเตรียมขึ้นมาเพื่อใช้เป็นตัวอย่าง

โหลด >> https://phyblas.hinaboshi.com/triamhai/ruprang-misi-25x25x1000x6.rar
(รายละเอียดเกี่ยวกับชุดข้อมูล https://phyblas.hinaboshi.com/20180811)



อาจสร้างฟังก์ชันสำหรับเตรียมรูป แล้วใช้ ดังนี้
def triam_rup(folder_rup,satsuan_truat,n_batch_fuek,n_batch_truat):
    tran_fuek = tf.Compose([
        tf.RandomVerticalFlip(), # เนื่องจากเป็นรูปร่างอิสระ จะพลิกบนล่างหรือซ้ายขวาก็ได้
        tf.RandomHorizontalFlip(),
        tf.ToTensor(),
        tf.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))])
    tran_truat = tf.Compose([
        tf.ToTensor(),
        tf.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))])
    rup_fuek = ds.ImageFolder(folder_rup,transform=tran_fuek)
    rup_truat = ds.ImageFolder(folder_rup,transform=tran_truat)
    n = len(rup_fuek) # จำนวนข้อมูลทั้งหมด
    n_truat = int(n*satsuan_truat) # จำนวนข้อมูลตรวจสอบ
    sumlueak = np.random.permutation(n) # สร้างตัวสุ่มเลือก
    sf = Sarasa(sumlueak[n_truat:]) # sampler ของข้อมูลฝึก
    st = Sarasa(sumlueak[:n_truat]) # sampler ของข้อมูลตรวจสอบ
    rup_fuek = Dalo(rup_fuek,batch_size=n_batch_fuek,sampler=sf)
    rup_truat = Dalo(rup_truat,batch_size=n_batch_truat,sampler=st)
    return rup_fuek,rup_truat

folder_rup = 'ruprang-misi-25x25x1000x6' # โฟลเดอร์ใหญ่ที่ใส่รูปแยกเป็นโฟลเดอร์ย่อยต่างๆไว้
rup_fuek,rup_truat = triam_rup(folder_rup,0.2,64,100000)
rup_truat = list(rup_truat)[0]

satsuan_truat คือสัดส่วนของข้อมูลตรวจสอบ

n_batch_fuek,n_batch_truat คือขนาดมินิแบตช์ของข้อมูลฝึกและข้อมูลตรวจ

ข้อมูลตรวจสอบเราไม่ได้จะทำมินิแบตช์แต่จะให้ดึงออกมาเตรียมทั้งชุดไว้คำนวณทีเดียวก็เลยให้ใส่เลขเยอะๆไป (ในที่นี้ใส่ 100000)

ต่อมาลองสร้าง CNN แบบง่ายๆแล้วทำการฝึกโดยบันทึกทั้งคะแนนในการทำนายชุดข้อมูลฝึกและชุดข้อมูลตรวจสอบ
import torch
import time

relu = torch.nn.ReLU()
maxp = torch.nn.MaxPool2d(2)
ha_entropy = torch.nn.CrossEntropyLoss()

class Plianrup(torch.nn.Module):
    def __init__(self,*k):
        super(Plianrup,self).__init__()
        self.k = k
    
    def forward(self,x):
        return x.reshape(x.size()[0],*self.k)

class Prasat(torch.nn.Sequential):
    def __init__(self,eta=0.001):
        super(Prasat,self).__init__(
            torch.nn.Conv2d(3,16,4,1,0),
            torch.nn.BatchNorm2d(16),
            relu,
            maxp,
            torch.nn.Conv2d(16,16,4,1,0),
            torch.nn.BatchNorm2d(16),
            relu,
            maxp,
            Plianrup(-1),
            torch.nn.Linear(16*4*4,32),
            torch.nn.BatchNorm1d(32),
            relu,
            torch.nn.Linear(32,6)
        )
        self.opt = torch.optim.Adam(self.parameters(),lr=eta)
        
    def rianru(self,rup_fuek,rup_truat,n_thamsam=200,ro=10):
        X_truat,z_truat = rup_truat
        self.khanaen_truat = []
        self.khanaen_fuek = []
        khanaen_sungsut = 0
        t_roem = time.time()
        for o in range(n_thamsam):
            self.train()
            X_fuek,z_fuek = [],[]
            for Xb,zb in rup_fuek:
                a = self(Xb)
                J = ha_entropy(a,zb)
                J.backward()
                self.opt.step()
                self.opt.zero_grad()
                X_fuek.append(Xb)
                z_fuek.append(zb)
            X_fuek,z_fuek = torch.cat(X_fuek),torch.cat(z_fuek)
            self.eval()
            khanaen_fuek = self.ha_khanaen_(X_fuek,z_fuek)
            khanaen_truat = self.ha_khanaen_(X_truat,z_truat)
            self.khanaen_fuek.append(khanaen_fuek)
            self.khanaen_truat.append(khanaen_truat)
            print('%d ครั้งผ่านไป ใช้เวลาไป %.1f นาที ทำนายข้อมูลฝึกแม่น %.4f ข้อมูลตรวจสอบแม่น %.4f'%(o+1,(time.time()-t_roem)/60,khanaen_fuek,khanaen_truat))
            
            if(khanaen_truat>khanaen_sungsut):
                khanaen_sungsut = khanaen_truat
                maiphoem = 0
            else:
                maiphoem += 1
            if(ro>0 and maiphoem>=ro):
                break
    
    def thamnai_(self,X):
        return self(X).argmax(1)
    
    def ha_khanaen_(self,X,z):
        return (self.thamnai_(X)==z).numpy().mean()



prasat = Prasat()
prasat.rianru(rup_fuek,rup_truat)

plt.plot(prasat.khanaen_fuek,'#aa33bb')
plt.plot(prasat.khanaen_truat,'#33bb22')
plt.legend([u'ข้อมูลฝึก',u'ข้อมูลตรวจสอบ'],prop={'family':'Tahoma','size':14})
plt.show()




ผลที่ได้คือคะแนนการทำนายชุดข้อมูลฝึกได้มากกว่าชุดข้อมูลตรวจสอบอย่างเห็นได้ชัด แสดงให้เห็นว่าข้อมูลถูกแบ่งเป็นสองกลุ่มแยกกันอย่างชัดเจน



>> อ่านต่อ บทที่ ๑๔


-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

-----------------------------------------

หมวดหมู่

-- คอมพิวเตอร์ >> ปัญญาประดิษฐ์ >> โครงข่ายประสาทเทียม
-- คอมพิวเตอร์ >> เขียนโปรแกรม >> python >> pytorch

ไม่อนุญาตให้นำเนื้อหาของบทความไปลงที่อื่นโดยไม่ได้ขออนุญาตโดยเด็ดขาด หากต้องการนำบางส่วนไปลงสามารถทำได้โดยต้องไม่ใช่การก๊อปแปะแต่ให้เปลี่ยนคำพูดเป็นของตัวเอง หรือไม่ก็เขียนในลักษณะการยกข้อความอ้างอิง และไม่ว่ากรณีไหนก็ตาม ต้องให้เครดิตพร้อมใส่ลิงก์ของทุกบทความที่มีการใช้เนื้อหาเสมอ

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
python
-- numpy
-- matplotlib

-- pandas
-- pytorch
maya
การเรียนรู้ของเครื่อง
-- โครงข่ายประสาทเทียม
บันทึกในญี่ปุ่น
บันทึกในจีน
-- บันทึกในปักกิ่ง
บันทึกในไต้หวัน
บันทึกในยุโรปเหนือ
บันทึกในประเทศอื่นๆ
เรียนภาษาจีน
บทความอื่นๆ

บทความแบ่งตามหมวด



ติดตามอัพเดตของบล็อกได้ที่แฟนเพจ

  ค้นหาบทความ

  บทความแนะนำ

หลักการเขียนทับศัพท์ภาษาจีนกลาง
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
บ้านเก่าของจางเสวียเหลียงในเทียนจิน
เที่ยวจิ่นโจว ๓ วัน ๒ คืน 23 - 25 พ.ค. 2015
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
บันทึกการเที่ยวสวีเดน 1-12 พ.ค. 2014
แนะนำองค์การวิจัยและพัฒนาการสำรวจอวกาศญี่ปุ่น (JAXA)
เที่ยวฮ่องกงในคืนคริสต์มาสอีฟ เดินทางไกลจากสนามบินมาทานติ่มซำอร่อยโต้รุ่ง
เล่าประสบการณ์ค่ายอบรมวิชาการทางดาราศาสตร์โดยโซวเคนได 10 - 16 พ.ย. 2013
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
บันทึกการเที่ยวญี่ปุ่นครั้งแรกในชีวิต - ทุกอย่างเริ่มต้นที่สนามบินนานาชาติคันไซ
หลักการเขียนคำทับศัพท์ภาษาญี่ปุ่น
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ
ทำไมถึงอยากมาเรียนต่อนอก
เหตุผลอะไรที่ต้องใช้ภาษาวิบัติ?

ไทย

日本語

中文