TensorFlow2 Data API CSV读取与解析

TensorFlow2中tf.data.Dataset中的from_tensor_slices()函数介绍,函数参数可以为普通列表,也可以为numpy数组,还可以为字典

此函数作用为将给定的数据做成TensorFlow的Dataset数据格式

为方便例子展示,引入所需的包

# tf.data 数据处理API
import tensorflow as tf
import numpy as np
import pandas as pd
import sklearn
import matplotlib
import os
import sys
import time
%matplotlib inline # 在jupyter中实现图形展示

from matplotlib import pyplot as plt
from tensorflow import keras
from sklearn.preprocessing import StandardScaler

例子:

1. 从内存中构建数据

dataset1 = tf.data.Dataset.from_tensor_slices(np.arange(10))

这样就得到一个基础的Dataset,拿到一个Dataset后最基础的操作就是对其进行遍历

for item in dataset1:

    print(item)

而在深度学习中,对Dataset的最基本的操作有以下两个

1. repeat epoch 神经网络重复对数据进行遍历

2. get batch 神经网络批次进行训练

那么TensorFlow2中的Dataset有以下操作方法

dataset1 = dataset1.repeat(5).batch(9)

就是对数据集遍历5次,而batch_size为9

 

3. Dataset的interleave函数

此方法的三个参数:

1、map_fn 对数据集中的元素进行变换的函数(通常会用lambda表达式的方式给出)

2、cycle_length 对数据集处理时,指定多少个线程并行处理

3、block_length 对处理后的数据每次取出多少个元素

例:

dataset2 = dataset1.interleave(

    lambda v : tf.data.Dataset.form_tensor_slices(v),

    cycle_length = 5,

    block_length = 5

)

 

# 输入为元组
x = np.array([[1, 2], [3, 4], [5, 6]])
y = np.array(['cat', 'dog', 'fox'])

dataset3 = tf.data.Dataset.from_tensor_slices((x, y))

for x_item, y_item in dataset3:
print(x_item.numpy(), y_item.numpy())
 
# 输入为字典
dataset4 = tf.data.Dataset.from_tensor_slices({'feature' : x,
'label': y})
for item in dataset4:
print(item['feature'].numpy(), item['label'].numpy())
 
 
# 生成csv文件,并从csv文件中读取数据生成dataset
# 把之前的房价预测的数据集生成csv文件
from sklearn.datasets import fetch_california_housing
housing = fetch_california_housing()

from sklearn.model_selection import train_test_split

x_train_all, x_test, y_train_all, y_test = train_test_split(
housing.data, housing.target, random_state = 7
)

# 切分训练集和验证集
x_train, x_valid, y_train, y_valid = train_test_split(
x_train_all, y_train_all, random_state = 11
)

# 对数据进行归一化
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
x_train_scaled = scaler.fit_transform(x_train)
x_valid_scaled = scaler.transform(x_valid)
x_test_scaled = scaler.transform(x_test)
 
# 将上述数据生成csv文件
# 创建保存数据的目录
output_dir = 'generate_housing_csv'
if not os.path.exists(output_dir):
os.mkdir(output_dir)

def save_to_csv(output_dir, data, name_prefix, header=None, n_parts=10):
"""
output_dir : 数据保存目录
data: 需要保存的数据(将训练数据和标签进行merge)
name_prefix: 数据前缀(因为数据有训练数据和标签, 所以用前缀进行区分)
header: csv文件的头部
n_parts: 将数据切分成几份去保存
"""
path_format = os.path.join(output_dir, "{}_{:02d}.csv")
filenames = []

# np.arry_split(array, integer)对数组进行拆分, 拆分成integer份, 返回一个数组的列表
# enumerate 枚举序列中的每个元素, 返回子元素以及对应的索引值
for file_idx, row_indices in enumerate(
np.array_split(np.arange(len(data)), n_parts)):

# 生成对应的子文件名
part_csv = path_format.format(name_prefix, file_idx)

# 加入到文件列表中
filenames.append(part_csv)

# 写文件
with open(part_csv, "wt", encoding="utf-8") as f:

# 如果header不为空, 先写入header
if header is not None:
f.write(header + "\n")
 
# 循环得到索引的行号, 并通过data[行号]取得数据, 再将数据中的每一列转成字符串然后用,拼接
for row_indice in row_indices:
f.write(",".join(repr(col) for col in data[row_indice]))
f.write("\n")

