机器学习实战笔记——第十三章

一、数据 API

        使用 tf.data.Dataset.from_tensor_slices 创建一个数据集:

dataset = tf.data.Dataset.from_tensor_slices(tf.range(10))

print(dataset, tf.range(10))
for item in dataset:
    print(item)

        结果如下:

机器学习实战笔记——第十三章_第1张图片

from_tensor_slices

        该函数创建一个给定张量的切片(沿第一个维度)。给定的张量沿它们的第一维进行切片。此操作保留输入张量的结构,删除每个张量的第一个维度并将其用作数据集维度。所有输入张量的第一维必须具有相同的大小。

from_tensor_slices(
    tensors
)

1.1 链式转换

dataset = dataset.repeat(3).batch(7, drop_remainder=True)

for item in dataset:
    print("repeat(3).batch: ", item)

dataset = dataset.map(lambda x: x * 2)

for item in dataset:
    print("map: ", item)

dataset = dataset.apply(tf.data.experimental.unbatch())

for item in dataset:
    print("apply: ", item)

dataset = dataset.filter(lambda x: x < 10)

for item in dataset:
    print("filter: ", item)

for item in dataset.take(3):
    print("take: ", item)

        可以对数据集进行转换,每个方法都会返回一个新的数据集而不是对原有数据集改动。所以需要新的变量来保存新数据集。Dateset 的方法如下

1.1.1 repeat

        重复数据集 count 次。

repeat(
    count=None
)
参数 注释
count 一个 tf.int64,表示数据集应该重复的次数。默认行为(如果 countNone-1)是无限期重复数据集。

1.1.2 batch

        将此数据集的连续元素组合成批。

batch(
    batch_size, drop_remainder=False, num_parallel_calls=None, deterministic=None
)
参数 注释
batch_size 在单个批次中组合的此数据集的连续元素的数量
drop_remainder 表示在最后一批少于元素的情况下是否应该删除它 ;
其它
tf.data.Dataset  |  TensorFlow Core v2.6.0

1.1.3 map

        映射数据集的元素。

map(
    map_func, num_parallel_calls=None, deterministic=None
)
参数 注释
map_func 映射函数
其它 tf.data.Dataset  |  TensorFlow Core v2.6.0

1.1.4 apply

        转换整个数据集

apply(
    transformation_func
)
参数 注释
transformation_func 接受一个 Dataset 参数并返回一个 Dataset 的函数

         示例如下:

dataset = tf.data.Dataset.range(100)

def dataset_fn(ds):
  return ds.filter(lambda x: x < 5)

dataset = dataset.apply(dataset_fn)
print(list(dataset.as_numpy_iterator()))

1.1.5 filter

         过滤数据集。

filter(
    predicate
)
参数 注释
predicate 将数据集元素映射到布尔值的函数

1.2 乱序数据

        当训练数据集独立且均匀分布时,梯度下降效果最佳,可以通过 shuffle 方法对实例进行乱序,该函数会创建一个新的数据集,首先将源数据集的第一个元素填充到缓冲区中,并用源数据集中的新元素替换它,需要指定缓冲区的大小,并且可以提供随机种子。

dataset = tf.data.Dataset.range(10).repeat(3)
dataset = dataset.shuffle(buffer_size=5, seed=42).batch(7)

for item in dataset:
    print("shuffle:", item)

         如果在经过乱序的数据集上调用 repeat 函数,默认情况下会在每次迭代生成一个新次序;如果希望每次迭代重用相同的顺序,可以设置 reshuffle_each_iteration = False 。

        但是对于不适合内存的大型数据集,缓冲区会很小,上述方法的作用很小。可以将源数据拆分成多个文件,在训练过程中以随机顺序读取它们,由于同一文件中的实例接近,可以同时读取多个文件并交错读取记录。

# 设 train_filepaths 为文件匹配集合
filepath_datasets = tf.data.Dataset.list_files(train_filepaths, seed=42)

        接下来可以调用 interleave 方法一次读取多个文件:

dataset = filepath_datasets.interleave(lambda filepath: tf.data.TextLineDataset(filepath).skip(1), cycle_length=5)

        默认情况下,interleave 不使用并行,它顺序的从每个文件中一次读取一行,若希望并行读取,可以将 num_parallel_calls 参数设置为所需的线程数。

1.2.1 shuffle

shuffle(
    buffer_size, seed=None, reshuffle_each_iteration=None
)
参数 注释
buffer_size 新数据集的取样数量
其它 tf.data.Dataset  |  TensorFlow Core v2.6.0

1.2.2 list_files

list_files(
    file_pattern, shuffle=None, seed=None
)
参数 注释
file_pattern 表示将匹配的文件名全局模式。
shuffle 文件是否被打乱
seed 随机种子

1.2.3 interleave

interleave(
    map_func, cycle_length=None, block_length=None, num_parallel_calls=None,
    deterministic=None
)
参数 注释
map_func 映射数据集的函数
cycle_length 同时输入的数量
其它 tf.data.Dataset  |  TensorFlow Core v2.6.0

