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



โครงข่ายประสาทเทียมเบื้องต้น บทที่ ๑๐: การประกอบโครงข่ายขึ้นจากชั้นต่างๆ
เขียนเมื่อ 2018/08/26 23:29
แก้ไขล่าสุด 2022/07/10 21:09
>> ต่อจาก บทที่ ๙



ในบทที่แล้วได้อธิบายวิธีการสร้างชั้นต่างๆสำหรับประกอบในโครงข่ายประสาทเทียม ส่วนในบทนี้จะลองนำมาใช้

ขอยกตัวอย่างด้วยการสร้างคลาสเพอร์เซปตรอนสองชั้นสำหรับจำแนกประเภทหลายกลุ่มแบบเดียวกับที่ทำในบทที่ ๘ แค่เปลี่ยนมาใช้วิธีการประกอบขึ้นโดยเอาชั้นมาต่อกัน

จะเริ่มจากสร้างคลาสของชั้นต่างๆขึ้น จากนั้นก็สร้างคลาสของโครงข่ายประสาทเทียม ๒ ชั้นซึ่งใช้ชั้นต่างๆนั้นข้างใน
import numpy as np
import matplotlib.pyplot as plt

class Affin:
    def __init__(self,m0,m1,sigma):
        self.m = m0,m1
        self.w = np.random.normal(0,sigma,self.m)
        self.b = np.zeros(m1)
        self.gw = 0
        self.gb = 0
    
    def pai(self,X):
        self.X = X
        return np.dot(X,self.w) + self.b
    
    def yon(self,g):
        self.gw += np.dot(self.X.T,g)
        self.gb += g.sum(0)
        return np.dot(g,self.w.T)

class Sigmoid:
    def pai(self,a):
        self.h = 1/(1+np.exp(-a))
        return self.h
    
    def yon(self,g):
        return g*(1-self.h)*self.h

class Softmax_entropy:
    def pai(self,a,Z):
        self.Z = Z
        exp_a = np.exp(a.T-a.max(1))
        self.h = (exp_a/exp_a.sum(0)).T
        return -(np.log(self.h[Z]+1e-10)).mean()
    
    def yon(self,g):
        return g*(self.h-self.Z)/len(self.h)

def ha_1h(z,n):
    return z[:,None]==range(n)



class Prasat2chan:
    def __init__(self,m,eta):
        self.m = m
        self.eta = eta
    
    def rianru(self,X,z,n_thamsam):
        self.kiklum = int(z.max()+1)
        Z = ha_1h(z,self.kiklum) # แปลเป็นวันฮ็อต
        # ชั้นทั้งหมดของโครงข่ายประสาท
        self.chan = [Affin(X.shape[1],self.m,1),
                     Sigmoid(),
                     Affin(self.m,self.kiklum,1),
                     Softmax_entropy()]
        self.khanaen = []
        self.entropy = []
        for o in range(n_thamsam):
            # คำนวณไปข้างหน้า
            a = X
            for c in self.chan[:-1]:
                a = c.pai(a)
            # คำนวณค่าเสียหายจากชั้นสุดท้าย
            entropy = self.chan[-1].pai(a,Z)
            self.entropy.append(entropy)
            khanaen = (a.argmax(1)==z).mean() # คำนวณคะแนน
            self.khanaen.append(khanaen)
            # แพร่ย้อนกลับ
            g = 1
            for c in reversed(self.chan):
                g = c.yon(g)
            # ปรับพารามิเตอร์จากค่าอนุพันธ์ที่เก็บไว้หลังแพร่ย้อน
            for i in [0,2]:
                self.chan[i].w -= self.eta*self.chan[i].gw
                self.chan[i].b -= self.eta*self.chan[i].gb
                self.chan[i].gw = 0
                self.chan[i].gb = 0
    
    def thamnai(self,X):
        for c in self.chan[:-1]:
            X = c.pai(X)
        return X.argmax(1)

ชั้น Affin ในที่นี้นิยามต่างจากที่แนะนำในบทที่แล้วโดยแค่ป้อนขนาดขาเข้า (m0) ขาออก (m1) กับความกว้างการแจกแจงค่า (sigma) แล้วให้ไปสร้างค่า w และ b ตามที่กำหนด แบบนี้สะดวกในการใช้งานมากกว่า

