搭建单隐层神经网络对非线性数据分类
我通过增加单隐层的神经元数 , 以及改变单隐层的激活函数的方式 , 探索了隐层对神经网络的影响. 通过训练发现 : 隐层的神经元数越多,模型对数据的拟合度越大 ,复杂度越高 , 并且容易出现过拟合 , 需要后期进行正则化. 对于隐层的激活函数, 我分别用了 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