DeepLearning: 搭建单隐层神经网络对非线性数据分类

搭建单隐层神经网络对非线性数据分类

我通过增加单隐层的神经元数 , 以及改变单隐层的激活函数的方式 , 探索了隐层对神经网络的影响. 通过训练发现 : 隐层的神经元数越多,模型对数据的拟合度越大 ,复杂度越高 , 并且容易出现过拟合 , 需要后期进行正则化. 对于隐层的激活函数, 我分别用了 tanh函数和Relu(线性修正单元), 通过训练后发现: 使用tanh函数作为激活函数准确率要高于Relu,但是迭代速度要低于Relu. 通过对两种激活函数分类后的图像观察发现: 似乎对噪音点过多的数据集, 使用Relu作为激活函数, 模型的鲁棒性更好???希望后面能有大佬斧正.
import numpy as np
import matplotlib.pyplot as plt
import sklearn
import sklearn.linear_model
from testCases import *
from planar_utils import load_planar_dataset, load_extra_datasets

工具函数

# 绘图

def plot_decision_boundary(predict,X,Y):
    
    f1_max,f2_max=X.max(axis=1)
    f1_min,f2_min=X.min(axis=1)
    
    f1=np.linspace(f1_min-1,f1_max+1,500)
    f2=np.linspace(f2_min-1,f2_max+1,500)
    
    x1,x2=np.meshgrid(f1,f2)
    
    x_show=np.stack((x1.flat,x2.flat),axis=1)
    y_show=predict(x_show)
    
    plt.contourf(x1,x2,y_show.reshape(x1.shape),cmap=plt.cm.Spectral)
    plt.scatter(X[0],X[1],c=np.squeeze(Y),cmap=plt.cm.Spectral)
    
def sigmoid(z):
    return 1/(1+np.exp(-z))

def ReLU(z):
    return np.where(z>0,z,0)

查看数据分布

np.random.seed(1) # 固定随机种子,使按一定规则随机
X,Y=load_planar_dataset()
# 画出数据分布
plt.scatter(X[0],X[1],c=np.squeeze(Y),s=40,cmap=plt.cm.Spectral)
plt.show()
# 蓝色:1,红色:0

在这里插入图片描述

print("X的维度:",X.shape)
print("Y的维度:",Y.shape)
print("数据集样本数有:{}个".format(X.shape[1]))
X的维度: (2, 400)
Y的维度: (1, 400)
数据集样本数有:400个

使用逻辑回归查看分类的效果

lr=sklearn.linear_model.LogisticRegression(solver='lbfgs')
lr.fit(X.T,Y.T.ravel())
score=lr.score(X.T,Y.T)

plot_decision_boundary(lambda x:lr.predict(x),X,Y)
print('逻辑回归的准确率为:{}%'.format(score*100))
逻辑回归的准确率为:47.0%

在这里插入图片描述

由于逻辑回归的决策函数是线性的,显然无法对非线性数据进行分类。

搭建神经网络

定义神经网络结构

# 定义神经网络结构
def layer_size(X,Y):
    '''
    parameters:
    X - train dataset
    Y - label
   
    returns:
    n_x - input layer of size
    n_y - hidden layer of size,default:4
    n_y - output layer of size 
    '''
    n_x=X.shape[0]
    n_y=Y.shape[0]
    
    return (n_x,n_y)

初始化模型参数

# 初始化参数
def initialize_parameters(n_x,n_h,n_y):
    '''
    parameters:
    n_x - input layer of size
    n_h - hidden layer of size,default:4
    n_y - output layer of size 
    
    returns:
    parameters - dictionary
    {
     W1:hidden layer's coef
     b1:hidden layer's threshold
     W2:output layer's coef
     b2:output layer;s threshold
    }
    '''
    
    np.random.seed(2) # 规定随机种子
    W1=np.random.randn(n_h,n_x)*0.01
    b1=np.zeros((n_h,1))
    W2=np.random.randn(n_y,n_h)*0.01
    b2=np.zeros((n_y,1))
    
    # 断言以保护矩阵维度
    assert(W1.shape==(n_h,n_x))
    assert(b1.shape==(n_h,1))
    assert(W2.shape==(n_y,n_h))
    assert(b2.shape==(n_y,1))
    
    parameters={
        'W1':W1,
        'b1':b1,
        'W2':W2,
        'b2':b2
    }
    
    return parameters

