В настоящее время все говорят о вложениях слов (или символов, предложений, документов). Стоит ли использовать «Мешок слов»? Стоит ли применять встраивание в каком-либо сценарии?

Прочитав эту статью, вы узнаете:

  • Почему люди говорят, что встраивание слов - это серебряная пуля?
  • Когда «Мешок слов» побеждает вложения слов?
  • 3 основных подхода в Bag of Words
  • Как мы можем собрать «Мешок слов» в несколько строк?

Почему кто-то говорит, что вложения слов - это серебряная пуля?

В соответствии с последними достижениями в области НЛП встраивание - это успешный способ решить проблему, связанную с текстом, и превзойти Bag of Words (BoW). Действительно, BoW ввел ограничения, такие как большой размер функции, разреженное представление и т. Д. Что касается встраивания слов, вы можете проверить мой предыдущий пост.

Должны ли мы по-прежнему использовать BoW? Мы можем лучше использовать BoW в некоторых сценариях

Когда «Мешок слов» побеждает вложения слов?

Вы все равно можете использовать BoW вместо Word Embedding в следующих ситуациях:

  1. Построение базовой модели. Используя scikit-learn, нужно всего несколько строк кода для построения модели. Позже можно использовать Deep Learning, чтобы избавиться от этого.
  2. Если ваш набор данных невелик, а контекст зависит от предметной области, BoW может работать лучше, чем Word Embedding. Контекст очень зависит от предметной области, что означает, что вы не можете найти соответствующий вектор из предварительно обученных моделей встраивания слов (GloVe, fastText и т. Д.).

Как мы можем собрать «Мешок слов» в несколько строк?

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

Подсчитать количество

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

doc = "In the-state-of-art of the NLP field, Embedding is the \
success way to resolve text related problem and outperform \
Bag of Words ( BoW ). Indeed, BoW introduced limitations \
large feature dimension, sparse representation etc."
count_vec = CountVectorizer()
count_occurs = count_vec.fit_transform([doc])
count_occur_df = pd.DataFrame(
    (count, word) for word, count in
     zip(count_occurs.toarray().tolist()[0], 
    count_vec.get_feature_names()))
count_occur_df.columns = ['Word', 'Count']
count_occur_df.sort_values('Count', ascending=False, inplace=True)
count_occur_df.head()

Выход

Word: "of", Occurrence: 3
Word: "bow", Occurrence: 2
Word: "way", Occurrence: 1

Нормализованное количество вхождений

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

doc = "In the-state-of-art of the NLP field, Embedding is the \
success way to resolve text related problem and outperform \
Bag of Words ( BoW ). Indeed, BoW introduced limitations \
large feature dimension, sparse representation etc."
norm_count_vec = TfidfVectorizer(use_idf=False, norm='l2')
norm_count_occurs = norm_count_vec.fit_transform([doc])
norm_count_occur_df = pd.DataFrame(
    (count, word) for word, count in zip(
    norm_count_occurs.toarray().tolist()[0], 
    norm_count_vec.get_feature_names()))
norm_count_occur_df.columns = ['Word', 'Count']
norm_count_occur_df.sort_values(
    'Count', ascending=False, inplace=True)
norm_count_occur_df.head()

Выход

Word: "of", Occurrence: 0.4286
Word: "bow", Occurrence: 0.4286
Word: "way", Occurrence: 0.1429

Частота термина-обратная частота документов (TF-IDF)

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

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

doc = "In the-state-of-art of the NLP field, Embedding is the \
success way to resolve text related problem and outperform \
Bag of Words ( BoW ). Indeed, BoW introduced limitations \
large feature dimension, sparse representation etc."
tfidf_vec = TfidfVectorizer()
tfidf_count_occurs = tfidf_vec.fit_transform([doc])
tfidf_count_occur_df = pd.DataFrame(
    (count, word) for word, count in zip(
    tfidf_count_occurs.toarray().tolist()[0],   
    tfidf_vec.get_feature_names()))
tfidf_count_occur_df.columns = ['Word', 'Count']
tfidf_count_occur_df.sort_values('Count', ascending=False, inplace=True)
tfidf_count_occur_df.head()

