机器学习 2014斯坦福大学课程: 4-1 神经网络

本文深入探讨了神经网络的基本概念,包括前向传播算法、代价函数及反向传播算法,并通过Stanford大学2014年课程实例,详细解析了神经网络在解决复杂机器学习问题中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

机器学习 2014斯坦福大学课程: 4-1 神经网络

刚开始学习机器学习,学习的视频教程是coursera网站上吴恩达(Andrew Ng)教授的机器学习课程。
在此梳理并记录总结笔记,供学习交流,欢迎批评指正!

机器学习 分类回顾

  1. 监督学习(supervised learning )
    1.1 回归问题(regression): 线性回归问题(linear regression)
    1.2 分类问题(classification):逻辑回归问题(logistic regression)
  2. 无监督学习(unsupervised learning)
    2.1 聚集问题(clustering)
    2.2. 非聚集问题(non-clustering)

神经网络(Neural Networks)

神经网络可用于解决非线性回归问题,当输入特征太多数据量大的时候。
回归问题:m为样本数,n为特征数
展示一个最简单的神经网络结构:
一个输入层,一个隐藏层,一个输出层;
隐藏层的层数和每层的个数是自己决定的,一般每层隐藏层的个数相同
在这里插入图片描述

标记:

  1. 输入层input layer :Layer1
    输入单元数:3个 x 1 , x 2 , x 3 x_1,x_2,x_3 x1,x2,x3 对应于3个特征
    又可表示为: a 1 1 , a 2 1 , a 3 1 a_1^1,a_2^1,a_3^1 a11,a21,a31
    偏差单元bias unit:1个 x 0 x_0 x0
  2. 隐藏层hidden layer:Layer2
    激活单元数:3个 a 1 2 , a 2 2 , a 3 2 a_1^2,a_2^2,a_3^2 a12,a22,a32
    a i j a_i^j aij代表第j层的第i个激活单元
    偏差单元:1个 a 0 a_0 a0
  3. 输出层output laye :Layer3
  4. 权重weight(参数 Θ \Theta Θ
    Θ ( 1 ) \Theta^{(1)} Θ(1)表示从Layer1到Layer2的映射,即输入层到隐藏层 a ( 2 ) = Θ 1 ∗ X a^{(2)}=\Theta^{1}*X a(2)=Θ1X
    Θ ( 2 ) \Theta^{(2)} Θ(2)表示从Layer2到Layer3的映射,即隐藏层到输出层 a ( 3 ) = Θ 2 ∗ a ( 2 ) a^{(3)}=\Theta^{2}*a^{(2)} a(3)=Θ2a(2)
    h = a ( 3 ) h=a^{(3)} h=a(3)

前向传播算法(Forward Propagation)

逻辑回归问题,二分类,y=0或1代表属于两个分类,n个特征
只考虑一个样本,神经网络只有一层隐藏层,一共神经网络层数L为3层, s l s_l sl表示该层的神经元数,
隐藏层的神经元单元数为 s 2 = s i z e s_2=size s2=size,输入层的单元数则为 s L = 1 s_L=1 sL=1

输入层Layer1: x ( n + 1 ) ∗ 1 = [ x 0 x 1 x 2 ⋮ x n ] = a ( 1 ) x_{(n+1)*1}=\begin{bmatrix}x_0\\x_1 \\x_2 \\\vdots\\x_n\\\end{bmatrix}=a^{(1)} x(n+1)1=x0x1x2xn=a(1)
隐藏层Layer2: a ( s i z e + 1 ) ∗ 1 ( 2 ) = [ a 0 ( 2 ) a 1 ( 2 ) a 2 ( 2 ) ⋮ a n ( 2 ) ] a^{(2)}_{(size+1)*1}=\begin{bmatrix}a_0^{(2)}\\a_1^{(2)} \\a_2^{(2)} \\\vdots\\a_n^{(2)}\\\end{bmatrix} a(size+1)1(2)=a0(2)a1(2)a2(2)an(2)
输出层: a ( 3 ) = a 1 ( 3 ) a^{(3)}=a_1^{(3)} a(3)=a1(3)
权重: Θ ( 1 ) \Theta^{(1)} Θ(1), Θ ( 2 ) \Theta^{(2)} Θ(2)
过程
z ( 2 ) = Θ ( 1 ) x z^{(2)}=\Theta^{(1)}x z(2)=Θ(1)x
其中 z s i z e ∗ 1 ( 2 ) , Θ s i z e ∗ ( n + 1 ) ( 1 ) , x ( n + 1 ) ∗ 1 z^{(2)}_{size*1},\Theta^{(1)}_{size*(n+1)},x_{(n+1)*1} zsize1(2),Θsize(n+1)(1),x(n+1)1
a ( 2 ) = g ( z ( 2 ) ) a^{(2)}=g(z^{(2)}) a(2)=g(z(2))
a ( 2 ) = [ a 0 ( 2 ) a 1 ( 2 ) ⋮ a n ( 2 ) ] = g ( [ θ 10 ( 1 ) θ 11 ( 1 ) ⋯ θ 1 n ( 1 ) θ 20 ( 1 ) θ 21 ( 1 ) ⋯ θ 2 n ( 1 ) ⋮ ⋮ ⋱ ⋮ θ s i z e 0 ( 1 ) θ s i z e 1 ( 1 ) ⋯ θ s i z e n ( 1 ) ] ∗ [ x 0 x 1 ⋮ x n ] ) a^{(2)}=\begin{bmatrix}a_0^{(2)}\\a_1^{(2)}\\\vdots\\a_n^{(2)}\\\end{bmatrix}= g( \begin{bmatrix}\theta_{10}^{(1)} & \theta_{11}^{(1)} & \cdots & \theta_{1n}^{(1)} \\ \theta_{20}^{(1)} & \theta_{21}^{(1)} & \cdots & \theta_{2n}^{(1)}\\ \vdots & \vdots & \ddots & \vdots \\ \theta_{size0}^{(1)} & \theta_{size1}^{(1)} & \cdots & \theta_{sizen}^{(1)} \\\end{bmatrix} *\begin{bmatrix}x_0\\x_1\\\vdots\\x_n\\\end{bmatrix}) a(2)=a0(2)a1(2)an(2)=g(θ10(1)θ20(1)θsize0(1)θ11(1)θ21(1)θsize1(1)θ1n(1)θ2n(1)θsizen(1)x0x1xn)
其中 a s i z e ∗ 1 ( 2 ) , z s i z e ∗ 1 ( 2 ) a^{(2)}_{size*1},z^{(2)}_{size*1} asize1(2)zsize1(2),g(z)为sigmoid函数,添加偏差单元 a 0 ( 2 ) = 1 a_0^{(2)}=1 a0(2)=1,变为 a ( s i z e + 1 ) ∗ 1 ( 2 ) a^{(2)}_{(size+1)*1} a(size+1)1(2)
z ( 3 ) = Θ ( 2 ) a 2 z^{(3)}=\Theta^{(2)}a^2 z(3)=Θ(2)a2
其中, z 1 ∗ 1 ( 3 ) , Θ ( 1 ∗ ( s i z e + 1 ) ) ( 2 ) , a ( s i z e + 1 ) ∗ 1 2 z^{(3)}_{1*1},\Theta^{(2)}_{(1*(size+1))},a^2_{(size+1)*1} z11(3)Θ(1(size+1))(2)a(size+1)12
h = a ( 3 ) = g ( z ( 3 ) ) h=a^{(3)}=g(z^{(3)}) h=a(3)=g(z(3))
对于所有样本,只需要将X转置,保证一个样本的特征在同一列,即可。
对于多分类问题,k>2, 将 y m ∗ 1 y_{m*1} ym1扩展到 Y m ∗ k Y_{m*k} Ymk
1分类, y=[1 0 0 0 0 … 0 0 0]
2分类, y=[0 1 0 0 0 … 0 0 0]
k分类, y=[0 0 0 0 0 … 0 0 1]
通过以上过程,即前向传播算法,我们能得到h,即拟合的公式

代价函数

逻辑回归问题中代价函数为:
J ( θ 0 , θ 1 , . . . θ n ) = 1 m ∑ i = 1 m ( − y ( i ) ∗ l o g ( h θ ( x ( i ) ) ) + ( 1 − y ( i ) ) ) l o g ( 1 − h θ ( x ( i ) ) ) ) + λ 2 m ∑ j = 1 n θ j 2 J(\theta_0,\theta_1,...\theta_n)=\frac{1}{m}\sum_{i=1}^m (-y^{(i)}*log(h_\theta(x^{(i)}))+(1-y^{(i))})log(1-h_\theta(x^{(i)}))) +\frac{\lambda}{2m}\sum_{j=1}^n\theta_j^2 J(θ0,θ1,...θn)=m1i=1m(y(i)log(hθ(x(i)))+(1y(i)))log(1hθ(x(i))))+2mλj=1nθj2
神经网络中代价函数为:
J ( Θ ) = 1 m ∑ i = 1 m ∑ k = 1 K ( − y k ( i ) ∗ l o g ( h Θ ( x ( i ) ) ) k + ( 1 − y k ( i ) ) ) l o g ( 1 − h Θ ( x ( i ) ) ) k ) + λ 2 m ∑ l = 1 L − 1 ∑ i = 1 s l ∑ j = 1 s l + 1 ( Θ j i l ) 2 J(\Theta)=\frac{1}{m}\sum_{i=1}^m\sum_{k=1}^K (-y_k^{(i)}*log(h_\Theta(x^{(i)}))_k+(1-y_k^{(i))})log(1-h_\Theta(x^{(i)}))_k) +\frac{\lambda}{2m}\sum_{l=1}^{L-1}\sum_{i=1}^{s_l}\sum_{j=1}^{s_l+1}(\Theta_{ji}^l)^2 J(Θ)=m1i=1mk=1K(yk(i)log(hΘ(x(i)))k+(1yk(i)))log(1hΘ(x(i)))k)+2mλl=1L1i=1slj=1sl+1(Θjil)2
第一项中,可以理解为有k个分类,每一个样本输出的k个分类求和,再所有样本求和
正则化一项,可以理解为每两层之间的权重,去掉 θ 0 \theta_0 θ0后平方所有元素求和,再所有层得权重相加。
以下是不严格的写法,帮助理解:
J ( Θ ) = 1 m ∑ i = 1 m ( − Y . ∗ l o g ( h ( Θ ) ) + ( 1 − Y ) . ∗ l o g ( 1 − h ( Θ ) ) ) + λ 2 m ( s u m ( ( Θ ( 1 ) ) 2 ) + s u m ( ( Θ ( 2 ) ) 2 ) ) + . . . ) J(\Theta)=\frac{1}{m}\sum_{i=1}^m(-Y.*log(h(\Theta))+(1-Y).*log(1-h(\Theta)))+\frac{\lambda}{2m}(sum((\Theta^{(1)})^2)+sum((\Theta^{(2)})^2))+...) J(Θ)=m1i=1m(Y.log(h(Θ))+(1Y).log(1h(Θ)))+2mλ(sum((Θ(1))2)+sum((Θ(2))2))+...)

