Tensorflow:如何在使用自定义 string_to_number 函数训练模型时即时将字符串输入转换为数字?

问题描述 投票:0回答:1

上下文

我有一个包含字符串和标签的数据框。我有一组特定的规则(我定义了一个

string_to_number
函数和一个编码字典)来将字符串值转换为 NumPy 数字数组。在下面的示例中,我将字符串转换为 RGB 值的 NumPy 数组。下面的代码为每个字符串字符使用 1 个像素,但我希望它是可定制的。我想训练一个基于
conv1d
的神经网络来执行基于标签的分类。

问题

如何使用我的

string_to_number
函数,以便它可以将字符串输入动态转换为 NumPy 数组,并将其提供给模型?还需要在批处理或整个数据集级别用零填充数据的可选能力。我什至需要填充卷积运算吗?

示例代码

import tensorflow as tf
import numpy as np
import pandas as pd

STRINGS = ['ABC', 'C', 'BA', 'AC', 'CAB']
LABELS = [0, 1, 2, 1, 3]

# create a dataframe with two columns, string and labels
df = pd.DataFrame({'string': STRINGS, 'label': LABELS})
df

输出:

  string  label
0    ABC      0
1      C      1
2     BA      2
3     AC      1
4    CAB      3

编码规则及作用:

ENCODING_DICT = {'A':[255, 0, 0], 'B':[0, 255, 0], 'C':[0, 0, 255]}

def string_to_number(
    string:str,
    encoding_dict:dict,
    pixels_per_character:int=1, # didn't use for the sake of simplicity
    pad_length:int=4):

    encoded_array = np.array([encoding_dict[char] for char in string])
    padded_array = np.zeros((1, 4, 3))
    padded_array[0, :encoded_array.shape[0], :] = encoded_array
    return padded_array

测试功能

string_to_number(STRINGS[0], ENCODING_DICT)

输出:

array([[[255.,   0.,   0.],
        [  0., 255.,   0.],
        [  0.,   0., 255.],
        [  0.,   0.,   0.]]])

型号和合身

# create a model
model = tf.keras.models.Sequential([
    # WHAT DO I DO HERE ________
    tf.keras.layers.Conv1D(3, 1, input_shape=(_____)),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(4, activation='softmax')
])
# compile and fit the model
model.compile ________
model.fit(df['string'], df['label'], ________)

我尝试过的方法

错误/试验太多,无法在此处详细介绍,但我希望以前构建过此类输入管道的人不需要这些细节。

  • lambda
    里面使用了一个
    tf.data.Dataset.map
    函数。
  • 使用自定义预处理头,如here所述。
  • 具有
    tf.data.Dataset.from_generator
    方法的数据生成器。我还没有实现这个,因为文档警告了这个方法的限制。

注:

  1. 数据集很大,
    string_to_number
    转换在内存/磁盘上很昂贵。因此,即时执行此操作很重要。
  2. 编码函数和映射字典比这里显示的更复杂。
python tensorflow keras conv-neural-network preprocessor
1个回答
0
投票

也许是这样的:

import tensorflow as tf
import pandas as pd

class TensorLookup:
  def __init__(self, keys, encoding):
    self.keys = keys
    self.encoding = encoding
    self.table = tf.lookup.StaticHashTable(
    tf.lookup.KeyValueTensorInitializer(self.keys, tf.range(tf.shape(self.keys)[0])),
    default_value=-1)
  
  def lookup(self, key):
    index = self.table.lookup(key)
    return tf.gather(self.encoding, index)


encoding = tf.constant([[255, 0, 0],                   
                        [0, 255, 0],
                        [0, 0, 255]], dtype=tf.int32)

encoding_dict = TensorLookup(keys = tf.constant(['a', 'b', 'c']), encoding = encoding)


STRINGS = ['ABC', 'C', 'BA', 'AC', 'CAB']
LABELS = [0, 1, 2, 1, 3]
df = pd.DataFrame({'string': STRINGS, 'label': LABELS})


model = tf.keras.models.Sequential([
    tf.keras.layers.Lambda(lambda x: tf.squeeze(tf.strings.bytes_split(tf.strings.lower(x)), axis=1), input_shape=(1, ), dtype=tf.string),
    tf.keras.layers.Lambda(lambda y: encoding_dict.lookup(y).to_tensor()),
    # .... other layers
])
model(df['string'].to_numpy()[..., None])
<tf.Tensor: shape=(5, 3, 3), dtype=int32, numpy=
array([[[255,   0,   0],
        [  0, 255,   0],
        [  0,   0, 255]],

       [[  0,   0, 255],
        [  0,   0,   0],
        [  0,   0,   0]],

       [[  0, 255,   0],
        [255,   0,   0],
        [  0,   0,   0]],

       [[255,   0,   0],
        [  0,   0, 255],
        [  0,   0,   0]],

       [[  0,   0, 255],
        [255,   0,   0],
        [  0, 255,   0]]], dtype=int32)>
© www.soinside.com 2019 - 2024. All rights reserved.