如何预处理我的地图数据集以适应我的模型输入?

How can I preprocess my Mapdataset to fit my model input?

我使用由文本中的标签和字符串中的浮点矢量组成的 MapDataset。 这是我阅读 tfrecord 内容的方式:

def extract_data(tfrecord_ds):
    feature_description = {
        'classes_text': tf.io.FixedLenFeature((), tf.string),
        'data': tf.io.FixedLenFeature([], tf.string)
    }

def _parse_data_function(example_proto):
    return tf.compat.v1.parse_single_example(example_proto, feature_description)
parsed_dataset = tfrecord_ds.map(_parse_data_function)

dataset = parsed_dataset.cache().shuffle(1000).batch(32).prefetch(tf.data.AUTOTUNE)
return dataset

我想根据label.txt文件将label_text转换为int,将data字符串转换为浮点向量。

我想使用此数据来训练这样的自定义模型:

my_model = tf.keras.Sequential([
        tf.keras.layers.Input(shape=(1024), dtype=tf.float32,
                              name='input_embedding'),
        tf.keras.layers.Dense(512, activation='relu'),
        tf.keras.layers.Dense(num_classes)
    ], name='audio_detector')

如何将我的 MapDataset 从 (string,string) 处理为 (int, float_array) 以便能够训练我的模型?

编辑:

这是我对数据进行编码的方式:

 features = {}
                                features['classes_text'] = tf.train.Feature(
                                    bytes_list=tf.train.BytesList(value=[audio_data_generator.label.encode()]))
                                bytes = embedding.numpy().tobytes()
                                features['data'] = tf.train.Feature(bytes_list=tf.train.BytesList(value=[bytes]))
                                tf_example = tf.train.Example(features=tf.train.Features(feature=features))
                                writer.write(tf_example.SerializeToString())

使用 tf.train.FloatList 对嵌入进行编码更容易。

写入 tfrecords 时使用:

features = {
  'classes_text': tf.train.Feature(bytes_list=tf.train.BytesList(value=[label.encode()])),
  'data': tf.train.Feature(float_list=tf.train.FloatList(value=embedding))
}
tf_example = tf.train.Example(features=tf.train.Features(feature=features))
writer.write(tf_example.SerializeToString())

并在读取时将嵌入大小设为tf.io.FixedLenFeature,例如:

embedding_size = 10
feature_description = {
  'classes_text': tf.io.FixedLenFeature((), tf.string),
  'data': tf.io.FixedLenFeature([embedding_size], tf.float32)
}

要将 label_text 转换为整数,您可以使用 tf.lookup.StaticVocabularyTable.

# Assuming lable.txt contains a single label per line.
with open('label.txt', 'r') as fin:
  categories = [line.strip() for line in fin.readlines()]
init = tf.lookup.KeyValueTensorInitializer(
    keys=tf.constant(categories),
    values=tf.constant(list(range(len(categories))), dtype=tf.int64))
label_table = tf.lookup.StaticVocabularyTable(
   init,
   num_oov_buckets=1)

feature_description = {
  'classes_text': tf.io.FixedLenFeature((), tf.string),
  'data': tf.io.FixedLenFeature([embedding_size], tf.float32)
}

def _parse_data_function(example_proto):
  example = tf.compat.v1.parse_single_example(example_proto, feature_description)
  # Apply the label lookup.
  example['classes_text'] = label_table.lookup(example['classes_text'])
  return example

parsed_dataset = tfrecord_ds.map(_parse_data_function)

dataset = parsed_dataset.cache().shuffle(1000).batch(32).prefetch(tf.data.AUTOTUNE)

编辑

如果您希望保持保存数据的方式,您可以使用 np.frombuffer 将 numpy 向量转换为二进制字符串。不过,您必须将此代码包装在 tf.function 和 tf.py_function 中。

def decode_embedding(embedding_bytes):
  return np.frombuffer(embedding_bytes.numpy())
@tf.function()
def tf_decode_embedding(embedding_bytes):
  return tf.py_function(decode_embedding, inp=[embedding_bytes], Tout=tf.float32)

feature_description = {
        'classes_text': tf.io.FixedLenFeature((), tf.string),
        'data': tf.io.FixedLenFeature([], tf.string)
    }

def _parse_data_function(example_proto):
    example = tf.compat.v1.parse_single_example(example_proto, feature_description)
    example['classes_text'] = label_table.lookup(example['classes_text'])
    example['data'] = tf_decode_embedding(example['data'])
    return example

parsed_dataset = tfrecord_ds.map(_parse_data_function)

dataset = parsed_dataset.cache().shuffle(1000).batch(32).prefetch(tf.data.AUTOTUNE)