Классификация статей Bangla с помощью TF-Hub

Посмотреть на TensorFlow.org Запустить в Google Colab Посмотреть на GitHub Скачать блокнот

Это Colab является демонстрацией использования Tensorflow хаб для классификации текста в неанглийском / местных языках. Здесь мы выбираем Bangla как местный язык и использовать pretrained вложения слова для решения мультикласса классификации задач , где мы классифицируем Bangla новостных статьи в 5 категориях. В pretrained вложения для Bangla приходит из FastText который является библиотекой по Facebook с опубликованным pretrained векторов слов на 157 языках.

Мы будем использовать pretrained вложения экспортера TF-HUB для преобразования слова вложения в модуль текстового вложения первым , а затем использовать модуль для подготовки классификатора с tf.keras , высокого уровень удобного API Tensorflow, чтобы построить глубокие модели обучения. Даже если мы используем здесь встраивания fastText, можно экспортировать любые другие вложения, предварительно обученные из других задач, и быстро получить результаты с помощью концентратора Tensorflow.

Настраивать

# https://github.com/pypa/setuptools/issues/1694#issuecomment-466010982
pip install gdown --no-use-pep517
sudo apt-get install -y unzip
Reading package lists...
Building dependency tree...
Reading state information...
unzip is already the newest version (6.0-21ubuntu1.1).
The following packages were automatically installed and are no longer required:
  linux-gcp-5.4-headers-5.4.0-1040 linux-gcp-5.4-headers-5.4.0-1043
  linux-gcp-5.4-headers-5.4.0-1044 linux-gcp-5.4-headers-5.4.0-1049
  linux-headers-5.4.0-1049-gcp linux-image-5.4.0-1049-gcp
  linux-modules-5.4.0-1049-gcp linux-modules-extra-5.4.0-1049-gcp
Use 'sudo apt autoremove' to remove them.
0 upgraded, 0 newly installed, 0 to remove and 143 not upgraded.
import os

import tensorflow as tf
import tensorflow_hub as hub

import gdown
import numpy as np
from sklearn.metrics import classification_report
import matplotlib.pyplot as plt
import seaborn as sns
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/pkg_resources/__init__.py:119: PkgResourcesDeprecationWarning: 0.18ubuntu0.18.04.1 is an invalid version and will not be supported in a future release
  PkgResourcesDeprecationWarning,

Набор данных

Мы будем использовать Бард (Bangla Статья Dataset) , который имеет около 376226 статей , собранных из различных новостных порталов Bangla и меченных 5 категорий: экономики, государство, международные, спорт и развлечения. Скачиваем файл из Google Drive это ( bit.ly/BARD_DATASET ссылка) указывает ссылка из этого репозитория GitHub.

gdown.download(
    url='https://drive.google.com/uc?id=1Ag0jd21oRwJhVFIBohmX_ogeojVtapLy',
    output='bard.zip',
    quiet=True
)
'bard.zip'
unzip -qo bard.zip

Экспорт предварительно обученных векторов слов в модуль TF-Hub

TF-концентратор обеспечивает некоторые полезные скрипты для преобразования вложения слов в TF-концентраторов модулей текст встраиванию здесь . Для того, чтобы модуль для Bangla или любых других языках, мы просто должны загрузить слово вложение .txt или .vec файл в том же каталоге, export_v2.py и запустить скрипт.

Экспортер читает вложения векторов и экспортирует его в Tensorflow SavedModel . SavedModel содержит полную программу TensorFlow, включая веса и график. TF-концентратор может загрузить SavedModel как модуль , который мы будем использовать для построения модели для классификации текста. Так как мы используем tf.keras для построения модели, мы будем использовать hub.KerasLayer , который обеспечивает оболочку для модуля TF-концентратор для использования в качестве Keras слоя.

Во- первых , мы получим наши слова вложения от FastText и внедренный экспортер из TF-концентратора репо .

curl -O https://dl.fbaipublicfiles.com/fasttext/vectors-crawl/cc.bn.300.vec.gz
curl -O https://raw.githubusercontent.com/tensorflow/hub/master/examples/text_embeddings_v2/export_v2.py
gunzip -qf cc.bn.300.vec.gz --k
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  840M  100  840M    0     0  11.6M      0  0:01:12  0:01:12 --:--:-- 12.0M
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  7469  100  7469    0     0  19053      0 --:--:-- --:--:-- --:--:-- 19005

Затем мы запустим сценарий экспорта для нашего внедренного файла. Поскольку вложения fastText имеют строку заголовка и довольно большие (около 3,3 ГБ для Bangla после преобразования в модуль), мы игнорируем первую строку и экспортируем только первые 100 000 токенов в модуль встраивания текста.

