DNN_机器学习[通俗易懂]

DNN_机器学习[通俗易懂]前言:深度神经网络(DeepNeuralNetworks,以下简称DNN),相对BP,增加了隐藏层的层次在CNN相当于全连接层

前言:

 

    深度神经网络(Deep Neural Networks, 以下简称DNN),相对BP,增加了隐藏层的层次

在CNN相当于全连接层。

  参考文档  https://www.cnblogs.com/pinard/p/6418668.html

 

这里主要给出代码实现

 


一  目录

  1.      常用损失函数和激活函数
  2.      代码实现

一   常用损失函数和激活函数

 

       常用损失函数有三种

       1.1  方差

                      J = \frac{1}{2}||a^L-y||^2

                     导数:

                      a^L-y

        1.2  对数似然

                       J= \sum_k y_k ln a_k^L

                       导数

                          \frac{1}{a_K^L}

       1.3  交叉熵

                    J=-(ylna+(1-y)ln(1-a))

                    导数

                    -\frac{y}{a^L}+\frac{1-y}{1-a^L}

 

     

 


      激活函数:

      sigmoid 函数

              a = \frac{1}{1+e^{-z}}

             导数

               a(1-a)

 

       softmax 函数

            a_i^L = \frac{e^{z_i^L}}{\sum_{j=1}^{n}e^{z_j^L}}

           导数

             a_i^L(1-a_i^L)

 

       tanh 函数

                 a^L=\frac{e^z-e^{-z}}{e^{z}+e^{-z}}

        导数:

                   1-(a^L)^2

             

损失函数 激活函数
方差 sigmoid
方差 tanh
交叉熵 sigmoid
对数似然 softmax
   

二   代码实现

 

  

# -*- coding: utf-8 -*-
"""
Created on Tue Apr 14 17:24:24 2020

@author: chengxf2
"""

import numpy as np
import matplotlib.pyplot as plt
import copy
from sklearn.datasets import load_iris


