数据预处理
简介
在上一节——数据读取中我们下载了Mnist数据集,并写了两个函数读取它们。
在这一节中,我们会调用这两个函数,并做数据预处理。
数据预处理有:
1、图像数据标准化
2、标签数据独热化(one-hot)
调用函数读取数据
注意将Mnist数据文件解压后保存在脚本所在的文件夹下。如果报错,找不到文件,可以修改默认目录。
#读取四个文件
X_train = read_image("train-images.idx3-ubyte")
Y_train = read_label("train-labels.idx1-ubyte")
X_test = read_image("t10k-images.idx3-ubyte")
Y_test = read_label("t10k-labels.idx1-ubyte")
读取后的工作区如图
图片数据标准化
对于uint8型图像数据,数据范围为(0-255)。标准化将其转换为(0-1)范围内的浮点型数据。
X_train /= 255
X_test /= 255
这样做的目的
1.是浮点型精度高便于处理。
2.在机器学习中,当输入的数据有多种特征,且各种特征取值范围相差较大时(一般10倍以上),直接使用梯度下降法收敛速度会较慢。正确的做法是让数据服从N(0,1),即标准正态分布。
import numpy as np
#np.mean()求均值,np.std()求标准差
Data = (Data - np.mean(Data)) / np.std(Data)
对于图像数据,为了方便显示图像,应将其变为(0-1),而并不是标准正态分布。
标签数据独热化(one-hot)
所谓独热向量,就是指一个非负整数对应的一个向量,除了一个值为1, 其他全为0,而为1的值的位置就是非负整数的值。
将标签转化为独热向量的目的是为了方便之后的输出层Softmax计算交叉熵作为损失函数,从而对整个模型进行优化。之后的小节我们再详解。
在转化之前,我们先将二维矩阵的标签数据压缩为一维列表。
#np.squeeze()压缩长度为1的维度
Y_train = np.squeeze(Y_train)
Y_test = np.squeeze(Y_test)
再编写一个转化函数
"""
one_hot.py
将标签转化为独热向量
"""
import numpy as np
def one_hot(indices, depth = None, axis = 0):
"""
将标签转化为独热向量
标签必须是列表类型
要转化的轴必须为0或1
参数:
indices -- 原始标签
depth -- 标签的深度(即转化后独热向量的长度)
axis -- 独热向量的方向轴
返回:
one_hot -- 独热向量组成的矩阵
"""
#计算标签最大值
indices_maximum = int(np.amax(indices, keepdims = True))
#计算标签的个数
num_examples = len(indices)
#计算默认深度
if None == depth:
depth = indices_maximum + 1
#建立一个沿axis方向值为0-indeces_maximum的二维矩阵
#axis为0时
if 0 == axis:
comparison = np.tile(np.array(range(depth)).\
reshape(depth, 1), (1, num_examples))
#其他情况都认为axis为1
else:
comparison = np.tile(np.array(range(depth).\
reshape(1, depth)), (num_examples, 1))
#将one-hot初始化为全零
if 0 == axis:
one_hot = np.zeros([depth, len(indices)])
else:
one_hot = np.zero([len(indices), depth])
#逐列/行比较,确定one-hot
for i in range(num_examples):
if 0 == axis:
one_hot[:, i] = np.equal(comparison[:, i], indices[i])
else:
one_hot[i, :] = np.equal(comparison[i, :], indices[i])
return one_hot
```
调用刚写好的函数
```Python
Y_train_one_hot = one_hot(Y_train)
Y_test_one_hot = one_hot(Y_test)
转化前
转化好的结果
没有直接覆盖Y_train和Y_test,后来做预测的时候他俩有用。