Архив метки: embedding

Пример классификации текстов на python с помощью fasttext

Fasttext это библиотека от фейсбука для создания векторного представления слов а также для классификации небольших текстов, а точнее — предложений. Основное отличие от самого известного векторного представления word2vec заключается в том, что каждое слово дополнительно дробится на символьные n-граммы, что позволяет решить проблему редких слов. Достоинством данного эмбеддинга также является высокая скорость работы и оптимизация под небольшие ресурсы (специально была оптимизирована под мобильные устройства).

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

Для установки воспользуемся командой:

pip3 install fasttext

Непосредственно пример:

import pandas as pd
import fasttext


# зададим набор текстов и меток классов
some_texts = [
   'текст номер один',
   'текст следующий под номером два',
   'третий набор слов',
   'что-то ещё для полноценного дата-сета',
   'пример текстового документа',
]
some_labels = [1, 1, 0, 0, 1]

# А теперь одно из разачарований имплементации именно этой библиотеки:
# Для обучения придется сделать файл, где целевой класс должен начинаться с __label__
df_train = pd.DataFrame({'txt': some_texts, 'target': some_labels})
df_train['target'] = df_train['target'].apply(lambda x: '__label__' + str(x))
df_train[['target', 'txt']].to_csv('train_data.txt', header=False, index=False, sep="\t")

# обучаем на 20 эпохах, полный набор гиперпараметров можно взглянуть на официальном сайте fasttext.cc
model = fasttext.train_supervised(input='train_data.txt', epoch=20)

# указываем чтобы отдавало вероятности обоих классов, по умолчанию k=1
p = model.predict('текст номер четыре', k=2)

print(p)
# (('__label__1', '__label__0'), array([0.5010367 , 0.49898329]))

Второе разачарование заключается в том, что в итоговом предсказании выдаётся сначала самый вероятный класс, и если требуется получить вероятность по конкретному классу, то нужно сначала узнать индекс нужного класса и только после этого по индексу взять вероятность. Для 2ух классов можно сделать примерно так:

    if p[0][0] == '__label__0':
        real_probability = p[1][1]
    else:
        real_probability = p[1][0]

В целом данный пример предлагается использовать для быстрого получения результата в задаче классификации текстов. Я попробовал код выше на соревновании mlbootcamp . ru по классификации экспертных вопросов и он показал результат из коробки лучше чем tf-idf: 0.73 fasttext против 0.68 tf-idf + lgbm