1.2.4 tf.data.TextLineDataset

        加载文本文件,并创建一个数据集,其中文件的每一行成为数据集的元素。

tf.data.TextLineDataset(
    filenames, compression_type=None, buffer_size=None, num_parallel_reads=None
)
参数 注释
filenames 一个或多个文件名。
其它 tf.data.TextLineDataset  |  TensorFlow Core v2.6.0

1.3 预处理数据

1.4 预取

1.4.1 prefetch

        创建从该数据集预取元素的数据集。这允许在处理当前元素时准备后面的元素。这通常会提高延迟和吞吐量,但代价是使用额外的内存来存储预取的元素。

prefetch(
    buffer_size
)

二、TFRecord

        TFRecord 格式是 Tensorflow 的首选格式,用于存储大量数据并有效读取数据,它只包含大小不同的二进制记录序列(一个长度、一个用于检查长度是否损坏的 CRC 校验、实际数据和最后一个 CRC 校验和)。使用方式如下:

with tf.io.TFRecordWriter('tfr.tfrecord') as f:
    f.write(b"the first")
    f.write(b"the second")

filepaths = ["tfr.tfrecord"]
dataset = tf.data.TFRecordDataset(filepaths)
for item in dataset:
    print(item)

tf.io.TFRecordWriter

tf.io.TFRecordWriter(
    path, options=None
)

tf.io.TFRecordWriter  |  TensorFlow Core v2.6.0

 tf.data.TFRecordDataset

tf.data.TFRecordDataset(
    filenames, compression_type=None, buffer_size=None, num_parallel_reads=None
)
参数 注释
filenames 一个或多个文件名
num_parallel_reads 表示要并行读取的文件数。如果大于1,则并行读取的文件记录以交错顺序输出。
其它 tf.data.TFRecordDataset  |  TensorFlow Core v2.6.0

2.1 压缩文件

        有时候压缩文件会很有用,可以通过设置 options 参数来创建压缩的 TFRecord 文件:

options = tf.io.TFRecordOptions(compression_type="GZIP")
with tf.io.TFRecordWriter('tfr2.tfrecord', options=options) as f:
    f.write(b"the first")
    f.write(b"the second")

2.1.1 tf.io.TFRecordOptions

        用于操作 TFRecord 文件的选项。

tf.io.TFRecordOptions(
    compression_type=None, flush_mode=None, input_buffer_size=None,
    output_buffer_size=None, window_bits=None, compression_level=None,
    compression_method=None, mem_level=None, compression_strategy=None
)
参数 注释
compression_type "GZIP""ZLIB", 或""(无压缩)
其它 tf.io.TFRecordOptions  |  TensorFlow Core v2.6.0

2.2 Tensorflow 协议

        Tensorflow 文件通常使用 Example protobuf ,这表示一个数据集的实例,可以通过 tf.train.Example 来创建一个实例。

person_example = tf.train.Example(
    features=tf.train.Features(
        feature={
            "name": tf.train.Feature(bytes_list=tf.train.BytesList(value=[b"Alice"])),
            "id": tf.train.Feature(int64_list=tf.train.Int64List(value=[123])),
            "emails": tf.train.Feature(tf.train.Feature(bytes_list=tf.train.BytesList(value=[b"[email protected]", b"[email protected]"])))
        }
    )
)

        然后可以调用 SerializeToString 方法对其序列化并将记录写入 TFRecord 文件中。

with tf.io.TFRecordWriter('tfr3.tfrecord') as f:
    f.write(person_example.SerializeToString())

        可以创建一个转换脚本,从当前格式如 CSV 中读取记录,为每个记录创建一个 Example protobuf 并序列化,然后保存的 TFRecord 文件中,最好处理过程乱序。

2.3 加载和解析 Example

        要加载序列化的  Example protobuf ,需要使用 tf.io.parse_single_example 来解析每个 Example ,它需要两个参数,一个是包含序列化数据的字符串标量张量,另一个是关于特征的描述,对上节的 Example 的特征描述如下:

feature_description = {
    "name": tf.io.FixedLenFeature([], tf.string, default_value=""),
    "id": tf.io.FixedLenFeature([], tf.int64, default_value=0),
    "emails": tf.io.VarLenFeature(tf.string)
}

       然后遍历 TFRecord Dataset 并解析序列化的 Example protobuf :

for example in tf.data.TFRecordDataset(['tfr3.tfrecord']):
    print(tf.io.parse_single_example(example, feature_description))

       固定长度特征被解析为规则张量,可变长度则解析为稀疏张量,可以通过 tf.sparse.to_dense 来将稀疏张量转换为密集张量。

        可以在 BytesList 中包含任何需要的二进制数据,如对一个 JPEG 格式的图像采用 tf.io.encode_jgp 编码,并将编码得到的二进制数据放入 ByteList 中,在解析后调用 tf.io.decode_jpeg 来获取原始图像 (或者通过 tf.io.decode_image 来解码任何图像)。也可以通过 tf.io.serialize_tensor() 来序列化张量并存储在 ByteList 中,然后调用 tf.io.parse_tensor 来解析。

        除此之外可以通过使用 tf.io.parse_example 一个批次地解析。

