Простая классификация текста с использованием Fasttext

Быстрая и простая классификация текста с помощью Fasttext

Создайте модель классификации текста с помощью простого размеченного набора данных, библиотеки Fasttext и 10 минут

Введение

Обработка естественного языка применяется для деловых задач с экспоненциально возрастающей скоростью. Одной из простейших автоматизаций ИИ, способных преобразовать бизнес, является классификация текста, поскольку во многих случаях классификация текстовых данных выполняется вручную в трудоемком процессе.

Классификация текста заключается в разработке ИИ, способного присваивать метки входному тексту. Эти модели ИИ могут быть обучены как задача обучения с учителем, корректируя их веса на основе ранее увиденных примеров с соответствующими метками.

Для выполнения классификации текста на Python мы можем использовать fasttext. Fasttext – это легкая библиотека на Python с открытым исходным кодом, способная быстро и легко создавать модели классификации текста.

В этой демонстрации я буду использовать набор данных, доступный здесь. Этот набор данных состоит из твитов, связанных с коронавирусом, и связанных с ними настроений. Есть пять возможных классов: крайне негативный, негативный, нейтральный, положительный и крайне положительный. Мы будем использовать fasttext, чтобы создать модель ИИ для классификации твитов с использованием этого набора данных.

Один момент, на который следует обратить внимание, состоит в том, что существует серая зона между каждой из этикеток: например, где находится “граница” между положительным и крайне положительным? Или “отрицательный” и “крайне отрицательный”? Определенно есть некоторые твиты, которые попадают между этими двумя классами, и правильная метка может быть субъективной в отношении того, с какой стороны линии оказалась метка. В результате, вряд ли будет достигнута точность проверки 100%.

Если вы хотите попробовать код самостоятельно, ноутбук Kaggle доступен здесь.

Обработка

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

  1. process_data выбирает интересующие колонки (нам нужны только текст и связанные с ним метки). Для метки мы добавляем строку “__label__”, поскольку fasttext ожидает, что у меток будет такой префикс.
  2. split_data разделяет данные на обучающий набор, проверочный набор и тестовый набор.
  3. save_data_as_txt создает необходимые для fasttext txt-файлы. Fasttext ожидает наличие txt-файла, содержащего текст и связанные метки, то есть именно это создает эта функция.
def process_data(df_train: pd.DataFrame, df_test: pd.DataFrame) -> Tuple[pd.DataFrame, pd.DataFrame]:    df_train = df_train[["Sentiment", "OriginalTweet"]]    df_test = df_test[["Sentiment", "OriginalTweet"]]    df_train["Sentiment"] = df_train["Sentiment"].apply(lambda x: "__label__" + "_".join(a for a in x.split()))    df_test["Sentiment"] = df_test["Sentiment"].apply(lambda x: "__label__" + "_".join(a for a in x.split()))    return df_train, df_testdef split_data(df_train: pd.DataFrame, df_test: pd.DataFrame, train_fraction: float) -> Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:    split_point = round(df_train.shape[0] * train_fraction)    df_train, df_val = df_train.iloc[:split_point], df_train.iloc[split_point:]    return df_train, df_val, df_testdef save_data_as_txt(df_train: pd.DataFrame, df_validation: pd.DataFrame, df_test: pd.DataFrame) -> None:    df_train.to_csv(train_filepath,index=False,sep=" ",header=None,quoting=csv.QUOTE_NONE,quotechar="",escapechar=" ",)    df_validation.to_csv(validation_filepath,index=False,sep=" ",header=None,quoting=csv.QUOTE_NONE,quotechar="",escapechar=" ",)    df_test.to_csv(test_filepath,index=False,sep=" ",header=None,quoting=csv.QUOTE_NONE,quotechar="",escapechar=" ",)

Теперь нужно только установить некоторые пути и вызвать вышеуказанные функции, и у нас есть все данные, готовые для создания модели fasttext!

df_train = pd.read_csv("/kaggle/input/covid-19-nlp-text-classification/Corona_NLP_train.csv", encoding="latin1")df_test = pd.read_csv("/kaggle/input/covid-19-nlp-text-classification/Corona_NLP_test.csv", encoding="latin1")train_filepath = "df_train.txt"validation_filepath = "df_val.txt"test_filepath = "df_test.txt"df_train, df_test = process_data(df_train=df_train, df_test=df_test)df_train, df_validation, df_test = split_data(df_train=df_train, df_test=df_test, train_fraction=0.9)save_data_as_txt(df_train=df_train, df_validation=df_validation, df_test=df_test)

Оценка модели

На самом деле, всю сложную работу мы уже сделали. Чтобы оценить модель, достаточно вызвать метод

model = fasttext.train_supervised(input=str(train_filepath))

, и вуаля! У нас есть обученная модель.

Хотя наша модель обучена, мы не знаем насколько она хорошо справляется с задачей. Давайте напишем функцию, которая будет возвращать среднюю точность для всех классов меток:

