前言
一、整个流程
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ʱ



注意这里的

#定义后向传播 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]=Z[1]*(1-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、构建整个模型
#构建整个模型 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 %
