如何在不使用lambda层的情况下在自定义keras模型中使用tf.lookup?

时间:2020-10-05 01:29:25

标签: tensorflow keras deep-learning nlp

我尝试为 TextVectorization 创建自定义图层,该图层需要 tf.lookup.KeyValueTensorInitializer tf.lookup.StaticVocabularyTable 。更高的类需要int64才能生成查找表。我的文本向量化如下:

def standardization(text: tf.Tensor) -> tf.Tensor:
    text = tf.strings.substr(text, 0, 1000)
    text = tf.strings.lower(text)
    text = tf.strings.regex_replace(text, '<br\s+/>', ' ')
    text = tf.strings.regex_replace(text, '\n', ' ')
    text = tf.strings.regex_replace(text,
                                  '[%s]' % re.escape(string.punctuation),
                                  '')
    return text

def tokenization(text):
    return tf.strings.split(text).to_tensor(default_value='<pad>')

class MyTextVectorization(keras.layers.Layer):
    def __init__(self, vocab_size = 10000, num_oov_buckets=100, **kwargs):
        super().__init__(**kwargs)
        self.vocab_size = vocab_size
        self.num_oov_buckets = num_oov_buckets


    def adapt(self, batch_dataset):

        self.counter = Counter()

        for texts in batch_dataset:
            tokens = tokenization(standardization(texts))
            for text in tokens:
                text_numpy = text.numpy()
                for word in text_numpy:
                    self.counter[word] += 1

        # 
        most_common_word = self.counter.most_common(self.vocab_size)
        self.vocabs = [word[0] for word in most_common_word]
        self.word_index = {word[0]: ind for ind, word in enumerate(most_common_word)}
        self.index_word = {index: word for word, index in self.word_index.items()}

        self.initializer = tf.lookup.KeyValueTensorInitializer(self.vocabs, tf.range(len(self.vocabs), dtype=tf.int64))
        self.table = tf.lookup.StaticVocabularyTable(self.initializer, self.num_oov_buckets)

    def __call__(self, texts):
        tokens = tokenization(standardization(texts))
        sequences = tf.cast(self.table.lookup(tokens), dtype=tf.int32)
        return tokens

然后,在创建MyTextVectorization实例并对其进行适应后,我创建了这样的顺序模型。

my_textvect = MyTextVectorization(input_shape=(), dtype=tf.string)
my_textvect.adapt(so_trainset.map(lambda x, y : x))

export_model = keras.models.Sequential([
                                        my_textvect,
                                        so_model, ## pretrain RNN which use my_textvect outside the keras model to process the texts
                                        keras.layers.Activation('softmax')
])

错误显示如下
ValueError: Tensor conversion requested dtype int32 for Tensor with dtype int64: <tf.Tensor 'Cumsum_5:0' shape=(None,) dtype=int64>

但是,如果我使用Lambda层(在我的情况下不理想),则可以很好地创建模型。

export_model = keras.models.Sequential([
                                        keras.layers.Lambda(my_textvect),
## The rest is the same

我想知道这里是什么问题?我试图将MyTextVectorization的输出强制转换为int32,如上所示,但仍然无法正常工作。在这种情况下,我宁愿不使用lambda层,因为tensorflow考试限制了我们不要使用lambda层! (实验性TextVectorization层也是如此)。

先谢谢大家。

0 个答案:

没有答案