from unagi import Chan,Affin,Relu,Sigmoid_entropy,Adam,Batchnorm
import numpy as np
class Batchnorm(Chan):
def __init__(self,m,mmt=0.9):
self.m = m # จำนวนตัวแปรของข้อมูล
self.param = [Param(np.ones(m)),Param(np.zeros(m))] # ค่า γ และ β
self.rmu = np.zeros(m) # ค่าเฉลี่ยขณะวิ่ง
self.rvar = np.zeros(m)+1e-8 # ความแปรปรวนขณะวิ่ง
self.mmt = mmt # โมเมนตัม
self.fuekyu = 1
def pai(self,x):
if(self.fuekyu): # กรณีฝึกอยู่ คำนวณ xn ค่าเฉลี่ยและความแปรปรวนในกลุ่ม
self.n = len(x)
mu = x.mean(0)
self.xc = x-mu
var = (self.xc**2).mean(0)+1e-8
self.sigma = np.sqrt(var)
self.xn = xn = self.xc/self.sigma
self.rmu = self.mmt*self.rmu + (1.-self.mmt)*mu
self.rvar = self.mmt*self.rvar + (1.-self.mmt)*var
else: # กรณีไม่ได้ฝึกอยู่ คำนวณ xn จาก rmu (μR) และ rvar (σR2)
xc = x - self.rmu
xn = xc/np.sqrt(self.rvar)
return self.param[0].kha*xn+self.param[1].kha
def yon(self,g):
self.param[0].g = (g*self.xn).sum(0)
self.param[1].g = g.sum(0)
gxn = self.param[0].kha*g
gsigma = -((gxn*self.xc)/self.sigma**2).sum(0)
gvar = gsigma/self.sigma/2
gxc = gxn/self.sigma + (2./self.n)*self.xc*gvar
gmu = gxc.sum(0)
gx = gxc - gmu/self.n
return gx
import matplotlib.pyplot as plt
n = 350
t = np.random.uniform(0,360,n*2)
r = [np.random.normal(1+0.4*np.sin(np.radians(t[:n])*5),0.2)]
r += [np.random.normal(2+0.4*np.sin(np.radians(t[n:])*5),0.3)]
r = np.hstack(r)
x = r*np.cos(np.radians(t))
y = r*np.sin(np.radians(t))
z = np.repeat([0,1],n)
X = np.array([x,y]).T
plt.axes(aspect=1)
plt.scatter(X[:,0],X[:,1],c=z,edgecolor='k',alpha=0.6,cmap='RdYlGn')
plt.show()
plt.figure(figsize=[6.5,6.5])
ax1 = plt.subplot(211,xticks=[])
ax1.set_title(u'เอนโทรปี',family='Tahoma')
ax2 = plt.subplot(212)
ax2.set_title(u'คะแนน',family='Tahoma')
m = [2,60,60,60,1] # จำนวนเซลล์ในชั้นต่างๆ
n_thamsam = 160 # จำนวนรอบที่ทำซ้ำเพื่อปรับพารามิเตอร์
for b in [0,1]:
for s in [0.1,1]:
# กำหนดแบบจำลอง
chan = []
param = []
for i in range(len(m)-1):
he_kaiming = np.sqrt(2./m[i]) # ค่าน้ำหนักตั้งต้นแบบเหอ ไข่หมิง
af = Affin(m[i],m[i+1],he_kaiming*s)
chan.append(af)
param.extend(af.param)
if(i<len(m)-2):
if(b): # ใส่ชั้นแบตช์นอร์ม
bn = Batchnorm(m[i+1])
chan.append(bn)
param.extend(bn.param)
chan.append(Relu())
chan.append(Sigmoid_entropy())
opt = Adam(param,eta=0.001) # ออปทิไมเซอร์
# เริ่มฝึก
lis_entropy = []
lis_khanaen = []
for i in range(n_thamsam):
# คำนวนไปข้างหน้าในโหมดฝึก เพื่อหาเอนโทรปีแล้วแพร่ย้อนกลับ
X_ = X
for c in chan[:-1]:
c.fuekyu = 1 # ฝึกอยู่
X_ = c(X_)
entropy = chan[-1](X_,z)
lis_entropy.append(entropy.kha) # บันทึกค่าเอนโทรปี
entropy.phraeyon() # แพร่ย้อนกลับ
opt() # ปรับพารามิเตอร์
# คำนวณไปข้างหน้าใหม่ในโหมดใช้งานจริง เพื่อหาคะแนนความแม่นในการทำนาย
X_ = X
for c in chan[:-1]:
c.fuekyu = 0 # ไม่ได้ฝึกอยู่
X_ = c(X_)
lis_khanaen.append(((X_.kha.ravel()>0)==z).mean()) # บันทึกคะแนน
ax1.plot(lis_entropy,[':','-'][s==1],color=['r','g'][b])
ax2.plot(lis_khanaen,[':','-'][s==1],color=['r','g'][b])
plt.legend([u'ไม่มีแบตช์นอร์ม, $\sigma_w$=เหอ/10',
u'ไม่มีแบตช์นอร์ม, $\sigma_w$=เหอ',
u'มีแบตช์นอร์ม, $\sigma_w$=เหอ/10',
u'มีแบตช์นอร์ม, $\sigma_w$=เหอ'],
prop={'family':'Tahoma','size':15})
plt.tight_layout()
plt.show()
ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