首页 >> 大全

多层神经网络实现猫图片的二分类问题

2023-12-06 大全 21 作者:考证青年

一、作业概述

本次作业要利用多层神经网络实现猫咪图片的二分类问题。其中训练集共有图片209张,测试集共有图片50张。隐藏层数量为一层,隐藏层上的神经元个数为5个。隐藏层的激活函数采用Relu函数,输出层的激活函数为函数。

二、完成步骤

1、数据预处理

要将图片转化为向量。每张图片的大小为64*64色素点,每个色素点由RGB三原色组成,所以每张图片需要64*64*3=12288个数据点确定。所以训练集图片数据维度为(12288,209)。而由于此问题是二分类问题,故输出的标签只有0-1两种可能,标签集的维度为(1,209)。处理完后还要将图片集的数据除以255,其目的是归一化。数据预处理的代码如下:

#1、数据预处理
import h5py
import numpy as np
from d2l import torch as d2l
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
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"][:])#保存的是以bytes类型保存的两个字符串数据:‘cat','non-cat'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
"""每张图片的大小为64*64色素点,每个色素点由RGB三原色组成,所以每张图片的数据维度为(64,64,3),一张图片共需要12288个数据点确定。load_dataset函数的返回值意义如下:
train_set_x_orig:训练集图像数据,一共209张,数据维度为(209,64,64,3)
train_set_y_orig:训练集的标签集,维度为(1,209)
test_set_x_orig:测试集图像数据,一共50张,维度为(50,64,64,3)
test_set_y_orig:测试集的标签集,维度为(1,50)
classes : 保存的是以bytes类型保存的两个字符串数据,数据为:[b’non-cat’ b’cat’]
"""
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()#调用load_dataset函数
d2l.plt.imshow(train_set_x_orig[27])
d2l.plt.show()
#打印出当前的训练标签值
#使用np.squeeze的目的是压缩维度,【未压缩】train_set_y[:,index]的值为[1] , 【压缩后】np.squeeze(train_set_y[:,index])的值为1
#print("【使用np.squeeze:" + str(np.squeeze(train_set_y[:,index])) + ",不使用np.squeeze: " + str(train_set_y[:,index]) + "】")
#只有压缩后的值才能进行解码操作
index=25
print("y=" + str(train_set_y[ :,index]) + ", it's a " + classes[np.squeeze(train_set_y[:,index])].decode("utf-8") + "' picture")
m_train=train_set_y.shape[1]#训练集里面图片的数量
m_test=test_set_y.shape[1]#测试集里面图片的数量
num_px=train_set_x_orig.shape[1]#训练集和测试集图片的高度和宽度,在这里均为64
print('训练集图片的数量为'+str(m_train))
print('测试集图片的数量为'+str(m_test))
print('训练集和测试集图片的高/宽为'+str(num_px))
print('每张图片大小为:'+"("+str(num_px)+","+str(num_px)+","+str(train_set_x_orig.shape[3])+")")
print('测试集图片的维数为:'+str(train_set_x_orig.shape))#(209,64,64,3)
print('测试集标签的维数为:'+str(train_set_y.shape))#(1,209)
print('训练集图片的维数为:'+str(test_set_x_orig.shape))#(50,64,64,3)
print('训练集标签的维数:'+str(test_set_y.shape))#(1,50)
train_set_x_orig_flatten=train_set_x_orig.reshape(train_set_x_orig.shape[0],-1).T#将训练集图片降维并转置,处理后的shape为(64*64*3,209)
test_set_x_orig_flatten=test_set_x_orig.reshape(test_set_x_orig.shape[0],-1).T
print('训练集图片降维后的维数为:'+str(train_set_x_orig_flatten.shape))#(12288,209)
print('训练集标签的维数为:'+str(train_set_y.shape))#(1,209)
print('测试集图片降维后的维数为:'+str(test_set_x_orig_flatten.shape))#(12288,50)
print('测试集标签的维数为:'+str(test_set_y.shape))#(1,50)
#像素值实际上是0-255范围内的三个数字的向量,因此可以对图片向量除以255来对其进行标准化

2、激活函数

激活函数有两个,分别为和relu函数,具体代码实现分别见下。

def sigmoid_function(X):return 1/(1+np.exp(-X))
def relu_function(X):a=np.maximum(0,X)assert (a.shape==X.shape)return a

3、参数初始化

W采用随机高斯分布进行初始化,b采用零进行初始化。传入的参数包括X,Y,以及隐藏层的神经元数量。返回值为一个字典,字典中包含初始化好的参数。代码如下。

_多层神经网络数学模型_典型的多层神经网络模型

