В настоящее время компании продвигают свои продукты и услуги, используя интернет-платформы и социальные сети. Растущее использование социальных сетей и Интернета коренным образом изменило то, как люди покупают товары. Клиенты также могут получить улучшенный доступ к информации о продукте через социальные сети. Согласно исследованиям, клиенты доверяют онлайн-оценкам потребителей больше, чем информации, предлагаемой поставщиками (Salehan et al., 2016). Кроме того, онлайн-отзывы клиентов более ориентированы на пользователя и описывают продукты с точки зрения пользователя.

Ожидается, что механизм «голосования за полезность» принесет Amazon.com дополнительный доход в размере 2,7 млрд долларов (Cao et al., 2011). Для любой фирмы очень важно понимать, какие элементы влияют на полезность интернет-обзоров. Это может помочь владельцам интернет-бизнеса увеличить доход за счет создания и развертывания автоматизированной системы для категоризации большого объема данных из онлайн-отзывов потребителей.

Определения проблем

Целью данной работы является создание автоматизированной системы категоризации на основе текста, которая может с высокой точностью прогнозировать полезность онлайн-отзывов потребителей на Amazon. Задача состоит в том, чтобы выполнить бинарную классификацию, используя комбинацию текстовых функций и алгоритмов машинного обучения. Бинарные классификации будут указаны следующим образом: «1» означает «Полезно», а «0» означает «Бесполезно». Количество пользователей, проголосовавших за отзыв как «полезный», будет использоваться для расчета оценки полезности. В этом исследовании будут использоваться различные текстовые функции, в том числе матричные векторизованные функции, функции на основе встраивания слов, а также структурные, синтаксические, семантические функции и функции метаданных, полученные из обзорного и сводного текста.

"Источник данных"

Набор данных Amazon Fine Food Reviews состоит из обзоров изысканных продуктов от Amazon.

Количество отзывов: 568 454
Количество пользователей: 256 059
Количество товаров: 74 258
Период времени: октябрь 1999 г. — октябрь 2012 г.
Количество атрибутов/столбцов в данных: 10

Информация об атрибутах:

  1. Id
  2. ProductId — уникальный идентификатор товара.
  3. UserId — уникальный идентификатор пользователя
  4. Имя профиля
  5. HelpfulnessNumerator — количество пользователей, которым отзыв был полезен.
  6. HelpfulnessDenominator — количество пользователей, которые указали, считают ли отзыв полезным или нет.
  7. Score — оценка от 1 до 5
  8. Time — временная метка обзора.
  9. Резюме — краткое изложение обзора
  10. Текст — текст обзора

Цель

Учитывая отзыв, определите, является ли он положительным (рейтинг 4 или 5) или отрицательным (рейтинг 1 или 2).

[В] Как узнать, положительный отзыв или нет?
[Ответ] Мы можем использовать систему оценки/оценки. Положительным отзывом можно считать оценку в 4 или 5 звезд. Оценка 1 или 2 может быть истолкована как неблагоприятная. Отзыв 3 является нейтральным и игнорируется. Это приблизительный и косвенный способ определения полярности (положительность/отрицательность) отзыва.

Загрузка данных

%matplotlib inline
import warnings
warnings.filterwarnings («игнорировать»)

импортировать sqlite3
импортировать pandas как pd
импортировать numpy как np
импортировать nltk
импортировать строку
импортировать matplotlib.pyplot как plt
импортировать seaborn как sns
из sklearn.feature_extraction.text импортировать TfidfTransformer
из sklearn.feature_extraction.text импортировать TfidfVectorizer

из sklearn.feature_extraction.text импортировать CountVectorizer
из sklearn.metrics импортировать путаницу_матрицу
из sklearn импортировать метрики
из sklearn.metrics импортировать roc_curve, auc
из nltk.stem.porter импортировать PorterStemmer

import re
# Учебник по регулярным выражениям Python: https://pymotw.com/2/re/
import string
from nltk.corpus import стоп-слова
from nltk.stem import PorterStemmer
из nltk.stem.wordnet импорт WordNetLemmatizer

из gensim.models импортировать Word2Vec
из gensim.models импортировать KeyedVectors
импортировать pickle

из tqdm import tqdm
import os

кон = sqlite3.connect('база данных.sqlite')

filtered_data = pd.read_sql_query(""" SELECT * FROM Reviews WHERE Score != 3 LIMIT 5000"", con)

def partition(x):
если x ‹ 3:
вернуть 0
вернуть 1

изменение отзывов с оценкой менее 3 на положительные и наоборот

print("Количество точек данных в наших данных", filtered_data.shape)
filtered_data.head(3)

display = pd.read_sql_query("""
ВЫБРАТЬ UserId, ProductId, ProfileName, Time, Score, Text, COUNT(*)
FROM Reviews
GROUP BY UserId
HAVING COUNT( *)›1
«»», con)

