前言:
深度神经网络(Deep Neural Networks, 以下简称DNN),相对BP,增加了隐藏层的层次
在CNN相当于全连接层。
参考文档 https://www.cnblogs.com/pinard/p/6418668.html
这里主要给出代码实现
一 目录
- 常用损失函数和激活函数
- 代码实现
一 常用损失函数和激活函数
常用损失函数有三种
1.1 方差
导数:
1.2 对数似然
导数
1.3 交叉熵
导数
激活函数:
sigmoid 函数
导数
a(1-a)
softmax 函数
导数
tanh 函数
导数:
损失函数 | 激活函数 |
方差 | 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