python export_v2.py --embedding_file=cc.bn.300.vec --export_path=text_module --num_lines_to_ignore=1 --num_lines_to_use=100000
INFO:tensorflow:Assets written to: text_module/assets
I1105 11:55:29.817717 140238757988160 builder_impl.py:784] Assets written to: text_module/assets
module_path = "text_module"
embedding_layer = hub.KerasLayer(module_path, trainable=False)

Модуль встраивания текста принимает на входе пакет предложений в одномерном тензоре строк и выводит векторы внедрения формы (batch_size, embedding_dim), соответствующие предложениям. Он предварительно обрабатывает ввод, разбивая его на пробелы. Вложения слов комбинируются приговорить вложения с sqrtn объединителем (см здесь ). Для демонстрации мы передаем список слов Bangla в качестве входных данных и получаем соответствующие векторы внедрения.

embedding_layer(['বাস', 'বসবাস', 'ট্রেন', 'যাত্রী', 'ট্রাক'])
<tf.Tensor: shape=(5, 300), dtype=float64, numpy=
array([[ 0.0462, -0.0355,  0.0129, ...,  0.0025, -0.0966,  0.0216],
       [-0.0631, -0.0051,  0.085 , ...,  0.0249, -0.0149,  0.0203],
       [ 0.1371, -0.069 , -0.1176, ...,  0.029 ,  0.0508, -0.026 ],
       [ 0.0532, -0.0465, -0.0504, ...,  0.02  , -0.0023,  0.0011],
       [ 0.0908, -0.0404, -0.0536, ..., -0.0275,  0.0528,  0.0253]])>

Преобразовать в набор данных Tensorflow

Поскольку набор данных действительно большой , а не загружать весь набор данных в памяти , мы будем использовать генератор для получения образцов в время выполнения в пакетном режиме с использованием Tensorflow набора данных функций. Набор данных также очень несбалансирован, поэтому перед использованием генератора мы перетасуем набор данных.

dir_names = ['economy', 'sports', 'entertainment', 'state', 'international']

file_paths = []
labels = []
for i, dir in enumerate(dir_names):
  file_names = ["/".join([dir, name]) for name in os.listdir(dir)]
  file_paths += file_names
  labels += [i] * len(os.listdir(dir))

np.random.seed(42)
permutation = np.random.permutation(len(file_paths))

file_paths = np.array(file_paths)[permutation]
labels = np.array(labels)[permutation]

Мы можем проверить распределение меток в примерах обучения и проверки после перетасовки.

train_frac = 0.8
train_size = int(len(file_paths) * train_frac)
# plot training vs validation distribution
plt.subplot(1, 2, 1)
plt.hist(labels[0:train_size])
plt.title("Train labels")
plt.subplot(1, 2, 2)
plt.hist(labels[train_size:])
plt.title("Validation labels")
plt.tight_layout()

png

Для создания набора данных с помощью генератора, мы сначала напишем функцию генератора , который считывает каждый из статей file_paths и этикеток из массива этикеток, а также выходы один учебный пример на каждом шагу. Переходим эту функцию генератора в tf.data.Dataset.from_generator метод и указать типы выходных. Каждый учебный пример представляет собой кортеж , содержащий статью tf.string типа данных и один горячий кодированную метку. Мы разделили набор данных с раздельным железно-проверки в 80-20 с использованием tf.data.Dataset.skip и tf.data.Dataset.take методы.

def load_file(path, label):
    return tf.io.read_file(path), label
def make_datasets(train_size):
  batch_size = 256

  train_files = file_paths[:train_size]
  train_labels = labels[:train_size]
  train_ds = tf.data.Dataset.from_tensor_slices((train_files, train_labels))
  train_ds = train_ds.map(load_file).shuffle(5000)
  train_ds = train_ds.batch(batch_size).prefetch(tf.data.AUTOTUNE)

  test_files = file_paths[train_size:]
  test_labels = labels[train_size:]
  test_ds = tf.data.Dataset.from_tensor_slices((test_files, test_labels))
  test_ds = test_ds.map(load_file)
  test_ds = test_ds.batch(batch_size).prefetch(tf.data.AUTOTUNE)


  return train_ds, test_ds
train_data, validation_data = make_datasets(train_size)

Модельное обучение и оценка

Так как мы уже добавили обертку вокруг нашего модуля , чтобы использовать его как любой другой слой в Keras, мы можем создать небольшую Последовательную модель , которая представляет собой линейный набор слоев. Мы можем добавить наш текст , внедренный модуль с model.add так же , как любой другой слой. Скомпилируем модель, указав потерю и оптимизатор, и обучаем ее 10 эпох. tf.keras API может обрабатывать Tensorflow наборов данных в качестве входных данных, поэтому мы можем передать экземпляр Dataset к пригонкам способу обучения модели. Так как мы используем функцию генератора, tf.data будет обрабатывать генерируя образцы, дозирование их и кормить их к модели.

Модель