反向传播算法(back propagation)

反向传播算法用于计算代价函数偏导上,在数学上得到证明,在此略。
在例子中有两个参数矩阵 Θ ( 1 ) , Θ ( 2 ) \Theta^{(1)},\Theta^{(2)} Θ(1),Θ(2)
那么对应的偏导数有 ∂ ∂ Θ ( 1 ) J Θ , ∂ ∂ Θ ( 2 ) J Θ \frac{\partial}{\partial\Theta^{(1)}}J_{\Theta},\frac{\partial}{\partial\Theta^{(2)}}J_{\Theta} Θ(1)JΘ,Θ(2)JΘ

对于每一个样本m:
输出层的误差: δ ( 3 ) = y − h = y − a ( 3 ) \delta^{(3)}=y-h=y-a^{(3)} δ(3)=yh=ya(3)
隐藏层的误差: δ ( 2 ) = ( θ ( 2 ) ) T δ ( 3 ) ∗ g ′ ( z 2 ) \delta^{(2)}=(\theta^{(2)})^T\delta^{(3)}*g^{'}(z^2) δ(2)=(θ(2))Tδ(3)g(z2)
其中, g ′ ( z ) g^{'}(z) g(z)为sigmoid函数的导函数,在数学上证明为 g ′ ( z ) = g ( z ) ∗ ( 1 − g ( z ) ) g^{'}(z)=g(z)*(1-g(z)) g(z)=g(z)(1g(z))
输入层不存在误差
对于所有样本 : Δ j i ( l ) = Δ j i ( l ) + a j ( l ) δ i l + 1 \Delta_{ji}^{(l)}=\Delta_{ji}^{(l)}+a_j^{(l)}\delta_i^{l+1} Δji(l)=Δji(l)+aj(l)δil+1
在此例子中:
Δ j i ( 1 ) = Δ j i ( 1 ) + a j ( 1 ) δ i 2 \Delta_{ji}^{(1)}=\Delta_{ji}^{(1)}+a_j^{(1)}\delta_i^{2} Δji(1)=Δji(1)+aj(1)δi2
Δ j i ( 2 ) = Δ j i ( 2 ) + a j ( 2 ) δ i 3 \Delta_{ji}^{(2)}=\Delta_{ji}^{(2)}+a_j^{(2)}\delta_i^{3} Δji(2)=Δji(2)+aj(2)δi3
代价函数的偏导数为:
D j i ( l ) = 1 m Δ j i ( l ) + λ m Θ i j l , j ≠ 0 D_{ji}^{(l)}=\frac{1}{m}\Delta_{ji}^{(l)}+\frac{\lambda}{m}\Theta_{ij}^{l},j\ne0 Dji(l)=m1Δji(l)+mλΘijl,j̸=0
在此例子中:
∂ ∂ Θ ( 1 ) J Θ = D j i ( 1 ) = 1 m Δ j i ( 1 ) + λ m Θ i j ( 1 ) , j ≠ 0 \frac{\partial}{\partial\Theta^{(1)}}J_{\Theta}=D_{ji}^{(1)}=\frac{1}{m}\Delta_{ji}^{(1)}+\frac{\lambda}{m}\Theta_{ij}^{(1)},j\ne0 Θ(1)JΘ=Dji(1)=m1Δji(1)+mλΘij(1),j̸=0
∂ ∂ Θ ( 2 ) J Θ = D j i ( 2 ) = 1 m Δ j i ( 2 ) + λ m Θ i j ( 2 ) , j ≠ 0 \frac{\partial}{\partial\Theta^{(2)}}J_{\Theta}=D_{ji}^{(2)}=\frac{1}{m}\Delta_{ji}^{(2)}+\frac{\lambda}{m}\Theta_{ij}^{(2)},j\ne0 Θ(2)JΘ=Dji(2)=m1Δji(2)+mλΘij(2),j̸=0
不难看出,反向传播算法需要与前向传播算法结合使用

解决思路

神经网络可以解决回归问题、分类问题
在本例子中,将分类问题的解决方法之一逻辑回归做了改进,用神经网络姐姐

  1. 构架神经网络(多少层,每层多少单元等)
  2. 通过前向传播算法可以计算出 h Θ ( x ) h_\Theta(x) hΘ(x),即拟合的式子
  3. 通过前向传播算法可以计算代价函数
  4. 通过前向后向传播算法可以计算代价函数偏导数
  5. 选择优化算法来优化代价函数,得到权重 Θ \Theta Θ,再代入到 h Θ ( x ) h_\Theta(x) hΘ(x)可以得到预测的y值

Octave/matlab代码

在课程练习4问题中,识别手写数字0-9,一共k=10个分类;
有5000个样本,每个样本图400个像素点,对应400个特征。

sigmoid和其偏导数函数

function [g] = sigmoid_test (z)
    g=1.0./(1.0+exp(-z));
endfunction
function [g] = sigmoidGrad (z)
  g=zeros(size(z));
  g=sigmoid_test(z).*(1-sigmoid_test(z));
endfunction

costfunc(计算代价函数,代价函数偏导数)

function [J,grad] = costfunc(X,y,input_layer_size,hidden_layer_size,output_layer_size,nn_para,lambda)
  %%costfunction and costfunction gradient
  
  %% add x0=1 to X
  m=size(X,1);
  X=[ones(m,1) X];%for every traning example, add x0=1;
  
  %%set y(5000,1)->y(5000,10)
  Y=[];
  E=eye(output_layer_size);
  for k=1:output_layer_size
    y0=find(y==k);
    Y(y0,:)=repmat(E(k,:),size(y0,1),1);%%将对应k=1的那些样本,都替换成[10000000...]
  end
  
  %%J(cost function)
  J=0;
  %%从两个theta参数矩阵存成了一个长的列向量,现在提取出来
  theta1=reshape(nn_para(1:hidden_layer_size*(input_layer_size+1)),hidden_layer_size,input_layer_size+1);
  theta2=reshape(nn_para(hidden_layer_size*(input_layer_size+1)+1:end),output_layer_size,hidden_layer_size+1);
  
  %forward propagation
  a1=X;
  z2=a1*theta1';
  a2=sigmoid(z2);
  a2=[ones(m,1) a2];
  z3=a2*theta2';
  a3=sigmoid(z3);
  h=a3;
  
  temp1=[zeros(size(theta1,1),1) theta1(:,2:end)];%%%%%%%theta(1,:)=0, for lambda regulation
  temp2=[zeros(size(theta2,1),1) theta2(:,2:end)];
  temp1=sum(temp1.^2);
  temp2=sum(temp2.^2);
  cost=Y.*log(h)+(1-Y).*log(1-h);
  J=-1/m*(sum(cost(:)))+lambda/(2*m)*(sum(temp1(:))+sum(temp2(:)));
  
  %%grad
  theta1_grad=zeros(size(theta1));
  theta2_grad=zeros(size(theta2));
  delta_1=zeros(size(theta1));
  delta_2=zeros(size(theta2));
  for i=1:m 
    %forward prop 
    a_1=X(i,:)';
    z_2=theta1*a_1;
    a_2=sigmoid(theta1*a_1);
    a_2=[1;a_2];
    z_3=theta2*a_2;
    a_3=sigmoid(z_3);
    
    %backward prop
    err_3=zeros(output_layer_size,1);
    for k=1:output_layer_size
      err_3(k)=a_3(k)-(y(i)==k);
    end
    err_2=theta2'*err_3; 
    err_2=err_2(2:end).*sigmoidGrad(z_2); %%%%%%%去掉第一项
    
    delta_1=delta_1+err_2*a_1';
    delta_2=delta_2+err_3*a_2';
  end
    theta1_temp=[zeros(size(theta1,1),1) theta1(:,2:end)]; %%%%%%%%%%%%将theta0都变为0
    theta2_temp=[zeros(size(theta2,1),1) theta2(:,2:end)];
    theta1_grad=1/m*delta_1+lambda/m*theta1_temp;
    theta2_grad=1/m*delta_2+lambda/m*theta2_temp;
    grad=[theta1_grad(:);theta2_grad(:)];
endfunction

Python代码

def sigmoid(z):
    return 1.0/(1.0+np.exp(-z))
def sigmoidGrad(z):
    return sigmoid(z)*(1-sigmoid(z))
def expand_y(y):
    res=[]
    for i in y:
        y_array=np.zeros(10)
        y_array[i-1]=1
        res.append(y_array)
    #encoder=OneHotEncoder(sparse=False)
    #y_onehot=encoder.fit_transform(y)
    #return y_onehot
    return np.array(res)
def serialize(a,b):
    return np.concatenate((np.ravel(a),np.ravel(b)))
def deserialize(seq,a1,a2,b1,b2):
    return seq[:a1*a2].reshape(a1,a2),seq[a1*a2:].reshape(b1,b2)
def feed_forward(nn_para,X,y,input_layer_size,hidden_layer_size,output_layer_size):
    theta1,theta2=deserialize(nn_para,hidden_layer_size,input_layer_size+1,output_layer_size,hidden_layer_size+1)
    a1=X
    z2=a1@theta1.T
    a2=sigmoid(z2)
    a2=np.insert(a2,0,values=np.ones(a2.shape[0]),axis=1)
    z3=a2@theta2.T
    a3=sigmoid(z3)
    h=a3
    
    theta1_temp=theta1[:,1:]
    theta2_temp=theta2[:,1:]
    reg=np.power(theta1_temp,2).sum()+np.power(theta2_temp,2).sum()
    return theta1,theta2,a1,a2,a3,z2,z3,h,reg
def cost(nn_para,X,y,input_layer_size,hidden_layer_size,output_layer_size,l):
    m=X.shape[0];
    theta1,theta2,a1,a2,a3,z2,z3,h,reg=feed_forward(nn_para,X,y,input_layer_size,hidden_layer_size,output_layer_size)
    c=y*np.log(h)+(1-y)*np.log(1-h)
    J=-1/m*c.sum()+l/(2*m)*reg
    return J
def back_forward(nn_para,X,y,input_layer_size,hidden_layer_size,output_layer_size,l):
    m=X.shape[0];
    theta1,theta2,a1,a2,a3,z2,z3,h,reg=feed_forward(nn_para,X,y,input_layer_size,hidden_layer_size,output_layer_size)

    delta1=np.zeros(theta1.shape)
    theta1_grad=np.zeros(theta1.shape)
    delta2=np.zeros(theta2.shape)
    theta2_grad=np.zeros(theta2.shape)
    for i in range(m):
        a1i=np.array([a1[i,:]]).T
        z2i=np.array([z2[i,:]]).T
        a2i=np.array([a2[i,:]]).T
        hi=np.array([h[i,:]]).T
        yi=np.array([y[i,:]]).T

        err3=hi-yi

        err2=(theta2.T)@err3
        err2=err2[1:]
        err2=err2*sigmoidGrad(z2i)

        delta1=delta1+err2*a1i.T
        delta2=delta2+err3*a2i.T

    theta1_temp=np.insert(theta1[:,1:],0,values=np.zeros(theta1.shape[0]),axis=1)
    theta2_temp=np.insert(theta2[:,1:],0,values=np.zeros(theta2.shape[0]),axis=1)
    theta1_grad=1/m*delta1+l/m*theta1_temp
    theta2_grad=1/m*delta2+l/m*theta2_temp

    return serialize(theta1_grad,theta2_grad)

注意:1. python中,矩阵元素与元素相乘为*或者np.multiply,矩阵相乘为@或者np.dot
2.a一维数组a.shape 返回为(x,)与(x,1) 意义完全不同,
要通过np.array(a).reshape(5,1)转换为而为矩阵,再进行矩阵运算,否则运算会出现维度不一致
未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值