tf.data模块

本文介绍了如何利用tf.data模块构建输入流水线,处理大量数据、不同格式的数据,并进行了数据转换。通过示例展示了从创建Dataset到使用各种操作如take、shuffle、repeat、batch、map和zip的过程,以及在fashion_mnist数据集上的应用。

tf.data模块

import tensorflow as tf
tf.__version__

‘2.0.0’

tf.data模块用于构建输入,且可以处理大量数据、不同的数据格式,以及数据转换。

tf.data.Dateset表示一组数据。tf.data.Dateset中一个元素包含一个或者多个Tensor对象,例如一个元素代表单个训练样本或者代表一对训练数据和标签

创建Dataset

tf.data.Dataset.from_tensor_slices(tensors)
tensors可以为列表,字典,元组,numpy的ndarray,tensor
Dataset对象中每个元素的结构必须相同,一个元素可以包含一个或多个tensor对象,这些tensor对象被称为组件。
Dataset对象可以对其直接进行迭代使用

dataset = tf.data.Dataset.from_tensor_slices([1, 2, 3])
print(dataset)

<TensorSliceDataset shapes: (), types: tf.int32>

TensorSliceDataset shapes 表示Dataset中元素的shape,这里元素为数字,所以shapes为()

for element in dataset:
    print(element)

tf.Tensor(1, shape=(), dtype=int32)
tf.Tensor(2, shape=(), dtype=int32)
tf.Tensor(3, shape=(), dtype=int32)

可以用.numpy()的方法,对Tensor进行转换

for element in dataset:
    print(element.numpy())

1
2
3

用一个二维列表创建

dataset = tf.data.Dataset.from_tensor_slices([[1, 2], [3, 4]])
print(dataset)
print()
for element in dataset:
    print(element)
print()
for element in dataset:
    print(element.numpy())

<TensorSliceDataset shapes: (2,), types: tf.int32>

tf.Tensor([1 2], shape=(2,), dtype=int32)
tf.Tensor([3 4], shape=(2,), dtype=int32)

[1 2]
[3 4]

用字典类型创建
Dataset的每个元素就是一个字典

dict = {'a': [[1], [2]], 'b': [[3], [4]]}
dataset = tf.data.Dataset.from_tensor_slices(dict)
print(dataset)
print()
for element in dataset:
    print(element)
print()
for element in dataset:
    print(element['a'].numpy(), element['b'].numpy())

<TensorSliceDataset shapes: {a: (1,), b: (1,)}, types: {a: tf.int32, b: tf.int32}>

{‘a’: <tf.Tensor: id=43, shape=(1,), dtype=int32, numpy=array([1])>, ‘b’: <tf.Tensor: id=44, shape=(1,), dtype=int32, numpy=array([3])>}
{‘a’: <tf.Tensor: id=45, shape=(1,), dtype=int32, numpy=array([2])>, ‘b’: <tf.Tensor: id=46, shape=(1,), dtype=int32, numpy=array([4])>}

[1] [3]
[2] [4]

使用Dataset

Dataset.take(count) 从当前的Dataset里取出最多count个元素作为一个新的Dataset返回

import numpy as np
dataset = tf.data.Dataset.from_tensor_slices(np.array([1, 2, 3]))
for ele in dataset.take(2):
    print(ele.numpy())
print()
for ele in dataset.take(4):
    print(ele.numpy())

1
2

1
2
3

Dataset.shuffle(buffer_size) 将当前Dataset中buffer_size个元素填充缓冲区,在缓冲区进行随机采样。如:下面dataset中有6个元素,buffer_size为2,先把元素1,2放入缓冲区进行随机抽样,抽样完把下一个元素3放入缓冲区保持缓冲区的元素数为2,再继续抽样。

dataset = tf.data.Dataset.from_tensor_slices(np.array([1, 2, 3, 4, 5, 6]))
for ele in dataset.shuffle(2):
    print(ele.numpy())

2
1
3
5
6
4

Dataset.repeat(count) 将当前Dataset重复count次,count默认为None,表示一直重复

for ele in dataset.repeat(2):
    print(ele.numpy())

1
2
3
4
5
6
1
2
3
4
5
6

Dataset.batch(batch_size) 将Dataset中batch个元素合并为一个元素

for ele in dataset.batch(2):
    print(ele.numpy())

[1 2]
[3 4]
[5 6]

Dataset.map(map_func) 将Dataset的每个元素都用map_func处理

for ele in dataset.map(tf.square):
    print(ele.numpy())

1
4
9
16
25
36

Dataset.zip(datasets) 将datasets中各个dataset的对应元素合并为元组作为新的Dataset的元素

a = tf.data.Dataset.from_tensor_slices([[1], [2], [3]])
b = tf.data.Dataset.from_tensor_slices([4, 5, 6])
print(tf.data.Dataset.zip((a, b)))
print() 
for ele in tf.data.Dataset.zip((a, b)):
    print(ele[0], ele[1])

