1、数据说明
本次训练集共有209张图片。每张图片的大小为64*64色素点,每个色素点由RGB三原色组成,所以每张图片的数据维度为(64,64,3)。训练集的数据维数为(209,64,64,3)。测试集共有50张图片,数据维数为(50,64,64,3)。
2、数据预处理
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来对其进行标准化
train_set_x=train_set_x_orig_flatten/255
test_set_x=test_set_x_orig_flatten/255
3、定义sigmoid函数
def sigmoid(X):
return 1/(1+np.exp(-X))
4、定义前向传播
def forward(W,X,b):
z=np.dot(W.T,X)+b
A=sigmoid(z)
return A
5、定义损失函数为交叉熵
def loss(A,Y):
return -np.sum((Y*np.log(A)+(1-Y)*np.log(1-A)))
6、定义后向传播,求导的推导过程可见视频
def backward(W,b,X,Y):
m=X.shape[1]
A=forward(W,X,b)
dw=(1/m)*np.dot(X,(A-Y).T)
db=(1/m)*np.sum(A-Y)
return dw,db
7、定义函数更新参数
def renew_param(w,b,dw,db,lr):
w-=lr*dw
b-=lr*db
return(w,b)
8、学习率为0.05,迭代次数为10000,计算参数。每迭代一百次打印loss。
num_epoches=10000
lr=0.05
dim=train_set_x.shape[0]
num_features=train_set_x.shape[1]
w=np.zeros(shape=(dim,1))
b=0
for i in range(num_epoches):
dw,db=backward(w,b,train_set_x,train_set_y)
renew_param(w,b,dw,db,lr)
if(i%100==0):
print(loss(forward(w,train_set_x,b),train_set_y).mean())
9、计算训练好的模型在训练集和测试集上的准确率
def predict(w,b,X):
m=X.shape[1]
Y_prediction=np.zeros((1,m))
w=w.reshape((X.shape[0],1))
A=sigmoid(np.dot(w.T,X)+b)
for i in range(m):
Y_prediction[0,i]=1 if A[0,i]>0.5 else 0
return Y_prediction
def accuracy(Y_prediction,Y):
return 1-np.mean(np.abs(Y_prediction-Y))
accuracy_train=accuracy(predict(w,b,train_set_x),train_set_y)
accuracy_test=accuracy(predict(w,b,test_set_x),test_set_y)
print('训练集的准确率为'+str(accuracy_train*100)+'%')
print('测试集的准确率为'+str(accuracy_test*100)+'%')