def obtain_accuracies(model):    train_results = model.test(path=train_filepath)    validation_results = model.test(path=validation_filepath)    test_results = model.test(path=test_filepath)    return train_results, validation_results, test_results

Вызов этой функции с помощью

train_results, validation_results, test_results = obtain_accuracies(model=model)print(train_results, validation_results, test_results)

Позволяет увидеть базовую точность обучения 71.0%, точность проверки 54.1% и точность тестирования 48.4%. Неплохой результат для базовой модели!

Кроме того, как уже упоминалось во введении, если искусственный интеллект классифицирует текст с крайне отрицательным значением как “отрицательный”, это считается ошибкой при расчете точности. Так что многие ошибки, сделанные моделью, являются “с одной погрешностью”, что означает, что правильный ответ был одной из соседних меток.

Настройка гиперпараметров

На данный момент у нас есть базовая модель, которая показала приемлемые результаты. Как мы могли бы улучшить ее? К счастью, существует несколько гиперпараметров, которые можно передать в метод fasttext.train_supervised и попробовать изменить, чтобы улучшить производительность модели.

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

Какие наборы гиперпараметров мы должны попробовать? Хотя можно было бы попытаться вручную установить гиперпараметры и попытаться улучшить их сами (или использовать библиотеку настройки гиперпараметров, например Optuna), я слишком ленив для этого и предпочитаю просто использовать случайный поиск.

def create_training_params(baseline: bool = False) -> Dict[str, Any]:    if baseline:        return {}    epoch = random.randint(2, 120)    wordNgrams = random.randint(1, 6)    lr = np.random.uniform(0.02, 0.5)    dim = random.randint(50, 200)    minn = random.randint(0, 5)    maxn = random.randint(0, 5)    minCount = random.randint(1, 5)    ws = random.randint(2, 10)    lrUpdateRate = random.randint(50, 200)    bucket = random.randint(200000, 20000000)    return {        "epoch": epoch,        "wordNgrams": wordNgrams,        "lr": lr,        "dim": dim,        "minn": minn,        "maxn": maxn,        "minCount": minCount,        "lrUpdateRate": lrUpdateRate,        "ws": ws,        "bucket": bucket,        "thread": 12,    }

Эта функция будет возвращать набор случайно выбранных параметров.

Мы можем попробовать один набор случайных параметров, просто запустив:

model = fasttext.train_supervised(input=str(train_filepath), **create_training_params())

Добавим несколько строк кода для создания более полного процесса настройки гиперпараметров. Ниже мы указываем количество итераций поиска и инициализируем лучшую точность (best_accuracy) как точность базовой модели, а лучшие параметры (best_params) как пустой словарь (стандартные параметры).

Затем мы запускаем цикл, в котором каждая итерация случайным образом генерирует параметры, тренирует и оценивает модель. Если новая точность больше предыдущей записи, мы перезаписываем лучшую точность и сохраняем лучшие параметры для будущих ссылок.

iterations = 10best_accuracy, best_params = validation_results[1], {}for it in range(iterations):    params = create_training_params()    model = fasttext.train_supervised(input=str(train_filepath), **params)    train_results, validation_results, test_results = obtain_accuracies(model=model)    if validation_results[1] > best_accuracy:        best_accuracy = validation_results[1]        best_params = params    print(f"Лучшая точность на данный момент: {best_accuracy}")print(f"Лучшие параметры: {best_params}")

Таким образом, нам удалось достичь окончательной точности в 56,1%!

Заключение

Изучив другие блокноты с использованием данного набора данных, я могу увидеть решение с использованием наивного байесовского классификатора с точностью 70% или решение с использованием BERT с точностью 88%. Очевидно, это намного лучше, чем то, что мы получили с помощью fasttext. Однако в этих реализациях было применено значительное количество предварительной обработки текста набора данных, чего мы не делали.

Если текстовые данные не являются чистыми, искусственный интеллект fasttext может смотреть на неправильные данные, пытаясь найти паттерны для маркировки текста. Для улучшения производительности следует применить методы предварительной обработки к набору данных. Кроме того, в исходном наборе данных есть дополнительные столбцы, которые могут быть полезными для входных данных модели (мы использовали только столбцы с текстом и метками). Я оставлю следующие шаги вам, так как целью этой статьи является общий обзор библиотеки fasttext.

Мы узнали:

  • Что такое библиотека fasttext
  • Как предобработать набор данных для использования в fasttext
  • Как подгонять базовую модель на данных
  • Как настраивать гиперпараметры модели для улучшения результатов базовой модели

Спасибо за чтение до конца! Я надеюсь, что вам это будет полезно, и удачи в ваших задачах классификации текста.

Ссылки:

Linkedin: https://www.linkedin.com/in/sergei-issaev/

Github: https://github.com/sergeiissaev

Kaggle: https://www.kaggle.com/sergei416

VoAGI: https://medium.com/@sergei740

Twitter: https://twitter.com/realSergAI

Узнайте больше о Vooban: https://vooban.com/en