Clasificación de texto con BERT Tokenizer y TF 2.0 en Python

BERT es una técnica de representación de texto similar a Word Embeddings. En este artículo, usaremos BERT y TensorFlow 2.0 para la clasificación de texto.

Este es el artículo 23 de mi serie de artículos sobre Python para PNL. En el Artículo anterior de esta serie, expliqué cómo realizar traducción automática neuronal usando [arquitectura seq2seq](https:/ /google.github.io/seq2seq/) con la biblioteca Keras de Python para el aprendizaje profundo.

En este artículo estudiaremos BERT, que significa Representaciones de codificador bidireccional de transformadores y su aplicación a la clasificación de texto. BERT es una técnica de representación de texto como Word Embeddings. Si no tiene idea de cómo funcionan las incrustaciones de palabras, consulte mi artículo sobre incrustaciones de palabras.

Al igual que las incrustaciones de palabras, BERT también es una técnica de representación de texto que es una fusión de una variedad de algoritmos de aprendizaje profundo de última generación, como el codificador bidireccional LSTM y Transformers. BERT fue desarrollado por investigadores de Google en 2018 y se ha demostrado que es de última generación para una variedad de tareas de procesamiento de lenguaje natural, como clasificación de texto, resumen de texto, generación de texto, etc. Recientemente, Google anunció que BERT se utiliza como parte central de su algoritmo de búsqueda para comprender mejor las consultas.

En este artículo no entraremos en los detalles matemáticos de cómo se implementa BERT, ya que hay muchos recursos disponibles en línea. Más bien, veremos cómo realizar la clasificación de texto utilizando el tokenizador BERT. En este artículo, verá cómo se puede usar el tokenizador BERT para crear un modelo de clasificación de texto. En el próximo artículo, explicaré cómo se puede usar el tokenizador BERT, junto con la capa de incrustación BERT, para crear modelos NLP aún más eficientes.

Nota: Todos los scripts de este artículo se probaron con el entorno Colaboración de Google, con el tiempo de ejecución de Python configurado en GPU.

El conjunto de datos

El conjunto de datos utilizado en este artículo se puede descargar desde este enlace Kaggle.

Si descarga el conjunto de datos y extrae el archivo comprimido, verá un archivo CSV. El archivo contiene 50.000 registros y dos columnas: revisión y opinión. La columna de reseña contiene el texto de la reseña y la columna de opinión contiene la opinión de la reseña. La columna de opinión puede tener dos valores, es decir, "positivo" y "negativo", lo que convierte a nuestro problema en un problema de clasificación binaria.

Anteriormente hemos realizado un análisis sentimental de este conjunto de datos en un Artículo anterior donde logramos el máximo precisión del 92% en el conjunto de entrenamiento a través de una técnica de incrustación de Word y una red neuronal convolucional. En el conjunto de prueba, la precisión máxima alcanzada fue del 85,40 % utilizando la incrustación de palabras y LSTM único con 128 nodos. Veamos si podemos obtener una mayor precisión utilizando la representación BERT.

