φυβλαςのβλογ
phyblasのブログ



โครงข่ายประสาทเทียมเบื้องต้น บทที่ ๑๔: ปัญหาการวิเคราะห์การถดถอย
เขียนเมื่อ 2018/08/26 23:33
แก้ไขล่าสุด 2021/09/28 16:42
>> ต่อจาก บทที่ ๑๓



ในบทที่ผ่านๆมาเราพูดถึงแต่ปัญหาการจำแนกประเภทข้อมูล

ในบทนี้จะแสดงถึงตัวอย่างการใช้ในปัญหาวิเคราะห์การถดถอยบ้าง



การวิเคราะห์การถดถอยเชิงเส้น

การวิเคราะห์การถดถอย (回归, regression) คือการหาความสัมพันธ์ระหว่างตัวแปรต้นกับตัวแปรตาม

ตัวอย่างเช่น มีข้อมูลค่าตัวแปรต้น x และตัวแปรตาม z เขียนความสัมพันธ์ได้แบบนี้
import numpy as np
import matplotlib.pyplot as plt
x = np.random.uniform(0,2,40)
z = 3*x-7 + np.random.normal(0,0.3,40)
plt.scatter(x,z,c='r',edgecolor='k')
plt.show()



ความสัมพันธ์ดูแล้วมีแนวโน้มที่จะเป็นเส้นตรง ดังนั้นสามารถบอกความสัมพันธ์ระหว่าง x และ z ได้โดยการใช้เส้นตรงลากผ่าน ได้ความสัมพันธ์ z = xw+b แบบนี้เรียกว่าการวิเคราะห์การถดถอยเชิงเส้น (线性回归, linear regression)

เกี่ยวกับการวิเคราะห์การถดถอยเชิงเส้นนั้น เคยได้อธิบายละเอียดไปแล้วใน https://phyblas.hinaboshi.com/20161210

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

ทั้งการวิเคราะห์การถดถอยและการวิเคราะห์จำแนกประเภทนั้นต่างก็เป็นการหาความสัมพันธ์ระหว่างตัวแปรต้นและตัวแปรตามเหมือนกัน แต่ต่างกันตรงที่ตัวแปรตามในการวิเคราะห์การจำแนกประเภทคือประเภทที่จำแนกได้ ส่วนการวิเคราะห์การถดถอยตัวแปรตามคือค่าตัวเลข

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

แต่ว่าในการวิเคราะห์การถดถอยจะไม่มีการใช้ฟังก์ชันกระตุ้น และจะใช้ค่าความเสียหายเป็นค่าความต่างกำลังสองเฉลี่ย
..(14.1)

โดย z คือคำตอบจริง ส่วน h คือคำตอบที่คำนวณได้ จะเห็นว่ายิ่งต่างกันมากค่าก็ยิ่งมากแสดงว่ายิ่งไม่ดี จึงเป็นค่าที่จะต้องลด

h ก็มาจากการคำนวณจาก x และ w โดยตรง
..(14.2)

อนุพันธ์ของค่าเสียหายเทียบกับ w และ b ก็จะได้
..(14.3)

ต่อมาลองนิยามคลาสของชั้นค่าเสียหายนี้เหมือนกับที่ทำกับชั้นอื่นๆที่ผ่านมา

ก่อนอื่นนำเข้าคลาสต่างๆที่จำเป็นในบทนี้ ซึ่งเตรียมไว้ใน >> unagi.py
from unagi import Chan,Affin,Relu,Sigmoid,Adam

เราอาจเขียนชั้นของค่าความต่างกำลังสองเฉลี่ยได้ดังนี้
class Mse(Chan):
    def pai(self,h,z):
        self.z = z[:,None]
        self.h = h
        return ((self.z-h)**2).mean()
    
    def yon(self,g):
        return g*2*(self.h-self.z)/len(self.z)

ต่อไปเป็นต้วอย่างการเขียนคลาสของการวิเคราะห์การถดถอยเชิงเส้น
class ThotthoiChoengsen:
    def rianru(self,X,z,n_thamsam):
        self.chan = [Affin(X.shape[1],1,0),Mse()]
        self.opt = Adam(self.chan[0].param)
        for o in range(n_thamsam):
            h = self.chan[0](X)
            mse = self.chan[1](h,z)
            mse.phraeyon()
            self.opt()
    
    def thamnai(self,X):
        h = self.chan[0].pai(X)
        return h.ravel()

ลองนำมาใช้กับข้อมูลหนึ่งมิติ
x = np.random.uniform(0,2,30)
X = x[:,None]
z = 2*x-3 + np.random.normal(0,0.4,30)
tc = ThotthoiChoengsen()
tc.rianru(X,z,10000)
x_ = np.linspace(-0.1,2.1,101)
X_ = x_[:,None]
z_ = tc.thamnai(X_)
plt.scatter(x,z,c='c',edgecolor='k')
plt.plot(x_,z_,'r')
plt.show()