<ZipDataset shapes: ((1,), ()), types: (tf.int32, tf.int32)>

tf.Tensor([1], shape=(1,), dtype=int32) tf.Tensor(4, shape=(), dtype=int32)
tf.Tensor([2], shape=(1,), dtype=int32) tf.Tensor(5, shape=(), dtype=int32)
tf.Tensor([3], shape=(1,), dtype=int32) tf.Tensor(6, shape=(), dtype=int32)

示例 fashion_mnist数据集

读取数据集

(train_image, train_label), (test_image, test_label) = tf.keras.datasets.fashion_mnist.load_data()
print("train_image.shape:", train_image.shape)
print("train_label.shape:", train_label.shape)
print("test_image.shape:", test_image.shape)
print("test_label.shape:", test_label.shape)

train_image.shape: (60000, 28, 28)
train_label.shape: (60000,)
test_image.shape: (10000, 28, 28)
test_label.shape: (10000,)

train_image = train_image / 255.0
test_image  = test_image / 255.0

创建训练数据

train_img = tf.data.Dataset.from_tensor_slices(train_image)
train_lab = tf.data.Dataset.from_tensor_slices(train_label)
train_data = tf.data.Dataset.zip((train_img, train_lab))
print(train_data)

<ZipDataset shapes: ((28, 28), ()), types: (tf.float64, tf.uint8)>

batch_size = 128
train_data = train_data.shuffle(train_image.shape[0]).repeat().batch(batch_size)
print(train_data)

<BatchDataset shapes: ((None, 28, 28), (None,)), types: (tf.float64, tf.uint8)>

创建测试数据

test_data = tf.data.Dataset.from_tensor_slices((test_image, test_label))
print(test_data)

<TensorSliceDataset shapes: ((28, 28), ()), types: (tf.float64, tf.uint8)>

test_data = test_data.batch(batch_size)
print(test_data)

<BatchDataset shapes: ((None, 28, 28), (None,)), types: (tf.float64, tf.uint8)>

构建模型

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(10, activation='softmax')
])
model.summary()

Model: “sequential”
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
flatten (Flatten) (None, 784) 0
_________________________________________________________________
dense (Dense) (None, 128) 100480
_________________________________________________________________
dense_1 (Dense) (None, 10) 1290
=================================================================
Total params: 101,770
Trainable params: 101,770
Non-trainable params: 0
_________________________________________________________________

model.compile(optimizer=tf.keras.optimizers.Adam(),
              loss="sparse_categorical_crossentropy",
              metrics=['accuracy']
)
train_steps = train_image.shape[0] // batch_size
test_steps = test_image.shape[0] // batch_size
model.fit(train_data,
          epochs=5, 
          steps_per_epoch=train_steps,
          validation_data=test_data, 
          validation_steps=test_steps,
)

Train for 468 steps, validate for 78 steps
Epoch 1/5
468/468 [============================== ] - 3s 6ms/step - loss: 0.5548 - accuracy: 0.8091 - val_loss: 0.4598 - val_accuracy: 0.8394
Epoch 2/5
468/468 [============================== ] - 2s 4ms/step - loss: 0.4051 - accuracy: 0.8576 - val_loss: 0.4223 - val_accuracy: 0.8503
Epoch 3/5
468/468 [============================== ] - 2s 4ms/step - loss: 0.3666 - accuracy: 0.8704 - val_loss: 0.3969 - val_accuracy: 0.8596
Epoch 4/5
468/468 [============================== ] - 2s 4ms/step - loss: 0.3395 - accuracy: 0.8787 - val_loss: 0.3742 - val_accuracy: 0.8683
Epoch 5/5
468/468 [============================== ] - 2s 4ms/step - loss: 0.3235 - accuracy: 0.8835 - val_loss: 0.3619 - val_accuracy: 0.8715
<tensorflow.python.keras.callbacks.History at 0x1fa52321bc8>

