机器学习–神经网络
如有错误或者疑问,欢迎交流,转载请注明出处
前向传播
神经网络的预测过程,由输入特征前向计算预测输出
除了输入层以外,隐藏层和输出层都是以sigmoid函数作为激活函数,输入层和隐藏层都加了偏置+1
import numpy as np
form sigmoid import * #自己写一个sigmoid函数
def nn_predict(theta1,theta2,X):
''' INPUT: theta1: 输入层到隐藏层参数 (hidden feature dim,input feature dim) ndarray theta2: 隐藏层到输出层参数 (output label dim,hidden feature dim) ndarray X: (m,n) ndarray m是测试样本数目 '''
m = x.shape[0]
num_labels = theta2.shape[0]
x = np.c_[np.ones(m),x] #加上偏置
z2 = x.dot(theta1.T)
a2 = sigmoid(z2)
a2 = np.c_[np.ones(m),a2] #加上偏置
z3 = a2.dot(theta2.T)
a3 = sigmoid(z3)
prediction = np.argmax(a3,axis=1) #返回概率最大的index
return prediction
反向传播学习
利用反向传播算法,根据带标签数据学习网络参数
1.定义损失函数
2.损失函数对参数求导
3.梯度法更新参数
-
cross entropy loss
因为参考了安主的Coursera Machine Learning课程,用了这个损失函数J(θ)=1m∑mi=1∑Kk=1[−y(i)klog((h(x(i)))k)−(1−y(i)k)log(1−(h(x(i)))k)] 其中m是训练样本数目,K是标签数目,感觉是逻辑回归损失函数的广泛定义,标签y是onehot编码的[0,0,0,1,…,0],类似这种
-
残差
残差就是损失函数对某个节点的输入的求导吧,求认证~
所以对输出层的第j个节点的输入求导,有点绕~,固定住损失函数的k,针对一个样例分析,即固定i
δ(3)j=====∂∂z(3)j(−yjlogg(z(3)j)−(1−yj)log(1−g(z(3)j)))(−yj1g(z(3)j)+(1−yj)11−g(z(3)j))∂g(z(3)j)∂z(3)j(−yj1g(z(3)j)+(1−yj)11−g(z(3)j))(g(z(3)j)(1−g(z(3)j))−yj(1−g(z(3)j)+(1−yj)g(z(3)j)g(z(3)j)−yj 写成向量的样子
δ(3)=a(3)−y
然后回传到隐藏层,其实是在做链式求导吧~δ(2)=(θ(2))Tδ(3)∗g′(z(2)) 就是把导数求到了隐藏层的输入而已吧~最终要求的其实是损失函数对参数的求导
Δ(l)=δ(l+1)(a(l))T 直观理解就是损失函数求导至l+1层的输入,而l+1层的输入是由参数
θ 与l层的输出线性组合得到的,所以继续链式求导就行了
#backpropagation
for i in range(m):#m是训练样本数目
a1 = X[i]#(input_layer_size+1,) ndarray
a1 = a1.reshape(1,input_layer_size+1)#这句为了形状正确~
z2 = a1.dot(theta1.T)#theta1(hidden_layer_size,input_layer_size+1)
a2 = sigmoid(z2)
a2 = np.c_[np.ones(1),a2]#增加偏置
z3 = a2.dot(theta2.T)#theta2(output_layer_size,hidden_layer_size+1)
a3 = sigmoid(z3)
delta3 = (a3 - yk[i])#yk:onehot label
z2 = np.c_[np.ones(1),z2]
delta2 = delta3.dot(theta2) * sigmoid_gradient(z2)
theta2_grad = theta2_grad + delta3.T.dot(a2)
theta1_grad = theta1_grad + delta2.T.dot(a1)[1:] #偏置项不反向传递误差
theta1_grad[:,0] = theta1_grad[:,:] / m
theta2_grad[:,0] = theta2_grad[:,:] / m
代码可以借鉴一下,和公式有出路,感觉只要写好公式,注意点矩阵的形状,问题不大。