正向传播

# 正向传播
def forward_propagation(X,parameters):
    '''
    parameters:
    X - train dataset
    parameters - type:dictionary 
    
    returns:
    A2 - output
    cache - dictionary:
    {
     Z1,A1,Z2
    }
    '''
    
    W1=parameters['W1']
    b1=parameters['b1']
    W2=parameters['W2']
    b2=parameters['b2']
    
    Z1=np.dot(W1,X)+b1
    A1=np.tanh(Z1) # 隐藏层使用tanh函数
    #A1=ReLU(Z1) # 隐藏层使用线性修正单元
    Z2=np.dot(W2,A1)+b2
    A2=sigmoid(Z2)
    
    assert(A2.shape==(1,X.shape[1])) 
    
    cache={
        'Z1':Z1,
        'A1':A1,
        'Z2':Z2,
        'A2':A2,
    }
    
    return (A2,cache)

计算损失

# 计算损失
def compute_cost(A2,Y):
    '''
    parameters:
    A2 - output
    Y - true label
    
    returns:
    cost - scalar,type:float
    '''
    m=Y.shape[1]
    allcost=-np.sum( (1-Y)*np.log2(1-A2) + Y*np.log2(A2) )
    cost=(1/m) * allcost
    cost=float(np.squeeze(cost))
    
    assert(isinstance(cost,float))
    
    return cost

反向传播

# 反向传播
def backward_propagation(X,Y,parameters,cache):
    '''
    parameters:
    X - train dataset
    Y - true label
    parameters - type:dictionary
    cache - tyepe:dictionary
    
    returns:
    grads - dictionary:{
    dW1,db1,dW2,db2
    }
    '''
    
    m=X.shape[1]
    
    A2=cache['A2']
    A1=cache['A1']
    W2=parameters['W2']
    
    dZ2=A2-Y
    dW2=(1/m)*np.dot(dZ2,A1.T)
    db2=(1/m)*np.sum(dZ2,axis=1,keepdims=True)
    
    dZ1=np.dot(W2.T,dZ2)*(1-np.power(A1,2)) # 隐藏层使用tanh函数
    #dZ1=np.dot(W2.T,dZ2)*np.where(A1>0,1,0) # 隐藏层使用线性修正单元
    dW1=(1/m)*np.dot(dZ1,X.T)
    db1=(1/m)*np.sum(dZ1,axis=1,keepdims=True)
    
    grads={
        'dW2':dW2,
        'db2':db2,
        'dW1':dW1,
        'db1':db1
    }
    
    return grads

更新参数

# 更新参数
def update_parameters(parameters,grads,learning_rate):
    '''
    parameters:
    parameters - dictionary
    grads - dictionary
    learning_rate - update step size
    
    returns:
    parameters - after update parameters
    '''
    
    W2=parameters['W2']
    b2=parameters['b2']
    W1=parameters['W1']
    b1=parameters['b1']
    
    dW2=grads['dW2']
    db2=grads['db2']
    dW1=grads['dW1']
    db1=grads['db1']
    
    W2=W2 - learning_rate * dW2
    W1=W1 - learning_rate * dW1
    b2=b2 - learning_rate * db2
    b1=b1 - learning_rate * db1
    
    parameters={
        'W1':W1,
        'b1':b1,
        'W2':W2,
        'b2':b2
    }
    
    return parameters

整合

# 整合
def nn_model(X,Y,n_h,num_iterations,learning_rate,print_cost=False):
    
    n_x,n_y=layer_size(X,Y)
    
    parameters=initialize_parameters(n_x,n_h,n_y)
    
    for i in range(num_iterations):
        
        A2,cache=forward_propagation(X,parameters)
    
        cost=compute_cost(A2,Y)
    
        grads=backward_propagation(X,Y,parameters,cache)
       
        parameters=update_parameters(parameters,grads,learning_rate)
        
        if print_cost:
            if i%1000==0:
                print("第",i,"次循环成本为:",str(cost))
    return parameters