Instalación e importación de bibliotecas requeridas {#instalación e importación de bibliotecas requeridas}

Antes de poder usar la representación de texto BERT, debe instalar BERT para TensorFlow 2.0. Ejecute los siguientes comandos pip en su terminal para instalar BERT para TensorFlow 2.0.

1
2
!pip install bert-for-tf2
!pip install sentencepiece

A continuación, debe asegurarse de que está ejecutando TensorFlow 2.0. Google Colab, de forma predeterminada, no ejecuta su secuencia de comandos en TensorFlow 2.0. Por lo tanto, para asegurarse de que está ejecutando su secuencia de comandos a través de TensorFlow 2.0, ejecute la siguiente secuencia de comandos:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
try:
    %tensorflow_version 2.x
except Exception:
    pass
import tensorflow as tf

import tensorflow_hub as hub

from tensorflow.keras import layers
import bert

En la secuencia de comandos anterior, además de TensorFlow 2.0, también importamos tensorflow_hub, que básicamente es un lugar donde puede encontrar todos los modelos preconstruidos y preentrenados desarrollados en TensorFlow. Importaremos y usaremos un modelo BERT incorporado desde el centro TF. Finalmente, si en el resultado ve el siguiente resultado, está listo para continuar:

1
TensorFlow 2.x selected.

Importación y preprocesamiento del conjunto de datos {#importación y preprocesamiento del conjunto de datos}

El siguiente script importa el conjunto de datos utilizando el método read_csv() del marco de datos de Pandas. El script también imprime la forma del conjunto de datos.

1
2
3
4
5
movie_reviews = pd.read_csv("/content/drive/My Drive/Colab Datasets/IMDB Dataset.csv")

movie_reviews.isnull().values.any()

movie_reviews.shape

Producción

1
(50000, 2)

El resultado muestra que nuestro conjunto de datos tiene 50 000 filas y 2 columnas.

A continuación, preprocesaremos nuestros datos para eliminar los signos de puntuación y los caracteres especiales. Para hacerlo, definiremos una función que tome como entrada una revisión de texto sin procesar y devuelva la revisión de texto limpia correspondiente.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def preprocess_text(sen):
    # Removing html tags
    sentence = remove_tags(sen)

    # Remove punctuations and numbers
    sentence = re.sub('[^a-zA-Z]', ' ', sentence)

    # Single character removal
    sentence = re.sub(r"\s+[a-zA-Z]\s+", ' ', sentence)

    # Removing multiple spaces
    sentence = re.sub(r'\s+', ' ', sentence)

    return sentence
1
2
3
4
TAG_RE = re.compile(r'<[^>]+>')

def remove_tags(text):
    return TAG_RE.sub('', text)

El siguiente script limpia todas las revisiones de texto:

1
2
3
4
reviews = []
sentences = list(movie_reviews['review'])
for sen in sentences:
    reviews.append(preprocess_text(sen))

Nuestro conjunto de datos contiene dos columnas, como se puede verificar a partir del siguiente script:

1
print(movie_reviews.columns.values)

Producción:

1
['review' 'sentiment']

La columna “revisión” contiene texto, mientras que la columna “opinión” contiene opiniones. La columna de sentimientos contiene valores en forma de texto. El siguiente script muestra valores únicos en la columna sentimiento:

1
movie_reviews.sentiment.unique()

Producción:

1
array(['positive', 'negative'], dtype=object)

Puede ver que la columna de opinión contiene dos valores únicos, es decir, “positivo” y “negativo”. Los algoritmos de aprendizaje profundo funcionan con números. Dado que solo tenemos dos valores únicos en la salida, podemos convertirlos en 1 y 0. El siguiente script reemplaza el sentimiento “positivo” por “1” y el sentimiento negativo por “0”.

1
2
3
y = movie_reviews['sentiment']

y = np.array(list(map(lambda x: 1 if x=="positive" else 0, y)))

Ahora la variable revisiones contiene reseñas de texto, mientras que la variable y contiene las etiquetas correspondientes. Vamos a imprimir aleatoriamente una reseña.

1
print(reviews[10])

Producción:

1
Phil the Alien is one of those quirky films where the humour is based around the oddness of everything rather than actual punchlines At first it was very odd and pretty funny but as the movie progressed didn find the jokes or oddness funny anymore Its low budget film thats never problem in itself there were some pretty interesting characters but eventually just lost interest imagine this film would appeal to stoner who is currently partaking For something similar but better try Brother from another planet 

Claramente parece una crítica negativa. Solo confirmémoslo imprimiendo el valor de la etiqueta correspondiente:

1
print(y[10])

Producción:

1
0

La salida 0 confirma que se trata de una revisión negativa. Ahora hemos preprocesado nuestros datos y ahora estamos listos para crear representaciones BERT a partir de nuestros datos de texto.

Crear un tokenizador BERT

Para usar las incrustaciones de texto BERT como entrada para entrenar el modelo de clasificación de texto, necesitamos tokenizar nuestras revisiones de texto. La tokenización se refiere a dividir una oración en palabras individuales. Para tokenizar nuestro texto, usaremos el tokenizador BERT. Mira el siguiente guión:

1
2
3
4
5
6
BertTokenizer = bert.bert_tokenization.FullTokenizer
bert_layer = hub.KerasLayer("https://tfhub.dev/tensorflow/bert_en_uncased_L-12_H-768_A-12/1",
                            trainable=False)
vocabulary_file = bert_layer.resolved_object.vocab_file.asset_path.numpy()
to_lower_case = bert_layer.resolved_object.do_lower_case.numpy()
tokenizer = BertTokenizer(vocabulary_file, to_lower_case)

En el script anterior, primero creamos un objeto de la clase FullTokenizer del módulo bert.bert_tokenization. A continuación, creamos una capa de incrustación BERT importando el modelo BERT desde hub.KerasLayer. El parámetro entrenable se establece en False, lo que significa que no entrenaremos la incorporación de BERT. En la siguiente línea, creamos un archivo de vocabulario BERT en forma de matriz numpy. Luego ponemos el texto en minúsculas y finalmente pasamos nuestras variables vocabulary_file y to_lower_case al objeto BertTokenizer.

Es pertinente mencionar que en este artículo, solo usaremos BERT Tokenizer. En el próximo artículo, usaremos BERT Embeddings junto con tokenizer.

Veamos ahora si nuestro tokenizador BERT realmente funciona. Para hacerlo, tokenizaremos una oración aleatoria, como se muestra a continuación:

1
tokenizer.tokenize("don't be so judgmental")

Producción:

1
['don', "'", 't', 'be', 'so', 'judgment', '##al']

Puede ver que el texto se tokenizó con éxito. También puede obtener los identificadores de los tokens utilizando convert_tokens_to_ids() del objeto tokenizador. Mira el siguiente guión:

1
tokenizer.convert_tokens_to_ids(tokenizer.tokenize("dont be so judgmental"))

Producción:

1
[2123, 2102, 2022, 2061, 8689, 2389]

Ahora definirá una función que acepta una sola revisión de texto y devuelve los identificadores de las palabras tokenizadas en la revisión. Ejecute el siguiente script:

1
2
def tokenize_reviews(text_reviews):
    return tokenizer.convert_tokens_to_ids(tokenizer.tokenize(text_reviews))

Y ejecute el siguiente script para tokenizar realmente todas las revisiones en el conjunto de datos de entrada:

1
tokenized_reviews = [tokenize_reviews(review) for review in reviews]

Preparación de datos para el entrenamiento

Las revisiones en nuestro conjunto de datos tienen diferentes duraciones. Algunas reseñas son muy pequeñas, mientras que otras son muy largas. Para entrenar el modelo, las oraciones de entrada deben tener la misma longitud. Para crear oraciones de igual longitud, una forma es rellenar las oraciones más cortas con ceros. Sin embargo, esto puede dar como resultado que una matriz dispersa contenga una gran cantidad de ceros. La otra forma es rellenar oraciones dentro de cada lote. Dado que entrenaremos el modelo en lotes, podemos rellenar las oraciones dentro del lote de entrenamiento localmente dependiendo de la longitud de la oración más larga. Para hacerlo, primero necesitamos encontrar la longitud de cada oración.

El siguiente script crea una lista de listas donde cada sublista contiene una revisión tokenizada, la etiqueta de la revisión y la duración de la revisión:

1
2
reviews_with_len = [[review, y[i], len(review)]
                 for i, review in enumerate(tokenized_reviews)]

En nuestro conjunto de datos, la primera mitad de las reseñas son positivas, mientras que la última mitad contiene reseñas negativas. Por lo tanto, para tener reseñas tanto positivas como negativas en los lotes de entrenamiento, necesitamos barajar las reseñas. El siguiente script mezcla los datos aleatoriamente:

1
random.shuffle(reviews_with_len)

Una vez que se mezclan los datos, los ordenaremos por la duración de las reseñas. Para ello, utilizaremos la función sort() de la lista y le diremos que queremos ordenar la lista con respecto al tercer elemento de la sublista, es decir, la duración de la reseña.

1
reviews_with_len.sort(key=lambda x: x[2])

Una vez que las reseñas están ordenadas por longitud, podemos eliminar el atributo de longitud de todas las reseñas. Ejecute el siguiente script para hacerlo:

1
sorted_reviews_labels = [(review_lab[0], review_lab[1]) for review_lab in reviews_with_len]

Una vez que se ordenen las revisiones, convertiremos el conjunto de datos para que pueda usarse para entrenar modelos de TensorFlow 2.0. Ejecute el siguiente código para convertir el conjunto de datos ordenado en una forma de conjunto de datos de entrada compatible con TensorFlow 2.0.

1
processed_dataset = tf.data.Dataset.from_generator(lambda: sorted_reviews_labels, output_types=(tf.int32, tf.int32))

Finalmente, ahora podemos rellenar nuestro conjunto de datos para cada lote. El tamaño de lote que vamos a utilizar es 32, lo que significa que después de procesar 32 revisiones, se actualizarán los pesos de la red neuronal. Para rellenar las revisiones localmente con respecto a los lotes, ejecute lo siguiente:

1
2
BATCH_SIZE = 32
batched_dataset = processed_dataset.padded_batch(BATCH_SIZE, padded_shapes=((None, ), ()))

Imprimamos el primer lote y veamos cómo se le ha aplicado el relleno:

1
next(iter(batched_dataset))

Producción:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
(<tf.Tensor: shape=(32, 21), dtype=int32, numpy=
 array([[ 2054,  5896,  2054,  2466,  2054,  6752,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0],
        [ 3078,  5436,  3078,  3257,  3532,  7613,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0],
        [ 3191,  1996,  2338,  5293,  1996,  3185,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0],
        [ 2062, 23873,  3993,  2062, 11259,  2172,  2172,  2062, 14888,
             0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0],
        [ 1045,  2876,  9278,  2023,  2028,  2130,  2006,  7922, 12635,
          2305,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0],
      ......
      
        [ 7244,  2092,  2856, 10828,  1997, 10904,  2402,  2472,  3135,
          2293,  2466,  2007, 10958,  8428, 10102,  1999,  1996,  4281,
          4276,  3773,     0],
        [ 2005,  5760,  7788,  4393,  8808,  2498,  2064, 12826,  2000,
          1996, 11056,  3152,  3811, 16755,  2169,  1998,  2296,  2028,
          1997,  2068,     0],
        [ 2307,  3185,  2926,  1996,  2189,  3802,  2696,  2508,  2012,
          2197,  2023,  8847,  6702,  2043,  2017,  2031,  2633,  2179,
          2008,  2569,  2619],
        [ 2028,  1997,  1996,  4569, 15580,  2102,  5691,  2081,  1999,
          3522,  2086,  2204, 23191,  5436,  1998, 11813,  6370,  2191,
          2023,  2028,  4438],
        [ 2023,  3185,  2097,  2467,  2022,  5934,  1998,  3185,  4438,
          2004,  2146,  2004,  2045,  2024,  2145,  2111,  2040,  6170,
          3153,  1998,  2552]], dtype=int32)>,
 <tf.Tensor: shape=(32,), dtype=int32, numpy=
 array([0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1,
        1, 1, 0, 1, 0, 1, 1, 0, 1, 1], dtype=int32)>)

El resultado anterior muestra las primeras cinco y las últimas cinco revisiones completas. De las últimas cinco revisiones, puede ver que el número total de palabras en la oración más grande fue 21. Por lo tanto, en las primeras cinco revisiones, se agregan 0 al final de las oraciones para que su longitud total también sea 21. El relleno para el próximo lote será diferente dependiendo del tamaño de la oración más grande del lote.

Una vez que hemos aplicado relleno a nuestro conjunto de datos, el siguiente paso es dividir el conjunto de datos en conjuntos de prueba y entrenamiento. Podemos hacerlo con la ayuda del siguiente código:

1
2
3
4
5
TOTAL_BATCHES = math.ceil(len(sorted_reviews_labels) / BATCH_SIZE)
TEST_BATCHES = TOTAL_BATCHES // 10
batched_dataset.shuffle(TOTAL_BATCHES)
test_data = batched_dataset.take(TEST_BATCHES)
train_data = batched_dataset.skip(TEST_BATCHES)

En el código anterior, primero encontramos el número total de lotes al dividir el total de registros por 32. Luego, el 10 % de los datos se reserva para la prueba. Para hacerlo, usamos el método take() del objeto batched_dataset() para almacenar el 10% de los datos en la variable test_data. Los datos restantes se almacenan en el objeto train_data para entrenar usando el método skip().

El conjunto de datos ha sido preparado y ahora estamos listos para crear nuestro modelo de clasificación de texto.

Creación del modelo

Ahora estamos listos para crear nuestro modelo. Para hacerlo, crearemos una clase llamada TEXT_MODEL que hereda de la clase tf.keras.Model. Dentro de la clase definiremos las capas de nuestro modelo. Nuestro modelo constará de tres capas de red neuronal convolucional. Puede usar capas LSTM en su lugar y también puede aumentar o disminuir la cantidad de capas. He copiado el número y tipos de capas de Cuaderno de colaboración de Google de SuperDataScience y esta arquitectura parece funcionar bastante bien para el conjunto de datos de reseñas de películas de IMDB también.

Ahora vamos a crear una clase modelo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class TEXT_MODEL(tf.keras.Model):
    
    def __init__(self,
                 vocabulary_size,
                 embedding_dimensions=128,
                 cnn_filters=50,
                 dnn_units=512,
                 model_output_classes=2,
                 dropout_rate=0.1,
                 training=False,
                 name="text_model"):
        super(TEXT_MODEL, self).__init__(name=name)
        
        self.embedding = layers.Embedding(vocabulary_size,
                                          embedding_dimensions)
        self.cnn_layer1 = layers.Conv1D(filters=cnn_filters,
                                        kernel_size=2,
                                        padding="valid",
                                        activation="relu")
        self.cnn_layer2 = layers.Conv1D(filters=cnn_filters,
                                        kernel_size=3,
                                        padding="valid",
                                        activation="relu")
        self.cnn_layer3 = layers.Conv1D(filters=cnn_filters,
                                        kernel_size=4,
                                        padding="valid",
                                        activation="relu")
        self.pool = layers.GlobalMaxPool1D()
        
        self.dense_1 = layers.Dense(units=dnn_units, activation="relu")
        self.dropout = layers.Dropout(rate=dropout_rate)
        if model_output_classes == 2:
            self.last_dense = layers.Dense(units=1,
                                           activation="sigmoid")
        else:
            self.last_dense = layers.Dense(units=model_output_classes,
                                           activation="softmax")
    
    def call(self, inputs, training):
        l = self.embedding(inputs)
        l_1 = self.cnn_layer1(l) 
        l_1 = self.pool(l_1) 
        l_2 = self.cnn_layer2(l) 
        l_2 = self.pool(l_2)
        l_3 = self.cnn_layer3(l)
        l_3 = self.pool(l_3) 
        
        concatenated = tf.concat([l_1, l_2, l_3], axis=-1) # (batch_size, 3 * cnn_filters)
        concatenated = self.dense_1(concatenated)
        concatenated = self.dropout(concatenated, training)
        model_output = self.last_dense(concatenated)
        
        return model_output

El script anterior es bastante sencillo. En el constructor de la clase, inicializamos algunos atributos con valores predeterminados. Estos valores serán reemplazados más adelante por los valores pasados ​​cuando se crea el objeto de la clase TEXT_MODEL.

A continuación, se han inicializado tres capas de red neuronal convolucional con los valores de kernel o filtro de 2, 3 y 4, respectivamente. Nuevamente, puede cambiar los tamaños de filtro si lo desea.

A continuación, dentro de la función call(), se aplica la agrupación máxima global a la salida de cada una de las capas de la red neuronal convolucional. Finalmente, las tres capas de la red neuronal convolucional se concatenan juntas y su salida se alimenta a la primera red neuronal densamente conectada. La segunda red neuronal densamente conectada se usa para predecir el sentimiento de salida, ya que solo contiene 2 clases. En caso de que tenga más clases en la salida, puede actualizar la variable output_classes en consecuencia.

Definamos ahora los valores de los hiperparámetros de nuestro modelo.

1
2
3
4
5
6
7
8
9
VOCAB_LENGTH = len(tokenizer.vocab)
EMB_DIM = 200
CNN_FILTERS = 100
DNN_UNITS = 256
OUTPUT_CLASSES = 2

DROPOUT_RATE = 0.2

NB_EPOCHS = 5

A continuación, necesitamos crear un objeto de la clase TEXT_MODEL y pasar los valores de hiperparámetros que definimos en el último paso al constructor de la clase TEXT_MODEL.

1
2
3
4
5
6
text_model = TEXT_MODEL(vocabulary_size=VOCAB_LENGTH,
                        embedding_dimensions=EMB_DIM,
                        cnn_filters=CNN_FILTERS,
                        dnn_units=DNN_UNITS,
                        model_output_classes=OUTPUT_CLASSES,
                        dropout_rate=DROPOUT_RATE)

Antes de que podamos entrenar el modelo, necesitamos compilarlo. El siguiente script compila el modelo:

1
2
3
4
5
6
7
8
if OUTPUT_CLASSES == 2:
    text_model.compile(loss="binary_crossentropy",
                       optimizer="adam",
                       metrics=["accuracy"])
else:
    text_model.compile(loss="sparse_categorical_crossentropy",
                       optimizer="adam",
                       metrics=["sparse_categorical_accuracy"])

Finalmente, para entrenar nuestro modelo, podemos usar el método fit de la clase del modelo.

1
text_model.fit(train_data, epochs=NB_EPOCHS)

Aquí está el resultado después de 5 épocas:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Epoch 1/5
1407/1407 [==============================] - 381s 271ms/step - loss: 0.3037 - accuracy: 0.8661
Epoch 2/5
1407/1407 [==============================] - 381s 271ms/step - loss: 0.1341 - accuracy: 0.9521
Epoch 3/5
1407/1407 [==============================] - 383s 272ms/step - loss: 0.0732 - accuracy: 0.9742
Epoch 4/5
1407/1407 [==============================] - 381s 271ms/step - loss: 0.0376 - accuracy: 0.9865
Epoch 5/5
1407/1407 [==============================] - 383s 272ms/step - loss: 0.0193 - accuracy: 0.9931
<tensorflow.python.keras.callbacks.History at 0x7f5f65690048>

Puede ver que obtuvimos una precisión del 99,31 % en el conjunto de entrenamiento.

Ahora vamos a evaluar el rendimiento de nuestro modelo en el conjunto de prueba:

1
2
results = text_model.evaluate(test_dataset)
print(results)

Producción:

1
156/Unknown - 4s 28ms/step - loss: 0.4428 - accuracy: 0.8926[0.442786190037926, 0.8926282]

A partir de la salida, podemos ver que obtuvimos una precisión del 89,26 % en el conjunto de prueba.

Yendo más lejos: proyecto de extremo a extremo portátil

¿Tu naturaleza inquisitiva te hace querer ir más allá? Recomendamos consultar nuestro Proyecto guiado: ["Subtítulos de imágenes con CNN y Transformers con Keras"](https://wikihtp.com/courses/image-captioning-with-cnns-and -transformadores-con-keras/#cta){target="_blank"}.

En este proyecto guiado, aprenderá a crear un modelo de subtítulos de imágenes, que acepta una imagen como entrada y produce un subtítulo de texto como salida.

Aprenderás a:

  • Preprocesar texto
  • Vectorizar la entrada de texto fácilmente
  • Trabaje con la API tf.data y cree conjuntos de datos de alto rendimiento
  • Cree Transformers desde cero con TensorFlow/Keras y KerasNLP: la adición horizontal oficial a Keras para crear modelos NLP de última generación
  • Cree arquitecturas híbridas donde la salida de una red se codifica para otra

¿Cómo enmarcamos los subtítulos de las imágenes? La mayoría lo considera un ejemplo de aprendizaje profundo generativo, porque estamos enseñando a una red a generar descripciones. Sin embargo, me gusta verlo como una instancia de traducción automática neuronal: estamos traduciendo las características visuales de una imagen en palabras. A través de la traducción, estamos generando una nueva representación de esa imagen, en lugar de simplemente generar un nuevo significado. Verlo como traducción, y solo por generación de extensión, enfoca la tarea bajo una luz diferente y la hace un poco más intuitiva.

Enmarcar el problema como uno de traducción hace que sea más fácil averiguar qué arquitectura querremos usar. Los transformadores solo de codificador son excelentes para comprender el texto (análisis de opinión, clasificación, etc.) porque los codificadores codifican representaciones significativas. Los modelos de solo decodificador son excelentes para la generación (como GPT-3), ya que los decodificadores pueden inferir representaciones significativas en otra secuencia con el mismo significado. La traducción generalmente se realiza mediante una arquitectura de codificador-decodificador, donde los codificadores codifican una representación significativa de una oración (o imagen, en nuestro caso) y los decodificadores aprenden a convertir esta secuencia en otra representación significativa que es más interpretable para nosotros (como una oración).

Conclusión

En este artículo, vio cómo podemos usar BERT Tokenizer para crear incrustaciones de palabras que se pueden usar para realizar la clasificación de texto. Realizamos un análisis sentimental de las reseñas de películas de IMDB y logramos una precisión del 89,26 % en el conjunto de prueba. En este artículo no usamos incrustaciones BERT, solo usamos BERT Tokenizer para tokenizar las palabras. En el próximo artículo, verá cómo se puede usar el tokenizador BERT junto con las incrustaciones BERT para realizar la clasificación de texto.