print(display.shape)
display.head()

Очистка данных: дедупликация

display= pd.read_sql_query("""
SELECT *
FROM Reviews
WHERE Score != 3 AND UserId="AR5J8UI46CURR"
ORDER BY ProductID
""" , con)
display.head()

Как видно из приведенного выше примера, один и тот же человек имеет многочисленные оценки с одними и теми же значениями HelpfulnessNumerator, HelpfulnessDenominator, Score, Time, Summary и Text, и при дальнейшем расследовании было обнаружено, что;

ProductId=B000HDOPZG — ванильное вафельное печенье Loacker Quadratini, упаковки по 8,82 унции (упаковка из 8 шт.)

ProductId=B000HDL1RQ — лимонное вафельное печенье Loacker Quadratini, упаковки по 8,82 унции (упаковка из 8 штук) и т. д.

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

Для этого мы использовали следующую стратегию: сначала сортировали данные по ProductId, затем оставляли только первый похожий отзыв о товаре, а остальные удаляли. Например, в приведенном выше примере остается только проверка для ProductId=B000HDL1RQ. Этот подход гарантирует, что каждый продукт имеет только одно представление, тогда как дедупликация без сортировки может привести к существованию нескольких представителей для одного и того же продукта.

Наблюдение: также было замечено, что значение HelpfulnessNumerator больше, чем HelpfulnessDenominator в двух строках ниже, что не соответствует действительности, поэтому эти две строки также удаляются из вычислений.