class DNN:
    
    
    def Perdict(self,X, labelArr,L):
        
        for i in range(L-1):#[0,1,2,3]
            wL = self.W[i]
            bL = self.B[i] 
            aL_pre = self.A[i] #前一层的输入
            

            zL = np.dot(wL,aL_pre)+bL
            aL = self.SigMoid(zL)
            self.Z[i] = zL
            self.A[i+1]= aL
        
        a_out = self.A[-1] #最终分类结果
        n,m = np.shape(a_out)
        print("\n n: ",n,"\t m: ",m)
        err = 0
        for i in range(m):
            
            pred_y = np.argmax(a_out[:,i])
            true_y = labelArr[i]
            
           # print("\n a ",pred_y, "true_y ",true_y)
            if pred_y != true_y:
                err+=1
        print("\n err::::: ",err)
            
    
    
    """
    转换编码
    Args
      n: 输出节点
      m: 样本总数
    return 
      X: n,m
      Y: [0,1,2]
    """
    def LoadData(self):
        
        iris = load_iris()
        
        x = iris.data
        y = iris.target
        
        #print("x ",x)
        #print("\n y ",y)
        
        return x.T, y
    
    """
    转换编码
    Args
      n: 输出节点
      m: 样本总数
    return 
      oneY
    """
    def OneHot(self, Y,n,m):
        
        oneY = np.zeros((n,m))
    
        for i in range(m):
            index = Y[i]
            oneY[index,i]= 1.0
        #print("\n oneY ",oneY)   
        return oneY
        
        
        
    
    """
    初始化各个参数
    Args
      sp :网路结构
      m: 样本个数,n样本维度
      x: 样本 
      
    
    """
    def InitPara(self, sp,x):
        
        L = len(sp)
        n,m = np.shape(x) 
        
        
      
        self.A.append(x) #第一个作为输入
        for i in range(0,L-1):

            n2 = sp[i+1] #当前的神经元个数
            n1 = sp[i] #前一层的输入个数
            w = np.random.random((n2,n1)) #权重系数
            b = np.random.random((n2,1)) #当前层的偏置值
            z = np.zeros((n2,m)) #神经元的输入
            a = np.zeros((n2,m)) #神经元的输出
            theta = np.zeros((n2,m)) #灵敏度
            

            self.W.append(w)
            self.B.append(b)
            self.A.append(a)
            self.Z.append(z)
            self.Theta.append(theta)
            
        #print("\n len ",len(self.Theta))
            
            
  
    """
    激活函数
    Args
       z: 神经元的输入单元
    return 
       a: 神经元的输出单元
    """
    def SigMoid(self, z):
        
        a = 1.0/(1.0+np.exp(-z))
        
        return a
        
    """
    初始化
    """
    def __init__(self, sp=[3,4,2,2]):
        
        self.W = []  #权重系数;长度为L-1
        self.B = [] # 偏置;长度为L-1
        self.A = []  #各个神经元输出;长度为L,包含数据X
        self.Z = [] # 各神经元的输入;长度为L-1
        self.Theta = [] #灵敏度;长度为L-1,对Z的梯度
        
        self.maxIter = 10000 #最大迭代次数
        self.thre = 0.03  #每次参数变化
        self.alpha = 0.01 #学习率;可以用样本1/m
        self.L =0; #网络层数;包含输入层X
        
    """
    前向传播.计算误差
    Args
       X: 输入的样本 [n,m]
       y: 标签输出[n_out,m]
       wL: 每一层的偏置
       bL: 当前层神经元的偏置值
       zL: 神经元的输入
       aL: 神经元的输出
       L: 长度
    return 
        None
    """
    def Forward(self, X,Y,L):
        
        for i in range(L-1):
            wL = self.W[i]
            bL = self.B[i] 
            aL_pre = self.A[i] #前一层的输入
            

            zL = np.dot(wL,aL_pre)+bL
            aL = self.SigMoid(zL)
            self.Z[i] = zL
            self.A[i+1]= aL
        
        a = self.A[-1] #最终分类结果
        m,n = np.shape(a)
        return None
    
    """
    参数变更
    Args
      w_old: 更新前参数
      w_new: 更新后参数
    return
      w_sum: 总的更新参数
    """
    def ParaChange(self, w_old, w_new):
        
        L = len(w_new)
        
        w_sum = 0.0
        
        for i in range(L):
            w1 = w_old[i]
            w2 = w_new[i]
            w = w1-w2
            w.flatten()
           
        
            
            w_sum+=np.linalg.norm(w,2)
            
        #print("\n w_change",w_sum)
    
    
    """
    反向传播算法
    Args
       Y: 标签
       L: 总的层数减1,为了方便计算
    """
    def BackWard(self,Y, L):
        
        w_old = copy.deepcopy(self.W) #保存原来的参数
        
        aL = self.A[-1]  #最终输出
        dz = np.multiply(aL,1.0-aL) #最后一层的
        thetaL =np.multiply(aL-Y,dz) #当前层的z的灵敏度
        self.Theta[-1]=thetaL  #更新当前的灵敏度
        
      
        
        aL_pre = self.A[L-1] #前一层的输入
      
        #先更新最后一层
        self.B[-1] = self.B[-1]-self.alpha*np.sum(thetaL,axis=0)
        self.W[-1]=  self.W[-1]-self.alpha*np.dot(thetaL, aL_pre.T)
        #print("\n new W: ",W)
       
     

        
        for j in range(L-1,0,-1): #[2,1] 最后一层已经更新过了
           
            
         
            theta_Next = self.Theta[j]  #前一层的灵敏度
            w_Next = w_old[j]           # 前一层网络的权重系数
            
            a_L =   self.A[j] #当前层的输出,多了一个0层
            a_Pre = self.A[j-1] #前一层
            dz = np.multiply(a_L,1.0-a_L)
            
            
            theta_L = np.multiply(np.dot(w_Next.T, theta_Next),dz)

            
            #更新参数
            w = w_old[j-1]- self.alpha*np.dot(theta_L,a_Pre.T) #需要更新的
            self.Theta[j-1] = theta_L 
            
            
            self.B[j-1] = self.B[j-1]-self.alpha*np.sum(theta_L,axis=0)
            self.W[j-1] = w
            
        #print("\n w",self.W)
        self.ParaChange(w_old, self.W)
            
           
 
            
            

        
    
    
    """
    训练
    Args
       X: 样本(n,m) n: 样本维度 m: 样本数量 列向量
       Y: OneHot格式 [n_out,m] 
       sp: 各层神经元个数;
    """
    def fit(self, X,Y,sp =[4,8,4,3]):
        
        self.L = len(sp)
        self.InitPara(sp,X)
        
        nOut = sp[-1]
        n,m = np.shape(X)
        

        Y = self.OneHot(Y,nOut,m)
        
       
        
     
        
        for i in range(self.maxIter):
            #print("\n i::::::::::::::::",i)
            self.Forward(X,Y,self.L)
            self.BackWard(Y,self.L-1)
            
          
            
            
'''        
X = np.array([[0.1,0.1,0.1],
              [0.2,0.2,0.2],
              [0.2,0.2,0.2],
              [0.2,0.2,0.2]])
    
#Y = [1,0,1,0]
'''
dnn = DNN()
X,Y =dnn.LoadData()
dnn.fit(X,Y)

#print("\n sp ",np.shape(X)) #[4,150]


print("\n end ------------\n")

dnn.Perdict(X[:,0],Y,4)

        
        

迭代次数大于5000次,错误率会迅速降低为0 

迭代次数越小,错误率越高

今天的文章DNN_机器学习[通俗易懂]分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/66230.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注