def create_model():
  model = tf.keras.Sequential([
    tf.keras.layers.Input(shape=[], dtype=tf.string),
    embedding_layer,
    tf.keras.layers.Dense(64, activation="relu"),
    tf.keras.layers.Dense(16, activation="relu"),
    tf.keras.layers.Dense(5),
  ])
  model.compile(loss=tf.losses.SparseCategoricalCrossentropy(from_logits=True),
      optimizer="adam", metrics=['accuracy'])
  return model
model = create_model()
# Create earlystopping callback
early_stopping_callback = tf.keras.callbacks.EarlyStopping(monitor='val_loss', min_delta=0, patience=3)

Обучение

history = model.fit(train_data, 
                    validation_data=validation_data, 
                    epochs=5, 
                    callbacks=[early_stopping_callback])
Epoch 1/5
1176/1176 [==============================] - 34s 28ms/step - loss: 0.2181 - accuracy: 0.9279 - val_loss: 0.1580 - val_accuracy: 0.9449
Epoch 2/5
1176/1176 [==============================] - 32s 27ms/step - loss: 0.1411 - accuracy: 0.9505 - val_loss: 0.1411 - val_accuracy: 0.9503
Epoch 3/5
1176/1176 [==============================] - 32s 27ms/step - loss: 0.1307 - accuracy: 0.9534 - val_loss: 0.1359 - val_accuracy: 0.9524
Epoch 4/5
1176/1176 [==============================] - 32s 27ms/step - loss: 0.1248 - accuracy: 0.9555 - val_loss: 0.1318 - val_accuracy: 0.9527
Epoch 5/5
1176/1176 [==============================] - 32s 27ms/step - loss: 0.1196 - accuracy: 0.9567 - val_loss: 0.1247 - val_accuracy: 0.9555

Оценка

Мы можем визуализировать точность и потерь данных кривых для обучения и проверки с использованием tf.keras.callbacks.History объекта , возвращаемый tf.keras.Model.fit метода, который содержит значение потерь и точности для каждой эпохи.

# Plot training & validation accuracy values
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Model accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()

# Plot training & validation loss values
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()

png

png

Прогноз

Мы можем получить прогнозы для данных проверки и проверить матрицу путаницы, чтобы увидеть производительность модели для каждого из 5 классов. Поскольку tf.keras.Model.predict метод возвращает массив я для вероятностей для каждого класса, они могут быть преобразованы в классе этикетки с использованием np.argmax .

y_pred = model.predict(validation_data)
y_pred = np.argmax(y_pred, axis=1)
samples = file_paths[0:3]
for i, sample in enumerate(samples):
  f = open(sample)
  text = f.read()
  print(text[0:100])
  print("True Class: ", sample.split("/")[0])
  print("Predicted Class: ", dir_names[y_pred[i]])
  f.close()
রবিন উইলিয়ামস তাঁর হ্যাপি ফিট ছবিতে মজা করে বলেছিলেন, ‘আমি শুনতে পাচ্ছি, মানুষ কিছু একটা চাইছে...সে
True Class:  entertainment
Predicted Class:  state

নির্মাণ শেষে ফিতা কেটে মন্ত্রী ভবন উদ্বোধন করেছেন বহু আগেই। তবে এখনো চালু করা যায়নি খাগড়াছড়ি জেল
True Class:  state
Predicted Class:  state

কমলাপুর বীরশ্রেষ্ঠ মোস্তফা কামাল স্টেডিয়ামে কাল ফকিরেরপুল ইয়ংমেন্স ক্লাব ৩-০ গোলে হারিয়েছে স্বাধ
True Class:  sports
Predicted Class:  state

Сравнить производительность

Теперь мы можем принимать правильные метки для проверки данных от labels и сравнить их с нашими прогнозами , чтобы получить classification_report .

y_true = np.array(labels[train_size:])
print(classification_report(y_true, y_pred, target_names=dir_names))
precision    recall  f1-score   support

      economy       0.83      0.76      0.79      3897
       sports       0.99      0.98      0.98     10204
entertainment       0.90      0.94      0.92      6256
        state       0.97      0.97      0.97     48512
international       0.92      0.93      0.93      6377

     accuracy                           0.96     75246
    macro avg       0.92      0.92      0.92     75246
 weighted avg       0.96      0.96      0.96     75246

Мы также можем сравнить производительность нашей модели с опубликованными результатами , полученных в оригинальной статье , которая была 0,96 точности .The оригинальных авторы описали много шагов предварительной обработки выполняются на наборе данных, например, падение пунктуации и цифр, удаление верхних 25 самых frequest стоп - слов. Как мы можем видеть в classification_report , мы также смогли получить 0,96 точность и точность после тренировки только 5 эпох без какой - либо предварительной обработки!

В этом примере, когда мы создали слой Keras из нашего модуля вложения, мы устанавливаем параметр trainable=False , что означает , что вложения вес не будет обновляться во время тренировки. Попробуйте установить значение True , чтобы достичь примерно 97% точности с помощью этого набора данных только после 2 эпох.