display= pd.read_sql_query("""
SELECT *
FROM Reviews
WHERE Score != 3 AND Id=44737 OR Id=64422
ORDER BY ProductID
" "", против)

дисплей.голова()

Предварительная обработка текста

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

В результате на этапе Preprocessing мы делаем следующее в следующем порядке:

  1. Сначала удалите теги HTML.
  2. Удалите все знаки препинания и ограниченный набор специальных символов, таких как, или., или #, и так далее.
  3. Проверьте, является ли термин буквенно-цифровым или состоит из английских букв.
  4. Проверьте, не длиннее ли слово, чем 2 символа (поскольку было исследовано, что нет прилагательного из 2 букв)
  5. Измените заглавную букву слова на строчную.
  6. Стоп-слова должны быть удалены.
  7. Наконец, мы определили слово Snowball Stemming (которое оказалось лучше, чем Porter Stemming), а затем собрали слова, используемые для описания положительных и отрицательных эмоций.

#печать случайных отзывов

send_0 = final['Text'].values[0]
print(sent_0)
print("="*50)

send_1000 = final[‘Text’].values[1000]
print(sent_1000)
print("="*50)

send_1500 = final[‘Text’].values[1500]
print(sent_1500)
print(“=”*50)

send_4900 = final[‘Text’].values[4900]
print(sent_4900)
print(“=”*50)

# удалить URL из текста python:

sent_0 = re.sub(r"http\S+", "", sent_0)
sent_1000 = re.sub(r"http\S+", "", send_1000)
sent_150 = re.sub( r"http\S+", "", sent_1500)
sent_4900 = re.sub(r"http\S+", "", send_4900)

печать (отправлено_0)

из bs4 импортировать BeautifulSoup

суп = BeautifulSoup(sent_0, ‘lxml’)
текст = суп.get_text()
печать (текст)
печать («=» * 50)

суп = BeautifulSoup(sent_1000, ‘lxml’)
текст = суп.get_text()
print(текст)
print(“=”*50)

суп = BeautifulSoup(sent_1500, ‘lxml’)
текст = суп.get_text()
print(текст)
print(“=”*50)

суп = BeautifulSoup(sent_4900, ‘lxml’)
текст = суп.get_text()
print(текст)

импортировать повторно

def decontracted(phrase):
# специфическая
фраза = re.sub(r"не будет", "не будет", фраза)
фраза = re.sub(r"может\ 'т», «не могу», словосочетание)

# общая
фраза = re.sub(r"n\'t", "не", фраза)
фраза = re.sub(r"\'re", "являются", фраза)< br /> фраза = re.sub(r"\'s", "есть", фраза)
фраза = re.sub(r"\'s", "будет", фраза)
фраза = re.sub(r"\'ll", "будет", фраза)
фраза = re.sub(r"\'t", "не", фраза)
фраза = re.sub (r"\'ve", "иметь", фраза)
фраза = re.sub(r"\'м", "ам", фраза)
возвратная фраза

sent_1500 = деконтрактировано(sent_1500)
print(sent_1500)
print("="*50)

# Объединение всех вышеперечисленных действий
из tqdm import tqdm
preprocessed_reviews = []
# tqdm предназначено для печати строки состояния
для отправки в tqdm(final['Text']. значения):
sentance = re.sub(r"http\S+", "", sentance)
sentance = BeautifulSoup(sentance, 'lxml').get_text()
sentance = decontracted (предложение)
sentance = re.sub("\S*\d\S*", "", sentance).strip()
sentance = re.sub('[^A-Za- z]+', ' ', sentance)

sentance = ' '.join(e.lower() для e в sentance.split(), если e.lower() не в стоп-словах)
preprocessed_reviews.append(sentance.strip())

preprocessed_reviews[1500]

Особенности:

СУМКА СЛОВ

  1. С помощью этой функции мы найдем все уникальные слова в данных и назначим номер измерения каждому уникальному слову.
  2. Мы создадим словарь Python для сохранения всех уникальных слов, так что ключ словаря представляет собой уникальное слово, а соответствующее значение представляет его число измерения.
  3. Например, если у вас есть обзор __' очень плохая пицца'__, вы можете представить каждое уникальное слово с помощью параметра Dimension_Number как
    dict = { ' очень»: 1, «плохо»: 2, «пицца»: 3}

count_vect = CountVectorizer() #in sci-kit-learn
count_vect.fit(preprocessed_reviews)
print("названия некоторых функций", count_vect.get_feature_names()[:10])
print( '='*50)

final_counts = count_vect.transform(preprocessed_reviews)
print("тип векторизатора подсчета", type(final_counts))
print("форма векторизатора BOW текста", final_counts.get_shape())< br /> print("количество уникальных слов", final_counts.get_shape()[1])

TF-IDF

Что означает термин tf-idf?
Вес tf-idf — это вес, обычно используемый при поиске информации и анализе текста. Tf-idf обозначает частоту документа, обратную частоте. Этот вес является статистической метрикой для определения важности слова в коллекции или корпусе документов. Важность слова возрастает прямо пропорционально количеству раз, которое оно появляется в документе, но уравновешивается его частотой в корпусе. Поисковые системы часто используют варианты системы взвешивания tf-idf в качестве основного инструмента для оценки релевантности документа в ответ на запрос пользователя.

Суммирование tf-idf для каждого термина запроса — одна из самых простых процедур ранжирования; несколько более продвинутых процессов ранжирования являются вариантами.

tf_idf_vect = TfidfVectorizer(ngram_range=(1,2), min_df=10)
tf_idf_vect.fit(preprocessed_reviews)
print("некоторые образцы функций (уникальные слова в корпусе)", tf_idf_vect.get_feature_names() [0:10])
print('='*50)

final_tf_idf = tf_idf_vect.transform(preprocessed_reviews)
print("тип векторизатора счета", type(final_tf_idf))
print("форма нашего текстового векторизатора TFIDF", final_tf_idf.get_shape())< br /> print("количество уникальных слов, включая униграммы и биграммы", final_tf_idf.get_shape()[1])

Word2Vec

Word2vec — это подход к обработке естественного языка, впервые опубликованный в 2013 году. Программа word2vec изучает связи слов из огромного корпуса текста с использованием модели нейронной сети. Как следует из названия, word2vec связывает каждое отдельное слово с определенным набором чисел, известным как вектор.

i=0
list_of_sentance=[]
для предложения в preprocessed_reviews:
list_of_sentance.append(sentance.split())

is_your_ram_gt_16g=False
want_to_use_google_w2v = False
want_to_train_w2v = True

if want_to_train_w2v:
# min_count = 5 учитывает только слова, которые встречаются не менее 5 раз
w2v_model=Word2Vec(list_of_sentance,min_count=5,size=50, workers=4)
print(w2v_model.wv .most_similar('отлично'))
print('='*50)
print(w2v_model.wv.most_similar('худший'))

elif want_to_use_google_w2v и is_your_ram_gt_16g:
if os.path.isfile('GoogleNews-vectors-negative300.bin'):
w2v_model=KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin', binary=True)
print(w2v_model.wv.most_similar('отлично'))
print(w2v_model.wv.most_similar('худшее'))
else:
print("У вас нет word2vec от Google файл, сохраните want_to_train_w2v = True, чтобы обучить собственный w2v»)

w2v_words = list(w2v_model.wv.vocab)
print("количество слов, которые встречаются не менее 5 раз", len(w2v_words))
print("образцы слов", w2v_words[0:50])

Гитхаб и ЛинкедИн

Linkedin: https://www.linkedin.com/in/shradhanjalipradhan/

GitHub: https://github.com/shradhanjalipradhan