ส่วนชั้น Softmax_entropy นี้คือซอฟต์แม็กซ์แล้วต่อด้วยเอนโทรปีไขว้ ที่เอามาเชื่อมกันโดยไม่แยกเพราะอนุพันธ์ของสองชั้นนี้ต่อกันคำนวณง่ายกว่าแยกทีละชั้น ดังนั้นยุบรวมกันแบบนี้คำนวณเร็วขึ้น ไม่มีประโยชน์ที่จะแยกเป็นชั้น

ตอนคำนวณไปข้างหน้า ที่ไม่ได้รวมชั้น Softmax_entropy ซึ่งเป็นชั้นสุดท้ายไว้ใน for ด้วยก็เพราะชั้นนี้ต้องใส่ค่าป้อนเข้า ๒ ตัว คือมี z ด้วย อีกทั้งผลจากชั้น Affin สุดท้ายยังต้องนำไปใช้ทำนายคำตอบเพื่อคำนวณคะแนนด้วย

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



ต่อไปเป็นตัวอย่างการนำคลาสที่สร้างขึ้นนี้มาใช้ ขอยกตัวอย่างเป็นข้อมูลลักษณะแบบนี้
np.random.seed(7)
r = np.tile(np.sqrt(np.linspace(0.5,25,200)),3)
t = np.random.normal(r,0.4)
z = np.arange(3).repeat(200)
t += z*np.pi/3*2
X = np.array([r*np.cos(t),r*np.sin(t)]).T
plt.scatter(X[:,0],X[:,1],50,c=z,edgecolor='k',cmap='winter')
plt.show()



สร้างโครงข่ายประสาทเพื่อจำแนกกลุ่มแล้วแสดงเขตการแบ่ง พร้อมทั้งแสดงความคืบหน้าในการเรียนรู้ด้วย
prasat = Prasat2chan(m=47,eta=0.5)
prasat.rianru(X,z,n_thamsam=2000)
mx,my = np.meshgrid(np.linspace(X[:,0].min(),X[:,0].max(),200),np.linspace(X[:,1].min(),X[:,1].max(),200))
mX = np.array([mx.ravel(),my.ravel()]).T
mz = prasat.thamnai(mX).reshape(200,-1)
plt.axes(aspect=1,xlim=(X[:,0].min(),X[:,0].max()),ylim=(X[:,1].min(),X[:,1].max()))
plt.contourf(mx,my,mz,cmap='winter',alpha=0.2)
plt.scatter(X[:,0],X[:,1],50,c=z,edgecolor='k',cmap='winter')
plt.figure()
plt.subplot(211,xticks=[])
plt.plot(prasat.entropy,'#8899dd')
plt.ylabel(u'เอนโทรปี',family='Tahoma')
plt.subplot(212)
plt.plot(prasat.khanaen,'#8899dd')
plt.ylabel(u'คะแนน',family='Tahoma')
plt.xlabel(u'จำนวนรอบ',family='Tahoma')
plt.show()





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

แต่ว่ายังมีวิธีที่จะสามารถทำให้สะดวกขึ้นได้มากกว่านี้อีก ซึ่งจะแนะนำต่อในบทต่อไป



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


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

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

ดูสถิติของหน้านี้

หมวดหมู่

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

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

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
มอดูลต่างๆ
-- numpy
-- matplotlib

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

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



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

  ค้นหาบทความ

  บทความแนะนำ

ตัวอักษรกรีกและเปรียบเทียบการใช้งานในภาษากรีกโบราณและกรีกสมัยใหม่
ที่มาของอักษรไทยและความเกี่ยวพันกับอักษรอื่นๆในตระกูลอักษรพราหมี
การสร้างแบบจำลองสามมิติเป็นไฟล์ .obj วิธีการอย่างง่ายที่ไม่ว่าใครก็ลองทำได้ทันที
รวมรายชื่อนักร้องเพลงกวางตุ้ง
ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
การใช้ unix shell เบื้องต้น ใน linux และ mac
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ

ไทย

日本語

中文