<think>我们正在讨论TensorFlow的tf.data模块,特别是数据预处理部分。根据引用[1]和[2],我们知道tf.data API在TensorFlow 2.x中非常强大和灵活,适用于大规模数据集和复杂的数据预处理。引用[3][4][5]提供了一些具体的例子,包括图像预处理、文本处理等。 用户意图:用户想要一个关于使用tf.data进行数据预处理的详细教程。 我们将涵盖以下内容: 1. 数据预处理的基本流程 2. 常用预处理操作(map, filter, shuffle, batch, prefetch等) 3. 图像数据预处理示例(参考引用[4][5]) 4. 文本数据预处理示例 5. 性能优化技巧 注意:我们将使用引用中提供的例子,并适当扩展。</think>### TensorFlow tf.data 数据预处理详细教程 TensorFlow 的 `tf.data` API 提供了高效的数据预处理流水线构建能力,特别适用于大规模数据集和复杂转换场景[^1]。以下是关键技术的详细实现指南: --- #### 一、核心预处理操作 1. **`Dataset.map()` - 数据转换** 对每个元素应用自定义函数,支持并行处理: ```python # 图像标准化与增强 def preprocess_image(image, label): image = tf.image.resize(image, [256, 256]) # 调整尺寸 image = tf.image.random_flip_left_right(image) # 随机翻转 return image/255.0, label # 归一化[^4] dataset = dataset.map(preprocess_image, num_parallel_calls=tf.data.AUTOTUNE) ``` 2. **`Dataset.filter()` - 数据筛选** 根据条件过滤样本: ```python # 保留标签为0或1的样本 dataset = dataset.filter(lambda x, y: tf.reduce_any(y == [0, 1])) ``` 3. **`Dataset.shuffle()` - 数据打乱** 避免训练顺序偏差: ```python dataset = dataset.shuffle(buffer_size=1000, reshuffle_each_iteration=True) ``` --- #### 二、图像数据预处理(结合OpenCV)[^5] ```python import cv2 import tensorflow as tf # 自定义OpenCV读取函数 def _read_py_function(filename, label): image = cv2.imread(filename.decode(), cv2.IMREAD_COLOR) # 解码路径并读取 image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # 转换通道顺序 return image.astype(np.float32), label # TensorFlow格式转换 def _resize_function(image, label): image = tf.image.resize(image, [224, 224]) # 统一尺寸 image = tf.image.per_image_standardization(image) # 标准化 return image, label # 构建流水线 filenames = ["img1.jpg", "img2.jpg"] # 图像路径列表 labels = [0, 1] # 对应标签 dataset = tf.data.Dataset.from_tensor_slices((filenames, labels)) dataset = dataset.map( lambda f, l: tf.py_func(_read_py_function, [f, l], [tf.float32, tf.int32]), num_parallel_calls=8 ) dataset = dataset.map(_resize_function) # 应用预处理 ``` --- #### 三、文本数据预处理 ```python # 从文本文件创建数据集 dataset = tf.data.TextLineDataset(["texts.txt"]) # 文本清洗与分词 def tokenize(text): text = tf.strings.lower(text) # 小写化 text = tf.strings.regex_replace(text, r"[^\w\s]", "") # 移除非字母字符 tokens = tf.strings.split(text) # 分词 return tokens # 构建词表 vocab = ["<unk>", "the", "a", ...] # 预定义词表 table = tf.lookup.StaticVocabularyTable( tf.lookup.KeyValueTensorInitializer(vocab, tf.range(len(vocab))), num_oov_buckets=1 ) # 完整流水线 dataset = dataset.map(tokenize) dataset = dataset.map(lambda x: table.lookup(x)) # 词表索引化 dataset = dataset.padded_batch(32, padded_shapes=[None]) # 动态填充批次 ``` --- #### 四、结构化数据预处理(CSV) ```python dataset = tf.data.experimental.make_csv_dataset( "data.csv", batch_size=64, column_names=['feat1', 'feat2', 'label'], label_name='label', num_epochs=1 ) # 特征工程 def feature_engineering(features, label): features['new_feat'] = features['feat1'] * 0.5 + features['feat2'] # 创建新特征 return features, label dataset = dataset.map(feature_engineering) ``` --- #### 五、性能优化技巧 1. **流水线加速** ```python dataset = dataset.cache() # 缓存数据 .shuffle(1000) # 打乱顺序 .batch(256) # 批量处理 .prefetch(tf.data.AUTOTUNE) # 预加载下一批[^1] ``` 2. **并行化策略** ```python # 并行读取+并行处理 dataset = tf.data.TFRecordDataset(files, num_parallel_reads=8) dataset = dataset.map(parse_fn, num_parallel_calls=tf.data.AUTOTUNE) ``` 3. **内存优化** - 使用生成器处理超大数据: ```python def gen(): for i in range(1_000_000): yield np.random.rand(256, 256, 3) dataset = tf.data.Dataset.from_generator(gen, output_signature=tf.TensorSpec(shape=(256,256,3)) ``` --- #### 六、预处理模式对比 | 数据类型 | 推荐方法 | 关键操作 | |----------|----------|----------| | 图像 | `tf.py_func` + `map` | 尺寸调整/标准化/增强[^5] | | 文本 | `TextLineDataset` + 词表 | 分词/索引化/填充[^2] | | 结构化 | `make_csv_dataset` | 特征工程/类型转换[^1] | | 流式数据 | `from_generator` | 动态生成/内存优化[^4] | > **最佳实践**:对于超过50GB的数据集,优先使用`TFRecordDataset`格式,其I/O效率比原生方法高3-5倍[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值