vanilla neural network 学习材料有好多
前年年都是用MATLAB写的,写的还挺丑,后来用tensorflow写把底层细节都盖住了。
这里是一个只用numpy实现的版本
学习材料的话。MATLAB推荐王小川的 45个神经网络案例 第一章
数学推导推荐吴恩达的Ufldl 反向传导算法
这个推荐用jupyter玩,把train和inference分开,可以用同样的parameter测着玩
activation function 的求导比较有技巧
sigmoid : 1/(1-exp(-x))
导数是fx*(1-fx)
fx是正向传播解出来的矩阵,为了高效计算,直接使用这个结果
tanh导数 1-(fx*fx)同理
要处理的问题就是逻辑:(a xor b) and c
也可以根据自己开心随便改,就是把改train_x 搞成相应的真值表。
在train与inference之间还可以加上文件读写来save parameter, 再load一部分回来做transfer learning(当然这已经是deep learning的套路了这个小网络没必要)
import numpy as np
train_x = np.array([
[0,0,1],
[0,1,1],
[1,0,1],
[1,1,1],
[0,0,0],
[0,1,0],
[1,0,0],
[1,1,0]
])
train_y = np.array([
[0],
[1],
[1],
[0],
[0],
[0],
[0],
[0]
])
def _sigmoid(x,der = False):
if der == True:
return x*(1-x)
return 1/(1+np.exp(-x))
def _tanh(x,der = False):
if der == True:
return 1-(x*x)
return np.tanh(x)
def _relu(x,der = False):
if der ==True:
return 1*(x>0)
return x*(x>0)
def train():
i = 3
o = 1
# hyperparameter
num = 50000
h = 4
#parameter
syn0 = 2*np.random.random((i,h))-1
syn1 = 2*np.random.random((h,o))-1
for epoch in range(num):
# feed forward
l0 = train_x # (4,i)
l1 = _sigmoid(l0.dot(syn0)) # (4,h)
l2 = _sigmoid(l1.dot(syn1)) # (4,o)
#loss
loss = 1/2*(train_y - l2)**2
# back propagate
l2_err = train_y - l2 # (4,o)
l2_delta = l2_err*_sigmoid(l2,der=True) # (4,o)
l1_err = l2_delta.dot(syn1.T) # (4,h)
l1_delta = l1_err*_sigmoid(l1,der=True) # (4,h)
## update parameter
syn1 += l1.T.dot(l2_delta)
syn0 += l0.T.dot(l1_delta)
if epoch%1000 == 0:
print(np.mean(loss))
return syn0,syn1
def inference(syn0,syn1,x):
l0 = x # (4,i)
l1 = _sigmoid(l0.dot(syn0)) # (4,h)
l2 = _sigmoid(l1.dot(syn1)) # (4,o)
return l2
test_x = np.array([0,1,1])
syn0,syn1 = train()
pre_y = inference(syn0,syn1,test_x)
print(pre_y)