预测

# 预测
def predict(parameters,X):
    
    A2=forward_propagation(X,parameters)[0]
    predictions=np.round(A2)
    
    return predictions

对之前的数据进行分类

parameters = nn_model(X, Y, n_h = 4, num_iterations=10000, learning_rate=1.2,print_cost=True)

#绘制边界
plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y)
plt.title("Decision Boundary for hidden layer size " + str(4))

predictions = predict(parameters, X)
print ('准确率: {}'.format( (1-np.abs(predictions-Y).sum()/Y.shape[1])*100 ) + '%')
第 0 次循环成本为: 0.9998569417307839
第 1000 次循环成本为: 0.4156163389949822
第 2000 次循环成本为: 0.3670006907735593
第 3000 次循环成本为: 0.33739465000867414
第 4000 次循环成本为: 0.32719239695288127
第 5000 次循环成本为: 0.32120779213605305
第 6000 次循环成本为: 0.3170054069401357
第 7000 次循环成本为: 0.31379144307505785
第 8000 次循环成本为: 0.316677281320471
第 9000 次循环成本为: 0.31533123647023475
准确率: 90.75%

在这里插入图片描述

更改隐藏层节点数量

plt.figure(figsize=(16, 32))
hidden_layer_sizes = [1, 2, 3, 4, 5, 20, 50] #隐藏层数量

for i,n_h in enumerate(hidden_layer_sizes):
    parameters = nn_model(X, Y, n_h, num_iterations=10000, learning_rate=1.2)
    predictions=predict(parameters,X)
    print ('节点数为 {} 时的准确率: {}'.format( n_h,(1-np.abs(predictions-Y).sum()/Y.shape[1])*100 ) + '%')
    plt.subplot(4,2,i+1)
    plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y)
    plt.title("Decision Boundary for hidden layer size " + str(n_h))
节点数为 1 时的准确率: 67.5%
节点数为 2 时的准确率: 67.25%
节点数为 3 时的准确率: 91.0%
节点数为 4 时的准确率: 90.75%
节点数为 5 时的准确率: 91.5%
节点数为 20 时的准确率: 91.25%
节点数为 50 时的准确率: 92.25%

在这里插入图片描述

对不同数据集进行探索

noisy_circles, noisy_moons, blobs, gaussian_quantiles, no_structure = load_extra_datasets()

datasets = {"noisy_circles": noisy_circles,
            "noisy_moons": noisy_moons,
            "blobs": blobs,
            "gaussian_quantiles": gaussian_quantiles}

dataset = "noisy_moons"

X, Y = datasets[dataset]
X, Y = X.T, Y.reshape(1, Y.shape[0])

if dataset == "gaussian_quantiles":
    Y = Y % 2

plt.scatter(X[0, :], X[1, :], c=np.squeeze(Y), s=40, cmap=plt.cm.Spectral)
<matplotlib.collections.PathCollection at 0x1c4dcd02e10>

在这里插入图片描述

parameters = nn_model(X, Y, n_h = 4, num_iterations=10000, learning_rate=1.2,print_cost=True)

#绘制边界
plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y)
plt.title("Decision Boundary for hidden layer size " + str(4))

predictions = predict(parameters, X)
print ('准确率: {}'.format( (1-np.abs(predictions-Y).sum()/Y.shape[1])*100 ) + '%')
第 0 次循环成本为: 0.999775810185032
第 1000 次循环成本为: 0.2411282826869065
第 2000 次循环成本为: 0.09967917263284516
第 3000 次循环成本为: 0.09192243290559801
第 4000 次循环成本为: 0.08845437205781047
第 5000 次循环成本为: 0.08608479518774807
第 6000 次循环成本为: 0.08420119608642555
第 7000 次循环成本为: 0.08263578077196151
第 8000 次循环成本为: 0.0813088555044688
第 9000 次循环成本为: 0.08016868759786135
准确率: 98.5%

在这里插入图片描述
参考:https://blog.csdn.net/u013733326/article/details/79702148
完整代码:https://github.com/TaoistNie/DeepLearning/tree/master/dl second lesson week3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值