在本文开始之前首先声明,本文参考Logistic Regression with a Neural Network mindset,我基于他的文章加以自己的理解发表这篇博客。
本文所用资料已上传百度云盘【点击下载】,请在开始之前将文件下载好,确保在python根目录下有lr_utils.py和数据集文件夹。
【python版本:3.6.4】
首先,将本次设计所要使用的几个库引用进来:
- numpy:python进行科学计算常用的包
- h5py:用于与H5文件中存储的数据集进行交互的包
- matplotlib:一个用于python制图的著名的库
- Ir_utils:基于H5py写的一个库,用于下载数据集中的数据
import numpy as np
import h5py
import matplotlib.pyplot as plt
from lr_utils import load_dataset
lr_utils.py库中代码如下,也可以自行打开查看:
import numpy as np
import h5py #h5py:Python与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"][:]) #读取训练数据集里面的图像对应的分类值(0/1)
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"][:]) #读取测试数据集里面的图像对应的分类值(0/1)
classes = np.array(test_dataset["list_classes"][:]) #保存的是以Bytes类型保存的两个字符串数据集
#数据为:【'non-cat','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
解释一下上面库中部分代码意思:
- H5文件:类似于python中的字典,也是由键值组成;
- h5py.File:用于读取H5文件的代码;
- train_dataset [ “train_set_x”] [:]:读取键 “train_set_x” 下的所有数据作为训练数据集;
- test_dataset [ “test_set_x”] [:]:读取键 “test_set_x” 下的所有数据作为测试数据集;
- train_dataset [ “train_set_y”] [:]:读取键 “train_set_y” 下数据作为训练数据集的标签(0丨1);
- test_dataset [ “test_set_y”] [:]:读取键 “test_set_y” 下数据作为测试数据集的标签(0丨1);
- classes:保存的是以字节类型保存的两个字符串数据,数据为:[b'non-cat'b'cat'];
- train_set_y_orig.reshape((1,train_set_y_orig.shape [0])):将train_set_y_orig矩阵重组为二维的1X209阶矩阵;
- test_set_y_orig.reshape((1,test_set_y_orig.shape [0])):将test_set_y_orig矩阵重组为二维的1X50阶矩阵;
接下来我们将数据加载到主函数中:
train_set_x_orig , train_set_y , test_set_x_orig , test_set_y , classes = load_dataset()
首先我们需要知道:train_set_x_orig是一个维度为(m_ train,num_px,num_px,3)的数组(test和train的维度相同),train_set_y是一个维度为(1,m_ train)的数组。
m_train = train_set_y.shape[1]
### 训练样本数,也等于train_set_x_orig.shape[0] ###
m_test = test_set_y.shape[1]
### 测试样本数,也等于test_set_x_orig.shape[0] ###
num_px = train_set_x_orig.shape[1]
### 图片像素 ###
然后看一下我们加载的数据
print ("Number of training examples: m_train = " + str(m_train))
print ("Number of testing examples: m_test = " + str(m_test))
print ("Height/Width of each image: num_px = " + str(num_px))
print ("Each image is of size: (" + str(num_px) + ", " + str(num_px) + ", 3)")
print ("train_set_x shape: " + str(train_set_x_orig.shape))
print ("train_set_y shape: " + str(train_set_y.shape))
print ("test_set_x shape: " + str(test_set_x_orig.shape))
print ("test_set_y shape: " + str(test_set_y.shape))
运行结果:
Number of training examples: m_train = 209
Number of testing examples: m_test = 50
Height/Width of each image: num_px = 64
Each image is of size: (64, 64, 3)
train_set_x shape: (209, 64, 64, 3)
train_set_y shape: (1, 209)
test_set_x shape: (50, 64, 64, 3)
test_set_y shape: (1, 50)
我们已经知道一张图片是由64×64像素构成的,每个像素点是由三原色(R,G,B)组成的,所以要乘上如图3所示,这样一张图片可以表示为numpy的数组(64,64,3)中,为了方便,我们需要将维度降低,将其构成一个(64X64X3,1)的numpy数组。这样我们的训练集和测试集是一个numpy数组,每一列代表一个平坦的图像。
使用以下代码可以实现将维度为(a,b,c,d)的矩阵平铺为(b * c * d,a)的矩阵X_flatten。
train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0], -1).T
### 将训练集的维度降低并转置 ###
test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1).T
### 将测试集的维度降低并转置 ###
print ("train_set_x_flatten shape: " + str(train_set_x_flatten.shape))
print ("test_set_x_flatten shape: " + str(test_set_x_flatten.shape))
已经知道train_set_x_orig.shape [0]是图片数量,使用重塑就构成了209行,然后多少列我并不知道可以让电脑自己去算,直接采用-1,最后得出结果是12288列。再转置一下我们就可以得到一个12288行,209列的一个矩阵。
降维后的情况:
train_set_x_flatten shape: (12288, 209)
test_set_x_flatten shape: (12288, 50)
因为一个像素点的颜色是由RGB三个值来表现的,所以像素点矩阵对应三个颜色向量矩阵,其值为从0到255的范围内数字。在机器学习中对数据进行预处理最常见的步骤是特征缩放和均值归一化。
特征缩放:目的是为了让梯度下降运行的更快一点,为了将特征的取值约束在-1到1之间,我们可以用数据集除上极差(最大值与最小值之差)
均值归一化:将特征值变为平均值为0的特征值采用公式,其中为数据集的平均值,S为极差。
对于图片数据集,数据集的每一行都直接除以255(像素通道的最大值),因为在RGB中不存在比255大的数据,所以我们可以放心的除以255,让标准化的数据位于[ 0,1]之间,现在标准化我们的数据集就可以得到最终数据处理后的数据集:
train_set_x = train_set_x_flatten / 255
### 对数据集进行居中和标准化 ###
test_set_x = test_set_x_flatten / 255
### 因为在RGB中不存在比255大的数据,可以放心除以像素通道的最大值 ###
数据加载完之后,我们可以看一下我们的数据集里面的图片以及处理后的数据是什么样子的。
### 标签数据 ###
print("train_set_y shape : " + str(train_set_y.shape))
print("train_set_y=" + str(train_set_y))
print("test_set_y shape : " + str(test_set_y.shape))
print("test_set_y=" + str(test_set_y))
train_set_y shape : (1, 209)
train_set_y=[[0 0 1 0 0