Обработка естественного языка

Текст в вектор | Обработка естественного языка в JavaScript

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

Самый простой пример — обзоры продуктов, и мы также будем использовать образцы данных обзоров для упражнений.

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

скажем, у нас есть некоторые данные отзывов, как показано ниже

всего 7 отзывов

каждый отзыв состоит из текста и оценки
оценка 1 означает положительный отзыв, а оценка 0 означает отрицательный отзыв

const review = [
  { text: "this product is amazing", score: 1 },
  { text: "this product is great", score: 1 },
  { text: "this product is horrible", score: 0 },
  { text: "this product is bad", score: 0 },
  { text: "this is amazing and tasty food", score: 1 },
  { text: "this food is fabulus", score: 1 },
  { text: "this product is tasteless", score: 0 },
  { text: "this smells bad", score: 0 },
];

если мы увидим это в таблице, это будет выглядеть примерно так

Мешок слов

Сумка слов - это просто сумка или набор слов и их количество в предложении.

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

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

шаги:

  1. Получить все слова во всех обзорах
  2. Для каждого предложения подсчитайте, сколько раз встречается это слово
const stopwords = ["is", "this", "are"];
// step 1 
const totalWords = [
  ...new Set(
    review.flatMap((a) =>
      a.text.split(" ").filter((a) => stopwords.indexOf(a) === -1)
    )
  ),
];
console.log(totalWords)
output will be 
['product', 'amazing', 'great', 'horrible', 'bad', 'and', 'tasty', 'food', 'fabulus', 'tasteless', 'smells']

Теперь все эти слова являются нашими функциями, и мы посмотрим, как каждое слово влияет на оценку.

Теперь шаг 2. Для каждого предложения подсчитайте, сколько раз встречается это слово.

const bagOfWords = review.map((a) => {
    const obj = {};
    totalWords.forEach((key) => {
      obj[key] = a.text.includes(key) ? 1 : 0;
    });
    return obj;
  });
console.table(bagOfWords)

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

он состоит из 3 слов (так как они будут удалены стоп-словами на шаге 1), и в таблице мы видим, что в первой строке «этот» «продукт» «изумительный» имеет значение 1, а другие имеют значение 0

Проблема с мешком слов

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

TF-IDF (Термин Частота Обратной Частоты Документа)

поскольку мы подсчитали частоту термина, мы посчитаем обратную частоту документа и умножим оба

так что в коде это будет очень просто

  1. Рассчитайте количество предложений, содержащих каждое слово из нашего шага 1 выше
const WordsWithSentences = [
  ...new Set(
    totalWords.map((a) => {
      return {
        word: a,
        reviews: review.filter((b) => b.text.includes(a)).length,
      };
    })
  ),
];
console.log('WordsWithSentences', WordsWithSentences);

Таким образом, это в основном похоже на то, что продукт присутствует в 5 обзорах
удивительный присутствует в двух обзорах и так далее.

2. Рассчитать Td-Idf для каждого слова

const tfidf = reviews.map((a) => {
    const obj = {};
    const totalWordsInReview = a.text.split(" ").length;
    totalWords.forEach((key) => {
      const numberOfSentenceswithTheWord = WordsWithSentences.find(
        (b) => b.word == key
      );
// calculate Tf 
      const tf = (a.text.includes(key) ? 1 : 0) / totalWordsInReview;

// calculate IDF
      const idf = Math.log(
        numberOfReviews / numberOfSentencesContainingTheWords.reviews
      );
// multiple both to get weight of word on score 
      obj[key] = tf * idf;
    });
    obj.output = a.score;
    return obj;
 });

Полный код будет выглядеть следующим образом

Теперь мы видим, что термину «удивительный» придается больше веса, чем термину «продукт» и т. д.
теперь мы можем использовать эти данные и применять модели и методы классификации.

Напишу больше о том, как применить наивную теорему Байеса к этим данным в простом JavaScript.

Пожалуйста, оставляйте свои ответы, это мотивирует писать больше, если вам это нравится.