return filenames

# 对数据进行merge
# np.c_()函数,对数据按行进行merge
train_data = np.c_[x_train_scaled, y_train]
valid_data = np.c_[x_valid_scaled, y_valid]
test_data = np.c_[x_test, y_test]

# 创建header
headers_cols = housing.feature_names + ["MidianHouseValue"]

# join() 函数, 将序列中的元素按指定的字符连接形成新的字符串
header_strs = ",".join(headers_cols)
 
# 生成文件
train_filenames = save_to_csv(output_dir, train_data, "train", header=header_strs, n_parts=20)
valid_filenames = save_to_csv(output_dir, valid_data, "valid", header=header_strs, n_parts=10)
test_filenames = save_to_csv(output_dir, test_data, "test", header=header_strs, n_parts=10)
 
这样就会生成20个训练数据集文件,10个验证数据集文件和10个测试数据集文件。

 

2、解析CSV文件并生成训练batch数据

# 根据csv文件名读取数据
# filenames -> dataset
# read file -> dataset -> datasets -> merge
filename_dataset = tf.data.Dataset.list_files(train_filenames)
for item in filename_dataset:
print(item)
 
# 读取文件,根据文件名读取CSV文件,并跳过header行
n_readers = 5
dataset = filename_dataset.interleave(
lambda filename : tf.data.TextLineDataset(filename).skip(1),
cycle_length = n_readers
)

# 读取到的CSV文件内容为一个字符串
for line in dataset.take(5):
print(line.numpy())
 
# 解析CSV中的一行
def parse_csv_file(line, n_fields=9):
"""
运用tf.io.decode_csv()函数解析csv文件内容
该函数有两个参数
第一个为要解析的字符串内容
第二个是一个列表(解析后的每个字段所对应的数据类型,
一般默认为tf.float32。np.nan默认就是float32类型)
line: 解析的CSV文件的一行的内容
n_fields: 每行中有多少个元素
"""

# np.nan 默认为tf.float32类型, 则生成具有n_fields个float32的值
defs = [tf.constant(np.nan)] * n_fields
parsed_fields = tf.io.decode_csv(line, record_defaults=defs)

# 由于housing数据集有8个特征值,最后一个是标签,所以要把前八个特征值组成向量,最后一个值组成标签
# 用tf.stack将特征值转化为向量
x = tf.stack(parsed_fields[0:-1])
y = tf.stack(parsed_fields[-1:])

return x, y
 
# 整体的函数解析CSV文件
# 1、filename -> filename_dataset
# 2、read file -> dataset -> datasets -> merge
# 3、parse csv
def csv_reader_dataset(filenames, n_readers=5, batch_size=32, n_parse_threads=5,
shuffle_buffer_size=10000):
"""
filenames: 文件名列表
n_readers: 并行处理线程数
batch_size: 批次大小
n_parse_threads: CSV解析时的并行线程数
shuffle_buffer_size: shuffle数据时的buffer
"""
filenames_dataset = tf.data.Dataset.list_files(filenames)
filenames_dataset = filename_dataset.repeat()
 
# 读取所有文件名所对应的文件内容,并拼接成一个数据集
# 最终返回的数据集是interleave函数中的每个文件内容的组合
dataset = filename_dataset.interleave(
lambda filename: tf.data.TextLineDataset(filename).skip(1),
cycle_length=n_readers
)

dataset.shuffle(shuffle_buffer_size)

# 对数据集中的所有行数据都进行parse_csv_file中的操作,然后返回操作后的数据集
# 也就是说原来数据集中有多少个元素,map之后还是有多少个元素
dataset = dataset.map(parse_csv_file,
num_parallel_calls=n_parse_threads)
dataset = dataset.batch(batch_size)

return dataset
 
 
batch_size = 32
train_set = csv_reader_dataset(train_filenames, batch_size=batch_size)
for x_batch, y_batch in train_set:
print(x_batch, y_batch)
 
这样就得到训练数据集上的一个batch,对于验证集合测试集是一样的
valid_set  = csv_reader_dataset(valid_filenames, batch_size=batch_size)
test_set = csv_reader_dataset(test_filenames, batch_size=batch_size)

你可能感兴趣的:(TensorFlow2 Data API CSV读取与解析)