`InaccessibleTensorError` с лямбда-функцией keras с использованием обнимающего лица BertModel - PullRequest
0 голосов
/ 19 февраля 2020

Я загружаю предварительно обученную модель Берта, чтобы выполнить классификацию текста. По умолчанию transformers.TFBertModel возвращает hidden_states только последнего слоя, где я могу извлечь первый токен и использовать его для классификации текста.

Однако я хочу извлечь векторные представления первого токена не из последнего ОДНОГО слоя, а из последних ЧЕТЫРЕХ слоев. Поэтому я пишу лямбда-слой, чтобы объединить четыре вектора первого токена (каждый из одного из четырех последних слоев) в один более длинный вектор. Вот где у меня проблема. Вот код для импорта модулей и определения функции.

import tensorflow as tf
from keras.layers import Input, Lambda
from transformers import BertConfig, TFBertModel

config = BertConfig(output_hidden_states=True)
bert_layer = TFBertModel.from_pretrained('bert-base-uncased', config=config)

@tf.function
def concat_layers(layers, nlayer=4):
    # input layers shape: a tuple of 13 layers, where each is of [# batches, # tokens, # features]
    # output ans shape: [# batches, # tokens, # features*nlayer]

    # stack the last 12 layers into dim of [# layers, # batches, # tokens, # features]
    layers = tf.stack(layers[1:], axis=0)

    # permute dimensions into [# batches, # tokens, # layers, # features]
    layers = tf.transpose(layers, (1, 2, 0, 3))

    # for each token, loop to slice last n-layers and reshape them into a vector
    ans = []
    for batch in layers:
        tans = []
        for token in batch:
            vec = tf.squeeze(tf.reshape(token[-nlayer:], (1, -1)))
            tans.append(vec)
        tans = tf.stack(tans, axis=0)
        ans.append(tans)
    ans = tf.stack(ans, axis=0)

    return ans

Хорошо работает с

input1 = Input(shape=(500,), dtype=tf.int32, name='inputs')
input2 = Input(shape=(500,), dtype=tf.int32, name='masks')
input3 = Input(shape=(500,), dtype=tf.int32, name='segments')
last_layer, first_token, layers = bert_layer([input1, input2, input3])

Но когда я делаю

layers = Lambda(function=concat_layers)(layers)

Он сообщает об ошибке :

InaccessibleTensorError: in converted code:

    <ipython-input-125-09697873bb2c>:17 concat_layers  *
        tans = tf.stack(tans, axis=0)
    /usr/local/lib/python3.6/dist-packages/tensorflow_core/python/util/dispatch.py:180 wrapper
        return target(*args, **kwargs)
    /usr/local/lib/python3.6/dist-packages/tensorflow_core/python/ops/array_ops.py:1255 stack
        return gen_array_ops.pack(values, axis=axis, name=name)
    /usr/local/lib/python3.6/dist-packages/tensorflow_core/python/ops/gen_array_ops.py:5704 pack
        "Pack", values=values, axis=axis, name=name)
    /usr/local/lib/python3.6/dist-packages/tensorflow_core/python/framework/op_def_library.py:742 _apply_op_helper
        attrs=attr_protos, op_def=op_def)
    /usr/local/lib/python3.6/dist-packages/tensorflow_core/python/framework/func_graph.py:591 _create_op_internal
        inp = self.capture(inp)
    /usr/local/lib/python3.6/dist-packages/tensorflow_core/python/framework/func_graph.py:641 capture
        % (tensor, tensor.graph, self))

    InaccessibleTensorError: The tensor 'Tensor("Squeeze:0", shape=(3072,), dtype=float32)' cannot be accessed here: it is defined in another function or code block. Use return values, explicit Python locals or TensorFlow collections to access it. Defined in: FuncGraph(name=while_body_687352, id=139971488261848); accessed from: FuncGraph(name=while_body_687327, id=139971488296744).

UPDATE NOTE

Я сузил проблему. Но не знаю, как это решить. Проблема связана с циклом. Именно это конкретное утверждение и вызывает проблему.

vec = tf.squeeze(tf.reshape(token[-nlayer:], (1, -1)))

Если я заменим решение с зацикливанием тока на векторизованное решение, как показано ниже, то оно будет работать.

ans = tf.reshape(tmat, (bs, nt, -1, nlayer, 768))
ans = ans[:, :, -1, :, :]
ans = tf.squeeze(tf.reshape(ans, (bs, nt, 1, -1)), 2)

, где bs - размер партии, nt - количество токенов (ограничено 512 для Берта).

Возможно ли решение для зацикливания, которое является более гибким, чем мое векторизованное решение, которое может только 1, 2, 3, 4, 6, 12 слоев, но не 5, 7, 8, 9, 10, 11 (т.е. 12% nlayer == 0).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...