2.3.1 tf.io.FixedLenFeature

        用于解析固定长度输入特征的配置

tf.io.FixedLenFeature(
    shape, dtype, default_value=None
)
  • shape:输入数据的形状。
  • dtype: 输入的数据类型。
  • default_value:如果示例缺少此功能时使用的值。它必须与dtype指定的 和兼容shape 

tf.io.FixedLenFeature  |  TensorFlow Core v2.6.0

2.3.2 tf.io.VarLenFeature

        用于解析可变长度输入特征的配置 

tf.io.VarLenFeature(
    dtype
)

tf.io.VarLenFeature  |  TensorFlow Core v2.6.0

2.3.3 tf.io.parse_single_example

        解析单个Exampleproto

tf.io.parse_single_example(
    serialized, features, example_names=None, name=None
)

tf.io.parse_single_example  |  TensorFlow Core v2.6.0

2.3.4 tf.io.parse_example

        将Exampleprotos解析dict为张量。

tf.io.parse_example(
    serialized, features, example_names=None, name=None
)

tf.io.parse_example  |  TensorFlow Core v2.6.0

2.4 使用 SequenceExample Protobuf 处理列表的列表

2.4.1 tf.io.parse_single_sequence_example

tf.io.parse_single_sequence_example(
    serialized, context_features=None, sequence_features=None, example_name=None,
    name=None
)

 tf.io.parse_single_sequence_example  |  TensorFlow Core v2.6.0

2.4.2 tf.io.parse_sequence_example

tf.io.parse_sequence_example(
    serialized, context_features=None, sequence_features=None, example_names=None,
    name=None
)

tf.io.parse_sequence_example  |  TensorFlow Core v2.6.0

三、预处理输入特征

        为神经网络准备的数据需要全转化为数值特征(归一化等),对于分类特征或文本特征,需要将其转化为数字,其中一种方法就是在模型中包含预处理层。可以使用 Lambda 层实现标准下,代码参考如下:

model = keras.Sequential([
    keras.layers.Lambda(lambda inputs: (inputs - means) / (std + eps))
])

        但更倾向一个自包含自定义层,首先需要创建一个继承 keas.layers.Layer 类:

class Standardization(keras.layers.Layer):
    def adapt(self, data):
        self.means_ = np.mean(data, axis=0, keepdims=True)
        self.stds_ = np.std(data, axis=0, keepdims=True)

    def call(self, inputs):
        return (inputs - self.means) / (self.stds_ + keras.backend.epsilon())

        首先创建一个该类的对象,并通过调用 adapt 方法来创建均值和方差,然后可以通过 model.add 方法将该层添加到模型中。现在可以使用 tf.keras.layers.Normalization 代替上述过程。

tf.keras.layers.Lambda

        将任意表达式包装为Layer对象

tf.keras.layers.Lambda(
    function, output_shape=None, mask=None, arguments=None, **kwargs
)
参数 注释
function 函数表达式
其它 tf.keras.layers.Lambda  |  TensorFlow Core v2.6.0

tf.keras.layers.Normalization

tf.keras.layers.Normalization(
    axis=-1, mean=None, variance=None, **kwargs
)

 tf.keras.layers.Normalization  |  TensorFlow Core v2.6.0

3.1 使用独热向量编码分类特征

vocab = ['1H OCEAN', 'INLAND', 'NEAR OCEAN', 'NEAR BAY', 'ISLAND']
indices = tf.range(len(vocab), dtype=tf.int64)
table_init = tf.lookup.KeyValueTensorInitializer(vocab, indices)
table = tf.lookup.StaticVocabularyTable(table_init, 2)

        上述代码中首先定义词汇表,然后创建带有相应索引的张量,为每个查找表创建一个初始化程序并将类别列表及索引传递给它,最后创建查找表,为其提供了初始化程序并制定了词汇表外桶的数量。如果查找词汇表中不存在的类别则查找表将计算该类的哈希并将这个未知类别分配给 oov 桶中的一个,计算出的索引从已知类别开始。

        然后就可以根据查找表将一小批分类特征编码为独热向量。

categories = tf.constant(['NEAR BAY', 'DESERT', 'INLAND', 'INLAND'])
cat_indices = table.lookup(categories)
cat_one_hot = tf.one_hot(cat_indices, depth=len(vocab) + 2)

        如果想将上述程序封装到一个类中,也需要一个 adapt 方法提取样本类别,并调用 call 方法建立映射。现在可以通过 tf.keras.layers.TextVectorization 实现。

3.1.1 tf.keras.layers.TextVectorization

tf.keras.layers.TextVectorization(
    max_tokens=None, standardize='lower_and_strip_punctuation',
    split='whitespace', ngrams=None, output_mode='int',
    output_sequence_length=None, pad_to_max_tokens=False, vocabulary=None, **kwargs
)

tf.keras.layers.TextVectorization  |  TensorFlow Core v2.6.0 

 

你可能感兴趣的:(机器学习,tensorflow,机器学习,python)