前言
最近在学习吴恩达的深度学习课程,关于《神经网络和深度学习》已经学习完,刚编写完最后一周的作业,这次任务主要是设计一个L层网络,每次网络的节点数也可以自己设置,现附上整个设计过程,供大家学习讨论!若有不对的地方,希望大家不吝赐教,谢谢!
一、整个流程
1、处理数据
先下载数据:点这里,提取码:smqn
提取数据,得到训练集,训练标签,测试集,测试标签,类别
import numpy as np
import h5py #与H5文件中存储的数据集进行交互的常用软件包
def load_dataset():
train_dataset=h5py.File('datasets/train_catvnoncat.h5','r')
train_set_x_orig=np.array(train_dataset['train_set_x'][:])
train_set_y_orig=np.array(train_dataset['train_set_y'][:])
test_dataset=h5py.File('datasets/test_catvnoncat.h5','r')
test_set_x_orig=np.array(test_dataset['test_set_x'][:])
test_set_y_orig=np.array(test_dataset['test_set_y'][:])
classes=np.array(test_dataset['list_classes'][:])
train_set_y_orig=train_set_y_orig.reshape((1,train_set_y_orig.shape[0]))
test_set_y_orig=test_set_y_orig.reshape((1,test_set_y_orig.shape[0]))
return train_set_x_orig,train_set_y_orig,test_set_x_orig,test_set_y_orig,classes
处理数据
train_x,train_y,test_x,test_y,classes=load_dataset()
train_m=train_y.shape[1]
test_m=test_y.shape[1]
picture_size=train_x.shape[1]
print('训练集的大小:'+str(train_m))
print('测试集的大小:'+str(test_m))
print('训练集的维数:'+str(train_x.shape))
print('测试集的维数:'+str(test_x.shape))
print('训练集标签的维数:'+str(train_y.shape))
print('测试集标签的维数:'+str(test_y.shape))
train_set_x_flatten=train_x.reshape(train_x.shape[0],-1).T
test_set_x_flatten=test_x.reshape(test_x.shape[0],-1).T
train_x=train_set_x_flatten/255
test_x=test_set_x_flatten/255
print('训练集的维数:'+str(train_x.shape))
print('测试集的维数:'+str(test_x.shape))
对训练集和测试集数据做简单的处理,进行平铺和归一化
可以得到如下信息:
训练集的大小:209
测试集的大小:50
训练集的维数:(209, 64, 64, 3)
测试集的维数:(50, 64, 64, 3)
训练集标签的维数:(1, 209)
测试集标签的维数:(1, 50)
训练集的维数:(12288, 209)
测试集的维数:(12288, 50)
2、设计网络大小
设计L层网络,注意网络层不包括输入层,只包括隐藏层和输出层,并设计每层的节点数,在这里我们把输入层记为第0层。
#得到网络的层数和每一层的单元节点数
def net_size(l,X,n):
net_dims={}
net_dims[0]=X.shape[0]
for i in range(1,l+1):
net_dims[i]=n[i-1]
print('一共有:%d层网络' % l)
print('每一层分别对应多少节点如下:')
print(net_dims)
return l,net_dims
#测试下
l=3
n=[4,3,1]
l,net_dims=net_size(l,train_x,n)
结果如下:
一共有:3层网络
每一层分别对应多少节点如下:
{0: 12288, 1: 4, 2: 3, 3: 1}
3、激活函数
关于隐藏层采取Relu激活函数,输出层采取sigmoid函数
#定义隐藏层的激活函数
def relu(z):
s=np.maximum(0,z)
return s
#定义输出层的激活函数
def sigmoid(z):
s=1/(1+np.exp(-z))
return s
4、初始化w和b
在对变量进行初始化时,一定要注意变量的维度
、
#初始化w和b
def init_w_b(l,net_dims):
parms={}
np.random.seed(1)
for i in range(1,l+1):
str1='w'+str(i)
parms[str1]=np.random.rand(net_dims[i],net_dims[i-1])*0.01
ch='b'+str(i)
parms[ch]=np.zeros(shape=(net_dims[i],1))
assert(parms[str1].shape==(net_dims[i],net_dims[i-1]))
assert(parms[ch].shape==(net_dims[i],1))
return parms
5、前向传播
、
在这里有两点需要注意:(1)除了输出层激活函数是sigmoid,前面的激活函数是relu。(2)在这里得单独出来计算,带入X代替
#前向传播
def forward(l,parms,X,Y,net_dims):
A={}
Z={}
for i in range(1,l+1):
A[i]=np.zeros(shape=(net_dims[i],Y.shape[1]))
Z[i]=np.zeros(shape=(net_dims[i],Y.shape[1]))
Z[1]=np.dot(parms['w1'],X)+parms['b1']
A[1]=relu(Z[1])
for i in range(2,l):
Z[i]=np.dot(parms['w'+str(i)],A[i-1])+parms['b'+str(i)]
A[i]=relu(Z[i])
Z[l]=np.dot(parms['w'+str(l)],A[l-1])+parms['b'+str(l)]
A[l]=sigmoid(Z[l])
A_Z={'A':A,
'Z':Z}
return A_Z
6、损失函数
#定义损失函数
def cost_function(Y,A_Z,l):
m=Y.shape[1]
A=A_Z['A']
A_last=A[l]
cost=(-1/m)*(np.sum(Y*(np.log(A_last))+(1-Y)*(np.log(1-A_last))))
return cost
7、反向传播
、、
(1) l=L
(2) l从L-1到2循环:
注意这里的
(3) l=1时
(这里是X,所以单独处理)
#定义后向传播
def backward(A_Z,Y,l,net_dims,parms,X):
A=A_Z['A']
Z=A_Z['Z']
m=Y.shape[1]
dZ={}
dw={}
db={}
g={}
#初始化
for i in range(1,l+1):
dZ[i]=np.zeros(shape=(net_dims[i],Y.shape[1]))
dw[i]=np.zeros(shape=(net_dims[i],net_dims[i-1]))
db[i]=np.zeros(shape=(net_dims[i],1))
g[i]=np.zeros(shape=(net_dims[i],Y.shape[1]))
dZ[l]=A[l]-Y
while(l):
dw[l]=(1/m)*(np.dot(dZ[l],A[l-1].T))
db[l]=(1/m)*(np.sum(dZ[l],axis=1,keepdims=True))
l-=1
if l==1:
break
g[l]=relu(Z[l])
dZ[l]=np.dot((parms['w'+str(l+1)]).T,dZ[l+1])*g[l]
g[1]=relu(Z[1])
dZ[1]=np.dot((parms['w2']).T,dZ[2])*g[1]
dw[1]=(1/m)*(np.dot(dZ[1],X.T))
db[1]=(1/m)*(np.sum(dZ[1],axis=1,keepdims=True))
grads={'dw':dw,
'db':db}
return grads
8、优化
#优化
def optimize(parms,l,net_dims,X,Y,iterations=2000,learning_rate=0.5,print_flag=False):
costs=[]
for j in range(iterations):
A_Z=forward(l,parms,X,Y,net_dims)
cost=cost_function(Y,A_Z,l)
grads=backward(A_Z,Y,l,net_dims,parms,X)
for i in range(1,l+1):
parms['w'+str(i)]=parms['w'+str(i)]-learning_rate*grads['dw'][i]
parms['b'+str(i)]=parms['b'+str(i)]-learning_rate*grads['db'][i]
if j%100==0:
costs.append(cost)
if (print_flag) and (j%100==0):
print('迭代次数:%d,损失值:%f' % (j,cost))
return parms,grads,costs
9、预测
#预测
def predict(parms,X,l,Y,net_dims):
A_Z=forward(l,parms,X,Y,net_dims)
y_predict=np.zeros(shape=(1,Y.shape[1]))
A=A_Z['A']
for i in range(Y.shape[1]):
if (A[l][0,i]-Y[0,i])>0.5:
y_predict[0,i]=1
else:
y_predict[0,i]=0
return y_predict
10、构建整个模型
设置网络大小初始化w和b对w和b进行优化用优化后的w和b进行预测
#构建整个模型
def modle(train_x,train_y,test_x,test_y,iterations=2000,learning_rate=0.5,print_flag=False):
l=3 #一共3层
n=[4,3,1] #每一层节点数分别是:4,3,1
l,net_dims=net_size(l,train_x,n)
parms=init_w_b(l,net_dims)
parms,grads,costs=optimize(parms,l,net_dims,train_x,train_y,iterations,learning_rate,print_flag)
y_predict_train=predict(parms,train_x,l,train_y,net_dims)
y_predict_test=predict(parms,test_x,l,test_y,net_dims)
print('训练集的准确性:',format(100-np.mean(np.abs(train_y-y_predict_train))),'%')
print('测试集的准确性:',format(100-np.mean(np.abs(test_y- y_predict_test))),'%')
res={'cost':costs,
'parms':parms,
'y_predict_train':y_predict_train,
'y_predict_test':y_predict_test,
'iterations':iterations,
'learning_rate':learning_rate}
return res
11、进行测试,对结果进行绘图
res=modle(train_x,train_y,test_x,test_y,iterations=5000,learning_rate=0.005,print_flag=True)
#绘制图
costs = np.squeeze(res['cost'])
plt.plot(costs)
plt.ylabel('cost')
plt.xlabel('iterations (per hundreds)')
plt.title("Learning rate =" + str(res["learning_rate"]))
plt.show()
12、查看结果
训练集的大小:209
测试集的大小:50
训练集的维数:(209, 64, 64, 3)
测试集的维数:(50, 64, 64, 3)
训练集标签的维数:(1, 209)
测试集标签的维数:(1, 50)
训练集的维数:(12288, 209)
测试集的维数:(12288, 50)
一共有:3层网络
每一层分别对应多少节点如下:
{0: 12288, 1: 4, 2: 3, 3: 1}
迭代次数:0,损失值:0.694434
迭代次数:100,损失值:0.655321
迭代次数:200,损失值:0.646017
迭代次数:300,损失值:0.644177
迭代次数:400,损失值:0.643994
迭代次数:500,损失值:0.643976
迭代次数:600,损失值:0.643974
迭代次数:700,损失值:0.643974
迭代次数:800,损失值:0.643974
迭代次数:900,损失值:0.643974
迭代次数:1000,损失值:0.643974
迭代次数:1100,损失值:0.643974
迭代次数:1200,损失值:0.643974
迭代次数:1300,损失值:0.643974
迭代次数:1400,损失值:0.643974
迭代次数:1500,损失值:0.643974
迭代次数:1600,损失值:0.643974
迭代次数:1700,损失值:0.643974
迭代次数:1800,损失值:0.643974
迭代次数:1900,损失值:0.643974
训练集的准确性: 99.6555023923445 %
测试集的准确性: 99.34 %
总结:以上即是整个流程,强调下,在计算每个变量值时,一定要注意维度的问题,所以我在进行编写程序前都会计算下每个变量的维度,最后在检查程序出错问题时,也需要特别关注这点,若需要整个工程程序可以留言,或有不懂的也可以留言。