python数据预处理并使用pickle模块保存
2018-01-21 19:17
736 查看
机器学习中,通常拿到的数据并不能直接使用,需要进行预处理,比如剔除部分特征、去除脏数据、数据归一化、独热编码等,也就是特征工程。我们不希望每次加载程序的时候都需要进行前面的预处理,因此可以把预处理之后的数据保存起来,这里可以用pickle模块。这有点类似电脑游戏中的进度保存。
下面以 notMNIST 数据集为例,介绍如何进行数据的预处理。
数据格式采用“.zip”格式。
Min-Max Scaling:
X′=a+(X−Xmin)(b−a)Xmax−Xmin
下面以 notMNIST 数据集为例,介绍如何进行数据的预处理。
1. 导入需要的模块
第一步,先把需要的模块导入。import hashlib import os import pickle from urllib.request import urlretrieve import numpy as np from PIL import Image from sklearn.model_selection import train_test_split from sklearn.preprocessing import LabelBinarizer from sklearn.utils import resample from tqdm import tqdm from zipfile import ZipFile print('All modules imported.')
hashlib:用来提供常见的摘要算法,比如MD5、SHA1等。摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。摘要算法不是加密算法,只能用于防篡改,也可以在不存储明文口令的情况下验证用户口令。(参考 hashlib)
os:包含普遍的操作系统功能,主要是对目录和文件进行访问,可以方便移植到不同的平台。
pickle:序列化模块,用来把内存中的数据变成可存储和传输的数据。
urllib.request:
urllib是用来处理网址的模块,其中
urllib.request是为打开url提供的可扩展类库。(参考 Python中的urllib.request模块)
PIL:是python上的标准图像处理库,
Python Imaging Library。(参考 PIL)
tqdm:用来显示进度条的,简单而且直观。(参考 python tqdm模块分析 、tqdm)
zipfile:是用来做zip格式编码的压缩和解压缩的。(参考 zipfile)
2. 下载数据集
将模型上传到云主机上计算的时候通常是先将数据集上传到网盘,再从网盘直接下载到云主机上,这样比采用本机上传要快很多。数据格式采用“.zip”格式。
def download(url, file): """ 从<url>处下载数据 :参数 url: 文件的URL :参数 file: 本地文件的路径 """ if not os.path.isfile(file): print('Downloading ' + file + '...') urlretrieve(url, file) print('Download Finished') # 分别下载训练集和测试集. download('https://s3.amazonaws.com/udacity-sdc/notMNIST_train.zip', 'notMNIST_train.zip') download('https://s3.amazonaws.com/udacity-sdc/notMNIST_test.zip', 'notMNIST_test.zip') # 校验MD5值,确保下载的数据是完整的 assert hashlib.md5(open('notMNIST_train.zip', 'rb').read()).hexdigest() == 'c8673b3f28f489e9cdf3a3d74e2ac8fa',\ 'notMNIST_train.zip file is corrupted. Remove the file and try again.' assert hashlib.md5(open('notMNIST_test.zip', 'rb').read()).hexdigest() == '5d3c7e653e63471c88df796156a9dfa9',\ 'notMNIST_test.zip file is corrupted. Remove the file and try again.' # 直到所有文件下载完,给出下列提示. print('All files downloaded.')
3. 解压特征和标签
自定义一个解压函数,从输入的zip文件中解压出features和labels,存储为numpy的数组格式。然后重采样出部分数据,方便后面快速测试模型。def uncompress_features_labels(file): """ 从zip文件中解压出features和labels :参数 file: 待解压文件 """ features = [] labels = [] with ZipFile(file) as zipf: # 进度条 filenames_pbar = tqdm(zipf.namelist(), unit='files') # 从所有文件中提取features和labels for filename in filenames_pbar: # 检查文件名是否为目录,不是则往下执行 if not filename.endswith('/'): #str.endswith() #ZipFile.open()以二进制的形式访问文件 with zipf.open(filename) as image_file: image = Image.open(image_file) image.load() # 将图像数据以一维矩阵形式存储 # 存储格式设定为 float32 feature = np.array(image, dtype=np.float32).flatten() # 提取文件名的首位,存储为对应的label。 # os.path.split()分割为“路径+文件名”,文件名中无'/' label = os.path.split(filename)[1][0] features.append(feature) labels.append(label) return np.array(features), np.array(labels) # 从zip文件中提取出train和test数据集中的features和labels train_features, train_labels = uncompress_features_labels('notMNIST_train.zip') test_features, test_labels = uncompress_features_labels('notMNIST_test.zip') # 重新采样,数据大小限制为docker_size_limit docker_size_limit = 150000 train_features, train_labels = resample(train_features, train_labels, n_samples=docker_size_limit) # 为特征工程设置标记,防止跳过重要步骤 is_features_normal = False is_labels_encod = False # 直到所有features和labels被解压,打印以下内容 print('All features and labels uncompressed.')
4. 特征工程
这里只进行features的归一化和labels的二值化(独热编码)。归一化 normalizing
对训练集和测试集的features进行归一化处理,这里用最小-最大规范化(Min-Max scaling)。Min-Max Scaling:
X′=a+(X−Xmin)(b−a)Xmax−Xmin
# 对于灰度图像数据的归一化 def normalize_grayscale(image_data): """ 将输入的最小最大值缩放到[0.1, 0.9] :参数 image_data: 待归一化的图像数据 :return: 归一化处理后的数据 """ a = 0.1 b = 0.9 grayscale_min = 0 grayscale_max = 255 return a + ( ( (image_data - grayscale_min)*(b - a) )/( grayscale_max - grayscale_min ) )
# 如果标记为False,则归一化处理,并置标记为True if not is_features_normal: train_features = normalize_grayscale(train_features) test_features = normalize_grayscale(test_features) is_features_normal = True
标签二值化
用sklearn.preprocessing中的
LabelBinarizer()对标签
A~F进行二值化处理,也即是独热编码(
One-Hot Encoding) 。
if not is_labels_encod: # 应用独热编码,将labels转化成数字(0/1表示) encoder = LabelBinarizer() encoder.fit(train_labels) train_labels = encoder.transform(train_labels) test_labels = encoder.transform(test_labels) # 转化为float32的格式,便于后面在TensorFlow可以进行乘法运算 train_labels = train_labels.astype(np.float32) test_labels = test_labels.astype(np.float32) is_labels_encod = True
划分验证集,随机打乱数据
首先检验特征工程是否完成,然后使用sklearn.model_selection中的
train_test_split将训练集随机划分为训练集和验证集。
assert is_features_normal, 'You skipped the step to normalize the features' assert is_labels_encod, 'You skipped the step to One-Hot Encode the labels' # 为训练集和验证集随机选取数据 train_features, valid_features, train_labels, valid_labels = train_test_split( train_features, train_labels, test_size=0.05, random_state=832289)
5. 数据保存
用pickle模块将处理好的数据存储成pickle格式,方便以后调用,即建立一个checkpoint。# 保存数据方便调用 pickle_file = 'notMNIST.pickle' if not os.path.isfile(pickle_file): #判断是否存在此文件,若无则存储 print('Saving data to pickle file...') try: with open('notMNIST.pickle', 'wb') as pfile: pickle.dump( { 'train_dataset': train_features, 'train_labels': train_labels, 'valid_dataset': valid_features, 'valid_labels': valid_labels, 'test_dataset': test_features, 'test_labels': test_labels, }, pfile, pickle.HIGHEST_PROTOCOL) except Exception as e: print('Unable to save data to', pickle_file, ':', e) raise print('Data cached in pickle file.')
pickle.HIGHEST_PROTOCOL:代表文件的协议版本,version 0~4,参考protocol version)
pickle.dump(obj, file[, protocol]):序列化数据,将
obj数据流写入到
file中,
file必须是可写入模式。
6. 数据载入
下一次加载文件时不用重新处理数据,可以从保存的pickle文件中直接加载,具体方法如下。%matplotlib inline #直接将绘图显示在当前页面,用于jupyter notebook # 加载模块 import pickle import math import numpy as np import tensorflow as tf from tqdm import tqdm import matplotlib.pyplot as plt # 读取数据 pickle_file = 'notMNIST.pickle' with open(pickle_file, 'rb') as f: pickle_data = pickle.load(f) # 反序列化,与pickle.dump相反 train_features = pickle_data['train_dataset'] train_labels = pickle_data['train_labels'] valid_features = pickle_data['valid_dataset'] valid_labels = pickle_data['valid_labels'] test_features = pickle_data['test_dataset'] test_labels = pickle_data['test_labels'] del pickle_data # 释放内存 print('Data and modules loaded.')
相关文章推荐
- python pickle模块使用-将内存数据保存到文本中以及从文本中直接读取信息到内存中
- python数据持久存储:pickle模块的基本使用
- python数据持久存储:pickle模块的基本使用
- python数据持久存储:pickle模块的基本使用
- [转]python数据持久存储:pickle模块的基本使用
- python数据持久存储:pickle模块的基本使用
- python数据持久存储:pickle模块的基本使用 分类: python python基础学习 python 小练习 2013-06-17 14:41 209人阅读 评论(0) 收藏
- python数据持久存储:pickle模块的基本使用
- python数据持久存储:pickle模块的基本使用
- python数据持久存储:pickle模块的基本使用
- Python中的数据对象持久化存储模块pickle的使用示例
- python数据持久存储:pickle模块的基本使用
- python数据持久存储:pickle模块的基本使用
- python数据持久存储:pickle模块的基本使用
- python数据持久存储:pickle模块的基本使用
- python数据持久存储:pickle模块的基本使用
- Python数据存储:pickle模块的使用讲解
- python数据持久存储:pickle模块的基本使用
- python数据持久存储:pickle模块的基本使用
- python数据持久存储:pickle模块的基本使用