ลองใช้กับข้อมูลสองมิติ
from mpl_toolkits.mplot3d import Axes3D

X = np.random.uniform(-1,1,[100,2])
x,y = X.T
z = np.random.normal(x*2+y*3+1,1)

tc = ThotthoiChoengsen()
tc.rianru(X,z,10000)

plt.figure(figsize=[7,7])
ax = plt.axes([0,0,1,1],projection='3d')
ax.scatter(x,y,z,c=z,edgecolor='k',cmap='winter')

mx,my = np.meshgrid(np.linspace(-1,1,21),np.linspace(-1,1,21))
mX = np.array([mx.ravel(),my.ravel()]).T
mz = tc.thamnai(mX).reshape(21,-1)
ax.plot_surface(mx,my,mz,rstride=1,cstride=1,alpha=0.2,color='r',edgecolor='k')
plt.show()





การวิเคราะห์การถดถอยแบบไม่เป็นเชิงเส้น

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

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

สำหรับปัญหาการวิเคราะห์การถดถอยนั้น แม้ว่าชั้นสุดท้ายจะไม่ต้องการฟังก์ชันกระตุ้น แต่ว่าในระหว่างชั้นต่างๆยังคงจำเป็นจะต้องใช้ฟังก์ชันกระตุ้นอยู่

ฟังก์ชันกระตุ้นระหว่างชั้นอาจเลือกใช้ ReLU หรือซิกมอยด์ก็ได้ แต่ผลที่ได้จะมีลักษณะค่อนข้างต่างกัน

ขอลองยกตัวอย่างเป็นโครงข่ายประสาท ๓ ชั้นที่ใช้ ReLU เขียนได้ดังนี้
class PrasatThotthoi:
    def __init__(self,m1,m2,eta=0.001):
        self.m1 = m1
        self.m2 = m2
        self.eta = eta
        self.chan = [None,
                     Relu(),
                     Affin(m1,m2,np.sqrt(2./m1)),
                     Relu(),
                     Affin(m2,1,0),
                     Mse()]
    
    def rianru(self,X,z,n_thamsam):
        m0 = X.shape[1]
        self.chan[0] = Affin(m0,self.m1,np.sqrt(2./m0))
        self.opt = Adam(self.param(),eta=self.eta)
        for o in range(n_thamsam):
            mse = self.ha_mse(X,z)
            mse.phraeyon()
            self.opt()
    
    def ha_mse(self,X,z):
        for c in self.chan[:-1]:
            X = c(X)
        return self.chan[-1](X,z)
    
    def param(self):
        p = []
        for c in self.chan:
            if(hasattr(c,'param')):
                p.extend(c.param)
        return p
    
    def thamnai(self,X):
        for c in self.chan[:-1]:
            X = c(X)
        return X.kha.ravel()

np.random.seed(0)
x = np.random.uniform(-1,1,60)
X = x[:,None]
z = np.sin(x*3)+np.random.normal(0,0.2,60)

m1,m2 = 20,30
ps = PrasatThotthoi(m1,m2,eta=0.005)
ps.rianru(X,z,1000)
x_ = np.linspace(-1.2,1.2,101)
X_ = x_[:,None]
z_ = ps.thamnai(X_)
plt.scatter(x,z,c='c',edgecolor='k')
plt.plot(x_,z_,'r')
plt.show()


จะเห็นว่าดูแล้วกราฟพยายามจะเข้าไปผ่านจุดต่างๆ แต่ก็ดูไม่เป็นธรรมชาติ และเต็มไปด้วยเส้นตรง นี่เป็นผลของการใช้ ReLU เป็นฟังก์ชันกระตุ้น

คือแม้ว่า ReLU จะเป็นฟังก์ชันไม่เป็นเชิงเส้น แต่ก็แค่เป็นการนำเชิงเส้นมาหักเท่านั้น ยังไงโดยพื้นฐานก็ยังเป็นเชิงเส้น เมื่อใช้ ReLU เป็นฟังก์ชันกระตุ้นในการวิเคราะห์การถดถอยจึงได้ผลลัพธ์ที่เหมือนเส้นตรงหักเป็นช่วงๆ

ในขณะที่หากลองเปลี่ยนมาใช้ฟังก์ชันซิกมอยด์ดู



ผลที่ได้จะเห็นว่าเป็นเส้นโค้งดูเป็นธรรมชาติกว่า



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


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

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

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

หมวดหมู่

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

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

目次

日本による名言集
モジュール
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
機械学習
-- ニューラル
     ネットワーク
javascript
モンゴル語
言語学
maya
確率論
日本での日記
中国での日記
-- 北京での日記
-- 香港での日記
-- 澳門での日記
台灣での日記
北欧での日記
他の国での日記
qiita
その他の記事

記事の類別



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

  記事を検索

  おすすめの記事

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

月別記事

2025年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2024年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2023年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2022年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2021年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

もっと前の記事

ไทย

日本語

中文