Вывод (значение точно такое же, как нормализованное количество экземпляров, поскольку демонстрационный код включает только один документ)

Word: "of", Occurrence: 0.4286
Word: "bow", Occurrence: 0.4286
Word: "way", Occurrence: 0.1429

Код

В этом образце кода будет сравниваться количество появлений, нормализованное количество случаев и TF-IDF.

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

def build_model(mode):
    # Intent to use default paramaters for show case
    vect = None
    if mode == 'count':
        vect = CountVectorizer()
    elif mode == 'tf':
        vect = TfidfVectorizer(use_idf=False, norm='l2')
    elif mode == 'tfidf':
        vect = TfidfVectorizer()
    else:
        raise ValueError('Mode should be either count or tfidf')
    
    return Pipeline([
        ('vect', vect),
        ('clf' , LogisticRegression(solver='newton-cg',n_jobs=-1))
    ])

Наличие еще одной функции-примера для построения конвейера end-2-end

def pipeline(df, mode):
    x = preprocess_x(df)
    y = preprocess_y(df)
    
    model_pipeline = build_model(mode)
    cv = KFold(n_splits=10, shuffle=True)
    
    scores = cross_val_score(
        model_pipeline, x, y, cv=cv, scoring='accuracy')
    print("Accuracy: %0.4f (+/- %0.4f)" % (
        scores.mean(), scores.std() * 2))
    
    return model_pipeline

Давайте проверим количество слов, которые нам нужно обработать

x = preprocess_x(x_train)
y = y_train
    
model_pipeline = build_model(mode='count')
model_pipeline.fit(x, y)
print('Number of Vocabulary: %d'% (len(model_pipeline.named_steps['vect'].get_feature_names())))

Выход

Number of Vocabulary: 130107

Вызов конвейера путем передачи «count» (количество появлений), «tf» (нормализованное количество появлений) и «tfidf» (TF-IDF)

print('Using Count Vectorizer------')
model_pipeline = pipeline(x_test, y_test, mode='count')
print('Using TF Vectorizer------')
model_pipeline = pipeline(x_test, y_test, mode='tf')
print('Using TF-IDF Vectorizer------')
model_pipeline = pipeline(x_test, y_test, mode='tfidf')

Результат

Using Count Vectorizer------
Accuracy: 0.8892 (+/- 0.0198)
Using TF Vectorizer------
Accuracy: 0.8071 (+/- 0.0110)
Using TF-IDF Vectorizer------
Accuracy: 0.8917 (+/- 0.0072)

Заключение

Весь код вы можете узнать на гитхабе.

Исходя из предыдущего опыта, я попытался решить проблему классификации товарных категорий, дав краткое описание. Например, если дано «Свежее яблоко», а ожидаемая категория - «Фрукты». Уже сейчас можно получить точность 80+ за счет использования только метода подсчета вхождений.

В этом случае, поскольку количество слов на обучающую запись составляет всего несколько слов (от 2 до 10 слов). Возможно, использование встраивания слов не является хорошей идеей, поскольку для обучения векторов нет большого количества соседей (слов).

С другой стороны, scikit-learn предоставляет другой параметр для дальнейшей настройки входных данных модели. Возможно, вам придется взглянуть на следующие функции

  • ngram_range: вместо использования одного слова также можно определить ngram
  • двоичный: Помимо подсчета вхождений, можно выбрать двоичное представление.
  • max_features: вместо использования всех слов можно выбрать максимальное количество слов, чтобы уменьшить сложность и размер модели.

Кроме того, некоторые шаги предварительной обработки могут выполняться в указанной выше библиотеке, а не обрабатывать их самостоятельно. Например, удаление стоп-слова, строчные буквы и т. Д. Для большей гибкости я буду использовать свой собственный код для завершения шагов предварительной обработки.

Обо мне

Я специалист по анализу данных в Bay Area. Сосредоточение внимания на последних достижениях науки о данных, искусственного интеллекта, особенно в области НЛП и связанных с ними платформ. Вы можете связаться со мной из Medium Blog, LinkedIn или Github.