def initialiaze_parameters(X,n_h,Y):parameters={}W1=np.random.randn(n_h,X.shape[0])*0.01b1 = np.zeros(shape=(n_h,1))W2=np.random.randn(Y.shape[0],n_h)*0.01b2=np.zeros(shape=(Y.shape[0],1))parameters["W1"]=W1parameters["b1"] = b1parameters["W2"] = W2parameters["b2"] = b2return parameters#返回一个字典,里面包含初始化好的参数

4、前向传播

利用前向传播得到Y的估计值A2,并用cache保留每次计算中产生的A和Z,以供后续反向传播计算可用。传入的参数只有X和字典。返回A2和cache。代码如下。

def forward_pro(X,parameters):caches=[]W1=parameters['W1']W2=parameters['W2']b1=parameters['b1']b2=parameters['b2']Z1=np.dot(W1,X)+b1A1=relu_function(Z1)cache=(Z1,A1)caches.append(cache)Z2=np.dot(W2,A1)+b2A2 = sigmoid_function(Z2)cache=(Z2,A2)caches.append(cache)return A2,caches

5、计算损失函数

利用交叉熵作为损失函数,代码如下:

def compute_cost(A2,Y):m=Y.shape[1]cost=(-1/m)*np.sum(np.multiply(Y,np.log(A2)+np.multiply(np.log(1-A2),1-Y)))cost=np.squeeze(cost)assert (cost.shape==())return cost

6、反向传播

从后往前对参数进行求导,并建立一个字典保存计算好的梯度,返回这个字典。并且用语句确保dw和w的维数是一样的,db和b的维数是一样的。

def backward_pro(parameters,caches,X,Y):m=X.shape[1]W1=parameters["W1"]b1=parameters["b1"]W2=parameters["W2"]b2=parameters["b2"]Z1,A1=caches[0]Z2,A2=caches[1]dZ2=A2-Ydb2=(1/m)*np.sum(dZ2,axis=1,keepdims=True)assert (db2.shape==b2.shape)dW2=(1/m)*np.dot(dZ2,A1.T)assert (dW2.shape==W2.shape)dA1=np.dot(W2.T,dZ2)dZ1=np.array(dA1,copy=True)dZ1[Z1<=0]=0assert (dZ1.shape==Z1.shape)dW1=(1/m)*np.dot(dZ1,X.T)assert (dW1.shape==W1.shape)db1=(1/m)*np.sum(dZ1,axis=1,keepdims=True)assert (db1.shape==b1.shape)grad={}grad['W1']=dW1grad['W2']=dW2grad['b1']=db1grad['b2']=db2return  grad

7、更新参数

传入学习率,字典,字典grad,返回更新好的参数

def renew_parameters(parameters,grad,learning_rate):dW1=grad["W1"]dW2=grad["W2"]db1=grad["b1"]db2=grad['b2']parameters['W1']-=dW1*learning_rateparameters["W2"]-=dW2*learning_rateparameters["b1"]-=db1*learning_rateparameters["b2"]-=db2*learning_ratereturn parameters

8、模型学习

传入学习率,X,Y,以及迭代次数。不断更新参数,直至迭代完成,每迭代100次打印一次cost,观察成本函数变化趋势。返回学习好的参数。

def nn_model(X,Y,num_epoches,learning_rate):parameters = initialiaze_parameters(X, 5,Y)for i in range(num_epoches):A2, caches = forward_pro(X, parameters)cost = compute_cost(A2, Y)grads=backward_pro(parameters,caches,X,Y)parameters=renew_parameters(parameters,grads,learning_rate)if(i0==0):print(f'第{i}次迭代的loss为:{cost}')return parameters

三、结果输出

将学习好的参数喂入数据,观察在训练集和测试集上的准确率。

parameters=nn_model(train_set_x,train_set_y,3000,0.0075)
print(parameters)print(parameters['W1'].shape)
print(parameters['b1'].shape)
print(parameters['W2'].shape)
print(parameters['b2'].shape)
def predict(parameters,X):A2,caches=forward_pro(X,parameters)m=A2.shape[1]Y_prediction=np.zeros((1,m))for i in range(m):Y_prediction[0,i]=1 if A2[0,i]>0.5 else 0return Y_prediction
def accuracy(Y_prediction,Y):return 1-np.mean(np.abs(Y_prediction-Y))
accuracy_train=accuracy(predict(parameters,train_set_x),train_set_y)
accuracy_test=accuracy(predict(parameters,test_set_x),test_set_y)
print('训练集的准确率为'+str(accuracy_train*100)+'%')
print('测试集的准确率为'+str(accuracy_test*100)+'%')

本次迭代次数采用3000次,学习率为0.0075。模型在训练集上的准确率为100%,测试集上的准确率为72%

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了