神经网络进阶

一、基本结构

请添加图片描述
​ 一个简单的两层神经网络的基本结构分为三层:输入层(一般不考虑在内,是数据的样本特征)、隐藏层(包含3个神经元,神经元用⚪表示,神经元是一个非线性单元)、输出层(包含一个神经元,也用⚪表示)。

​ 每个神经元的数学运算一般由两部分组成:线性部分和非线性部分,计算公式如下:
{ z = w 1 x 1 + w 2 x 2 + b a = g ( z ) \{{z=w_1x_1+w_2x_2+b \atop a=g(z)} {a=g(z)z=w1x1+w2x2+b
其中, z = w 1 x 1 + w 2 x 2 + b z=w_1x_1+w_2x_2+b z=w1x1+w2x2+b表示线性运算, a = g ( z ) a=g(z) a=g(z)表示非线性运算,又称激活函数。

二、前向传播

  1. 神经网络前向传播过程,即神经网络从输入层到输出层的计算过程(仍以上例为例,上标表示当前神经网络层数,下标表示当前层的第几个神经单元):

    从输入层到隐藏层:
    { z 1 [ 1 ] = w 1 [ 1 ] x + b 1 [ 1 ] , a 1 [ 1 ] = g ( z 1 [ 1 ] ) z 2 [ 1 ] = w 2 [ 1 ] x + b 2 [ 1 ] , a 2 [ 1 ] = g ( z 2 [ 1 ] ) z 3 [ 1 ] = w 3 [ 1 ] x + b 3 [ 1 ] , a 3 [ 1 ] = g ( z 3 [ 1 ] ) \{{z^{[1]}_1=w^{[1]}_1x+b^{[1]}_1,a^{[1]}_1=g(z^{[1]}_1) \atop {{z^{[1]}_2=w^{[1]}_2x+b^{[1]}_2,a^{[1]}_2=g(z^{[1]}_2)} \atop {z^{[1]}_3=w^{[1]}_3x+b^{[1]}_3,a^{[1]}_3=g(z^{[1]}_3)}}} {z3[1]=w3[1]x+b3[1],a3[1]=g(z3[1])z2[1]=w2[1]x+b2[1],a2[1]=g(z2[1])z1[1]=w1[1]x+b1[1],a1[1]=g(z1[1])
    从隐藏层到输出层:
    z [ 2 ] = w 1 [ 2 ] a [ 1 ] + b 1 [ 2 ] , a [ 2 ] = g ( z [ 2 ] ) z^{[2]}=w^{[2]}_1a^{[1]}+b^{[2]}_1,a^{[2]}=g(z^{[2]}) z[2]=w1[2]a[1]+b1[2],a[2]=g(z[2])

  2. 上式改为针对m个样本的情况,可以写成矩阵运算形式:

    从输入层到隐藏层:
    { Z [ 1 ] = W [ 1 ] X + b [ 1 ] A [ 1 ] = g ( Z [ 1 ] ) \{{Z^{[1]}=W^{[1]}X+b^{[1]} \atop A^{[1]}=g(Z^{[1]})} {A[1]=g(Z[1])Z[1]=W[1]X+b[1]
    从隐藏层到输出层:
    { Z [ 2 ] = W [ 2 ] X [ 1 ] + b [ 2 ] A [ 2 ] = g ( Z [ 2 ] ) \{{Z^{[2]}=W^{[2]}X^{[1]}+b^{[2]} \atop A^{[2]}=g(Z^{[2]})} {A[2]=g(Z[2])Z[2]=W[2]X[1]+b[2]

三、激活函数

非线性运算在神经元中一般由激活函数来实现,激活函数同一表示成g(z),以下是几个常见的激活函数:

  1. Sigmoid函数:如果神经元采用Sigmoid函数作为激活函数,那么单个神经元实现的功能就相当于逻辑回归。缺点:当|z|很大时,激活函数的梯度很小,因此在这个区域内梯度下降算法会运行的较慢,应尽量避免|z|落在这个区域,应尽可能将|z|限定在0附近,从而提高梯度下降算法的运算速度。
    a = 1 1 + e − z a=\frac{1}{1+e^{-z}} a=1+ez1 请添加图片描述

  2. tanh函数:是双曲正切函数。缺点同Sigmoid函数。
    a = e z − e − z e z + e − z a=\frac{e^z-e^{-z}}{e^z+e^{-z}} a=ez+ezezez
    请添加图片描述

  3. ReLU函数:修正线性单元,是分段函数。最大的特点就是在z>0时梯度恒为1,保证了网络训练时梯度下降的速度,但是缺点是在z<=0时,梯度为0,此时神经元不工作(实际应用中证明,这种情况影响并不大)。
    a = m a x ( 0 , z ) a=max(0,z) a=max(0,z)
    请添加图片描述

  4. Leaky ReLU函数:是ReLU函数的改进,两者区别仅在于当z<=0时,a不恒为0,而是有一个较小的梯度(大小不唯一),这样做的好处时始终保持梯度不为0。
    a = m a x ( 0.01 z , z ) a=max(0.01z,z) a=max(0.01z,z)
    请添加图片描述

  5. 选择合适的激活函数的方法:

    1. 对于隐藏层的激活函数:一般来说tanh函数好于Sigmoid函数,因为tanh函数取值范围在[-1,+1],隐藏层的输出线性在[-1,+1]可以看成是在0值附近分布,均值为0,这样从隐藏层到输出层,数据达到了归一化(*****************)。为了弥补Sigmoid函数和tanh函数的缺点,选择ReLU函数能够保证在z>0时梯度始终为1,从而提高神经网络梯度下降算法的运行速度。进一步弥补ReLU函数的缺点,出现了LeaKy ReLU函数。
    2. 对于输出层的激活函数,因为二分问题的输出取值为{0,1},所以一般会选择Sigmoid函数作为激活函数。
    3. 如果是预测问题(***********************)而非分类问题,在输出是连续值的情况下,输出层的激活函数可以使用线性函数。如果输出恒为正值,也可以使用ReLU激活函数。
  6. 非线性激活函数:根据上述的公式,有下列(因为是线性的,激活函数简化为a=z)展开,这表明如果使用线性激活函数,输出仍是输入的线性组合,即使是包含多层隐藏层的神经网络,只要激活函数是线性的,最终的输出仍然是线性模型,神经网络就没有任何作用了。因此激活函数必须是非线性的。
    A [ 2 ] = Z [ 2 ] = W [ 2 ] A [ 1 ] + b [ 2 ] = W [ 2 ] Z [ 1 ] + b [ 2 ] = W [ 2 ] ( W [ 1 ] X + b [ 1 ] ) + b [ 2 ] = ( W [ 2 ] W [ 1 ] ) X + ( + W [ 2 ] b [ 1 ] + b [ 2 ] ) = W ‘ X + b ‘ A^{[2]}=Z^{[2]}=W^{[2]}A^{[1]}+b^{[2]}=W^{[2]}Z^{[1]}+b^{[2]}=W^{[2]}(W^{[1]}X+b^{[1]})+b^{[2]}=(W^{[2]}W^{[1]})X+(+W^{[2]}b^{[1]}+b^{[2]})=W^`X+b^` A[2]=Z[2]=W[2]A[1]+b[2]=W[2]Z[1]+b[2]=W[2](W[1]X+b[1])+b[2]=(W[2]W[1])X+(+W[2]b[1]+b[2])=WX+b
    如果所有隐藏层都使用线性激活函数,只有输出层使用非线性激活函数,那么整个神经网络的结构就类似于一个简单的逻辑回归模型,相当于只使用一个神经元。

四、反向传播

  1. 神经网络经过前向传播后,接下来可以计算其损失函数。神经网络二分类问题与逻辑回归一样,采用交叉熵损失:
    J = − 1 m ∑ y ( i ) l o g a [ 2 ] ( i ) + ( 1 − y ( i ) ) l o g ( 1 − a [ 2 ] ( i ) ) J=-\frac{1}{m}\sum y^{(i)}log a^{[2](i)}+(1-y^{(i)})log(1-a^{[2](i)}) J=m1y(i)loga[2](i)+(1y(i))log(1a[2](i))

  2. 计算交叉熵损失后,就可以及逆行神经网络的反向传播了。反向传播是对神经网络输出层、隐藏层的参数W和b计算偏导数的过程。

  3. 神经网络代价函数J对 Z [ 2 ] Z^{[2]} Z[2]的偏导数:(*****************************)
    d Z [ 2 ] = A [ 2 ] − Y dZ^{[2]}=A^{[2]}-Y dZ[2]=A[2]Y
    根据求偏导法则计算其他偏导数,输出层:
    { d W [ 2 ] = d Z [ 2 ] ⋅ ∂ Z [ 2 ] ∂ W [ 2 ] = 1 m ( A [ 2 ] − Y ) A [ 1 ] T d b [ 2 ] = 1 m ∑ d Z [ 2 ] ( i ) \{{{dW^{[2]}=dZ^{[2]}·\frac{∂Z^{[2]}}{∂W^{[2]}}}=\frac{1}{m}(A^{[2]}-Y)A^{[1]T} \atop db^{[2]}=\frac{1}{m}\sum dZ^{[2](i)}} {db[2]=m1dZ[2](i)dW[2]=dZ[2]W[2]Z[2]=m1(A[2]Y)A[1]T
    隐藏层:
    { d Z [ 1 ] = d Z [ 2 ] ⋅ ∂ Z [ 2 ] ∂ A [ 1 ] ⋅ ∂ A [ 1 ] ∂ Z [ 1 ] = W [ 2 ] T d Z [ 2 ] ∗ g ‘ ( Z [ 1 ] ) d W [ 1 ] = d Z [ 1 ] ⋅ ∂ Z [ 1 ] ∂ W [ 1 ] = 1 m d Z [ 1 ] X T d b [ 1 ] = 1 m ∑ d Z [ 1 ] ( i ) \{{dZ^{[1]}=dZ^{[2]}·\frac{∂Z^{[2]}}{∂A^{[1]}}·\frac{∂A^{[1]}}{∂Z^{[1]}}=W^{[2]T}dZ^{[2]}*g^`(Z^{[1]}) \atop {dW^{[1]}=dZ^{[1]}·\frac{∂Z^{[1]}}{∂W^{[1]}}=\frac{1}{m}dZ^{[1]}X^T \atop db^{[1]}=\frac{1}{m}\sum dZ^{[1](i)}}} {db[1]=m1dZ[1](i)dW[1]=dZ[1]W[1]Z[1]=m1dZ[1]XTdZ[1]=dZ[2]A[1]Z[2]Z[1]A[1]=W[2]TdZ[2]g(Z[1])
    其中*表示点乘,`表示激活函数的导数。

  4. 总结:请添加图片描述

五、更新参数

完成反向传播后得到了各层的参数梯度dW和db,接下来需要根据梯度下降算法对参数W和b进行更新。
{ W [ 1 ] = W [ 1 ] − η ⋅ d W [ 1 ] b [ 1 ] = b [ 1 ] − η ⋅ d b [ 1 ] W [ 2 ] = W [ 2 ] − η ⋅ d W [ 2 ] b [ 2 ] = b [ 2 ] − η ⋅ d b [ 2 ] \{{{W^{[1]}=W^{[1]}-\eta·dW^{[1]} \atop b^{[1]}=b^{[1]}-\eta·db^{[1]}} \atop {W^{[2]}=W^{[2]}-\eta·dW^{[2]} \atop b^{[2]}=b^{[2]}-\eta·db^{[2]}}} {b[2]=b[2]ηdb[2]W[2]=W[2]ηdW[2]b[1]=b[1]ηdb[1]W[1]=W[1]ηdW[1]
至此经过前向传播、反向传播、更新参数后,神经网络的一次训练就完成了。

六、初始化

​ 神经网络中的参数W和b的初始化,在逻辑回归模型中,参数W和b一般全部初始化为0即可,**神经网络中却不能这样做!**因为如果初始化为0,那么隐藏层各个神经元的dW都一样,这样会导致隐藏层3个神经元对应的权重每次迭代更新都会得到完全相同的结果,造成隐藏层3个神经元完全对称,效果相同,隐藏层多个神经元就没有意义了。

​ 因此神经网络的权重系数W一般不会初始化为零,可以进行**随机初始化。**但是偏置项系数b一般可以初始化为0,不会影响神经网络的训练效果。

七、神经网络的Python实现

  1. 准备数据:采用与上一节中相同的数据集。

  2. 参数初始化:按照第六部分的初始化方式进行:

    def initialize_parameters(n_x, n_h, n_y):
    	"""
    	函数输入:
    		n_x:输入层维度
    		n_h:隐藏层神经元个数
    		n_y:输出层神经元个数
    	函数输出;
    		params:存储参数的字典,W1,b1, W2, b2
    	"""
    	np.random.seed(0)   #设置随机种子
    	#参数初始化
    	W1 = np.random.randn(n_h, n_x)
     	b1 = np.zeros((n_h, 1))
    	W2 = np.random.randn(n_y, n_h)
    	b2 = np.zeros((n_y, 1))
    	parameters = {
    		'W1':W1,
    		'b1':b1,
    		'W2':W2,
    		'b2':b2
    	}
    	return parameters
    
  3. 前向传播:隐藏层的激活函数选择tanh函数(NumPy中自带),输出层的激活函数选择Sigmoid函数。

    def sigmoid(z):
    	"""
    	函数输入:
    		z:激活函数输入,神经元线性输出
    	函数输出:
    		a:激活函数输出,神经元非线性输出
    	"""
    	a = 1/(1+np.exp(-z))
    	return a
    
    
    #定义前向传播
    def forward_propagation(X, parameters):
    	"""
    	函数输入:
    		X:神经网络输入
    		cache:神经网络参数
    	函数输出:
    		A2:神经网络输出
    		cache:缓存,存储中间变量:Z1, A1, Z2, A2
    	"""
    	#神经网络参数
    	W1 = parameters['W1']
    	b1 = parameters['b1']
    	W2 = parameters['W2']
    	b2 = parameters['b2']
    	#输入层->隐藏层
    	Z1 = np.dot(W1, X) + b1
    	A1 = np.tanh(Z1)
    	#隐藏层->输出层
    	Z2 = np.dot(W2, A1) + b2
    	A2 = sigmoid(Z2)
    	cache={
    		'Z1':Z1,
    		'A1':A1,
    		'Z2':Z2,
    		'A2':A2
    	}
    	return A2,cache
    
  4. 交叉熵损失:与上一节中逻辑回归一样。

    def compute_loss(A2, Y):
    	"""
    	函数输入:
    		A2:神经网络输出
    		Y:样本真实标签
    	函数输出:
    		cost:神经网络交叉熵损失
    	"""
    	#样本个数
    	m = Y.shape[1]
    	cross_entropy = -(Y*np.log(A2)+(1-Y)*np.log(1-A2))
    	cost = 1.0/m*np.sum(cross_entropy)
    	return cost
    
  5. 反向传播:

    def back_propagation(X, Y, parameters, cache):
    	"""
    	函数输出:
    		X:神经网络输入
    		Y:样本真实标签
    		parameters:网络参数
    		cache:缓存,存储中间变量:Z1, A1, Z2, A2
    	函数输入:
    		grads:神经网络参数梯度
    	"""
    	#样本个数
    	m = X.shape[1]
    	#神经网络参数
    	W1 = parameters['W1']
    	b1 = parameters['b1']
    	W2 = parameters['W2']
    	b2 = parameters['b2']
    	#中间变量
    	Z1 = cache['Z1']
    	A1 = cache['A1']
    	Z2 = cache['Z2']
    	A2 = cache['A2']
    	#计算梯度
    	dZ2 = A2 -Y
    	dW2 = 1.0/m*np.dot(dZ2, A1.T)
    	db2 = 1.0/m*np.sum(dZ2, axis=1, keepdims=True)
    	dZ1 = np.dot(W2.T, dZ2)*(1-np.power(A1, 2))
    	dW1 = 1.0/m*np.dot(dZ1, X.T)
    	db1 = 1.0/m*np.sum(dZ1, axis=1, keepdims=True)
    	grads = {
    		'dW1':dW1,
    		'db1':db1,
    		'dW2':dW2,
    		'db2':db2
    	}
    	return grads
    
  6. 更新参数:根据梯度下降算法更新参数。

    def update_parameters(parameters, grads, learning_rate=0.1):
    	"""
    	函数输出:
    		parameters:网络参数
    		grads:神经网络参数梯度
    	函数输入:
    		parameters:网络参数
    	"""
    	#神经网络参数
    	W1 = parameters['W1']
    	b1 = parameters['b1']
    	W2 = parameters['W2']
    	b2 = parameters['b2']
    	#神经网络参数梯度
    	dW1 = grads['dW1']
    	db1 = grads['db1']
    	dW2 = grads['dW2']
    	db2 = grads['db2']
    	#梯度下降算法
    	W1 = W1-learning_rate*dW1
    	b1 = b1-learning_rate*db1
    	W2 = W2-learning_rate*dW2
    	b2 = b2-learning_rate*db2
    	parameters = {
    		'W1':W1,
    		'b1':b1,
    		'W2':W2,
    		'b2':b2
    	}
    	return parameters
    
  7. 构建整个神将网络模型:将前面定义的几个模块整合起来。

    def nn_model(X, Y, n_h=3, num_iterations=200, learning_rate=0.1):
    	"""
    	函数输入:
    		X:神经网络输入
    		Y:样本真实标签
    		n_h:隐藏层神经元个数
    		num_iterations:训练次数
    		learning_rate:学习率
    	函数输出:
    		parameters:训练完成后的网络参数
    	"""
    	#定义网络
    	n_x=X.shape[0]
    	n_y=1
    	#参数初始化
    	parameters = initialize_parameters(n_x, n_h,n_y)
    	#迭代训练
    	for i in range(num_iterations):
    		#正向传播
    		A2, cache = forward_propagation(X, parameters)
    		#计算交叉熵损失
    		cost = compute_loss(A2, Y)
    		#反向传播
    		grads = back_propagation(X, Y, parameters, cache)
    		#更新参数
    		parameters = update_parameters(parameters, grads, learning_rate)
    		#print
    		if (i+1)%20==0:
    			print('Iteration:%d, cost=%f'%(i+1, cost))
    	return parameters
    
  8. 训练:选择隐藏层神经元个数为3,迭代训练次数为500,学习率设置为0.2。

    parameters = nn_model(X, Y, n_h=3, num_iterations=500, learning_rate=0.2)
    
  9. 预测:使用模型对数据集进行分类。

    def predict(X, parameters):
    	"""
    	函数输入:
    		X:神经网络输入
    		parameters:训练完成后的网络参数
    	函数输出:
    		Y_pred:预测样本标签
    	"""
    	#神经网络参数
    	W1 = parameters['W1']
    	b1 = parameters['b1']
    	W2 = parameters['W2']
    	b2 = parameters['b2']
    	#输入层->隐藏层
    	Z1 = np.dot(W1, X)+b1
    	A1 = np.tanh(Z1)
    	#隐藏层->输出层
    	Z2 = np.dot(W2, A1)+b2
    	A2 = sigmoid(Z2)
    	#预测标签
    	Y_pred = np.zeros((1,X.shape[1]))   #初始化Y_pred
    	Y_pred[A2 > 0.5]=1   #Y_hat大于0.5的预测为正值(输出层使用的Sigmoid)
    	return Y_pred
    
    
    #对数据及进行预测,并计算准确率
    accuracy = np.mean(Y_pred == Y)
    print(accuracy)
    

    还可以绘制决策边界,可视化分类效果:

    from matplotlib.colors import ListedColormap
    
    x_min, x_max = X[0, :].min() - 0.5,X[0, :].max() + 0.5
    y_min, y_max = X[1, :].min() - 0.5,X[1, :].max() + 0.5
    step = 0.001
    xx,yy=np.meshgrid(np.arange(x_min,x_max,step),np.arange(y_min,y_max,step))
    Z = predict(np.c_[xx.ravel(),yy.ravel()].T,parameters)
    Z = Z.reshape(xx.shape)
    plt.contourf(xx,yy,Z,cmap=plt.cm.Spectral)   #绘制边界
    #负类
    plt.scatter(X[0,Y[0,:]==0],X[1,Y[0,:]==0],c='g',marker='s',label='负类')
    #正类
    plt.scatter(X[0,Y[0,:]==1],X[1,Y[0,:]==1],c='y',marker='o',label='正类')
    plt.legend()
    plt.show()
    
  10. 全部代码:

    import sklearn.datasets
    import numpy as np
    from matplotlib.colors import ListedColormap
    import matplotlib.pyplot as plt
    
    np.random.seed(1)   #设置随机种子
    #导入make_moon数据集,样本个数m=200,噪声标准差为0.2
    X, Y = sklearn.datasets.make_moons(n_samples=200, noise=.2)
    #X shape:[2, 200], Y shape:[1, 200]
    X, Y = X.T, Y.reshape(1, Y.shape[0])
    #负类
    plt.scatter(X[0, Y[0,:]==0],X[1, Y[0,:]==0], c='r', marker='s')
    #正类
    plt.scatter(X[0, Y[0,:]==1],X[1, Y[0,:]==1], c='b', marker='o')
    plt.show()
    
    def initialize_parameters(n_x, n_h, n_y):
    	"""
    	函数输入:
    		n_x:输入层维度
    		n_h:隐藏层神经元个数
    		n_y:输出层神经元个数
    	函数输出;
    		params:存储参数的字典,W1,b1, W2, b2
    	"""
    	np.random.seed(0)   #设置随机种子
    	#参数初始化
    	W1 = np.random.randn(n_h, n_x)
    	b1 = np.zeros((n_h, 1))
    	W2 = np.random.randn(n_y, n_h)
    	b2 = np.zeros((n_y, 1))
    	parameters = {
    		'W1':W1,
    		'b1':b1,
    		'W2':W2,
    		'b2':b2
    	}
    	return parameters
    
    def sigmoid(z):
    	"""
    	函数输入:
    		z:激活函数输入,神经元线性输出
    	函数输出:
    		a:激活函数输出,神经元非线性输出
    	"""
    	a = 1/(1+np.exp(-z))
    	return a
    
    #定义前向传播
    def forward_propagation(X, parameters):
    	"""
    	函数输入:
    		X:神经网络输入
    		cache:神经网络参数
    	函数输出:
    		A2:神经网络输出
    		cache:缓存,存储中间变量:Z1, A1, Z2, A2
    	"""
    	#神经网络参数
    	W1 = parameters['W1']
    	b1 = parameters['b1']
    	W2 = parameters['W2']
    	b2 = parameters['b2']
    	#输入层->隐藏层
    	Z1 = np.dot(W1, X) + b1
    	A1 = np.tanh(Z1)
    	#隐藏层->输出层
    	Z2 = np.dot(W2, A1) + b2
    	A2 = sigmoid(Z2)
    	cache={
    		'Z1':Z1,
    		'A1':A1,
    		'Z2':Z2,
    		'A2':A2
    	}
    	return A2,cache
    
    def compute_loss(A2, Y):
    	"""
    	函数输入:
    		A2:神经网络输出
    		Y:样本真实标签
    	函数输出:
    		cost:神经网络交叉熵损失
    	"""
    	#样本个数
    	m = Y.shape[1]
    	cross_entropy = -(Y*np.log(A2)+(1-Y)*np.log(1-A2))
    	cost = 1.0/m*np.sum(cross_entropy)
    	return cost
    
    def back_propagation(X, Y, parameters, cache):
    	"""
    	函数输出:
    		X:神经网络输入
    		Y:样本真实标签
    		parameters:网络参数
    		cache:缓存,存储中间变量:Z1, A1, Z2, A2
    	函数输入:
    		grads:神经网络参数梯度
    	"""
    	#样本个数
    	m = X.shape[1]
    	#神经网络参数
    	W1 = parameters['W1']
    	b1 = parameters['b1']
    	W2 = parameters['W2']
    	b2 = parameters['b2']
    	#中间变量
    	Z1 = cache['Z1']
    	A1 = cache['A1']
    	Z2 = cache['Z2']
    	A2 = cache['A2']
    	#计算梯度
    	dZ2 = A2 -Y
    	dW2 = 1.0/m*np.dot(dZ2, A1.T)
    	db2 = 1.0/m*np.sum(dZ2, axis=1, keepdims=True)
    	dZ1 = np.dot(W2.T, dZ2)*(1-np.power(A1, 2))
    	dW1 = 1.0/m*np.dot(dZ1, X.T)
    	db1 = 1.0/m*np.sum(dZ1, axis=1, keepdims=True)
    	grads = {
    		'dW1':dW1,
    		'db1':db1,
    		'dW2':dW2,
    		'db2':db2
    	}
    	return grads
    
    def update_parameters(parameters, grads, learning_rate=0.1):
    	"""
    	函数输出:
    		parameters:网络参数
    		grads:神经网络参数梯度
    	函数输入:
    		parameters:网络参数
    	"""
    	#神经网络参数
    	W1 = parameters['W1']
    	b1 = parameters['b1']
    	W2 = parameters['W2']
    	b2 = parameters['b2']
    	#神经网络参数梯度
    	dW1 = grads['dW1']
    	db1 = grads['db1']
    	dW2 = grads['dW2']
    	db2 = grads['db2']
    	#梯度下降算法
    	W1 = W1-learning_rate*dW1
    	b1 = b1-learning_rate*db1
    	W2 = W2-learning_rate*dW2
    	b2 = b2-learning_rate*db2
    	parameters = {
    		'W1':W1,
    		'b1':b1,
    		'W2':W2,
    		'b2':b2
    	}
    	return parameters
    
    def nn_model(X, Y, n_h=3, num_iterations=200, learning_rate=0.1):
    	"""
    	函数输入:
    		X:神经网络输入
    		Y:样本真实标签
    		n_h:隐藏层神经元个数
    		num_iterations:训练次数
    		learning_rate:学习率
    	函数输出:
    		parameters:训练完成后的网络参数
    	"""
    	#定义网络
    	n_x=X.shape[0]
    	n_y=1
    	#参数初始化
    	parameters = initialize_parameters(n_x, n_h,n_y)
    	#迭代训练
    	for i in range(num_iterations):
    		#正向传播
    		A2, cache = forward_propagation(X, parameters)
    		#计算交叉熵损失
    		cost = compute_loss(A2, Y)
    		#反向传播
    		grads = back_propagation(X, Y, parameters, cache)
    		#更新参数
    		parameters = update_parameters(parameters, grads, learning_rate)
    		#print
    		if (i+1)%20==0:
    			print('Iteration:%d, cost=%f'%(i+1, cost))
    	return parameters
    
    parameters = nn_model(X, Y, n_h=3, num_iterations=500, learning_rate=0.2)
    
    def predict(X, parameters):
    	"""
    	函数输入:
    		X:神经网络输入
    		parameters:训练完成后的网络参数
    	函数输出:
    		Y_pred:预测样本标签
    	"""
    	#神经网络参数
    	W1 = parameters['W1']
    	b1 = parameters['b1']
    	W2 = parameters['W2']
    	b2 = parameters['b2']
    	#输入层->隐藏层
    	Z1 = np.dot(W1, X)+b1
    	A1 = np.tanh(Z1)
    	#隐藏层->输出层
    	Z2 = np.dot(W2, A1)+b2
    	A2 = sigmoid(Z2)
    	#预测标签
    	Y_pred = np.zeros((1, X.shape[1]))   #初始化Y_pred
    	Y_pred[A2 > 0.5]=1   #Y_hat大于0.5的预测为正值(输出层使用的Sigmoid)
    	return Y_pred
    
    
    #对数据集进行预测,并计算准确率
    Y_pred = predict(X, parameters)
    accuracy = np.mean(Y_pred == Y)
    print(accuracy)
    
    x_min, x_max = X[0, :].min() - 0.5,X[0, :].max() + 0.5
    y_min, y_max = X[1, :].min() - 0.5,X[1, :].max() + 0.5
    step = 0.001
    xx,yy=np.meshgrid(np.arange(x_min,x_max,step),np.arange(y_min,y_max,step))
    Z = predict(np.c_[xx.ravel(),yy.ravel()].T,parameters)
    Z = Z.reshape(xx.shape)
    plt.contourf(xx,yy,Z,cmap=plt.cm.Spectral)   #绘制边界
    #负类
    plt.scatter(X[0,Y[0,:]==0],X[1,Y[0,:]==0],c='g',marker='s',label='负类')
    #正类
    plt.scatter(X[0,Y[0,:]==1],X[1,Y[0,:]==1],c='y',marker='o',label='正类')
    plt.legend()
    plt.show()
    
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值