我有一个包含字符串和标签的数据框。我有一组特定的规则(我定义了一个
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
函数。tf.data.Dataset.from_generator
方法的数据生成器。我还没有实现这个,因为文档警告了这个方法的限制。string_to_number
转换在内存/磁盘上很昂贵。因此,即时执行此操作很重要。也许是这样的:
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)>