DNN_机器学习

前言:

 

    深度神经网络(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 

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个表达式是计算二分类(通常涉及机器学习中的预测模型,如DNN,即深度神经网络)中模型的准确率(Accuracy)。其中: - TP (True Positive): 真正例,预测为正且实际为正的样本数。 - TN (True Negative): 真负例,预测为负且实际为负的样本数。 - FP (False Positive): 假正例,预测为正但实际为负的样本数。 - FN (False Negative): 假负例,预测为负但实际为正的样本数。 公式 `(TP_DNN + TN_DNN) / (TP_DNN + TN_DNN + FP_DNN + FN_DNN)` 就是将正确预测(TP和TN)的总数除以所有预测总数(包括正确和错误预测),得到分类器在给定数据集上的准确率。 为了增加一个固定的阈值为0.5(通常用于二元分类问题中的概率阈值决策),我们通常会这样操作: 1. 对于模型输出的概率或预测概率进行比较。如果预测概率大于等于0.5,我们可以将其分类为正例(例如1),否则为负例(例如0)。 2. 计算新的TP、TN、FP和FN,基于新的分类标准。 这是一个示例代码片段: ```python # 假设model_output是DNN模型的输出概率列表 threshold = 0.5 new_predictions = [1 if prob >= threshold else 0 for prob in model_output] # 更新计数 TP_new = sum([1 for pred, actual in zip(new_predictions, labels) if pred == 1 and actual == 1]) TN_new = sum([1 for pred, actual in zip(new_predictions, labels) if pred == 0 and actual == 0]) FP_new = sum([1 for pred, actual in zip(new_predictions, labels) if pred == 1 and actual == 0]) FN_new = sum([1 for pred, actual in zip(new_predictions, labels) if pred == 0 and actual == 1]) # 新的精度计算 accuracy_DNN_thresholded = (TP_new + TN_new) / (TP_new + TN_new + FP_new + FN_new) print(f"Accuracy with 0.5 threshold: {accuracy_DNN_thresholded}") ``` 这里`labels`是对应的实际标签列表,`model_output`是模型预测的概率输出。这个新精度值就是基于0.5阈值后的模型性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值