Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Большие данные - лекция-5 - работа с категориями и текстами

3a855e4e8dd144b8942da2463831a067?s=47 Anton
March 13, 2019

Большие данные - лекция-5 - работа с категориями и текстами

Работа с текстом: категории, мешок слов, tf-idf, ЕЯ (NLP)

Обновлено: 12.03.2020

3a855e4e8dd144b8942da2463831a067?s=128

Anton

March 13, 2019
Tweet

Transcript

  1. Работа с текстом: категории, мешок слов, алгоритм tf-idf, ЕЯ (NLP)

  2. По материалам • Введение в машинное обучение, ВШЭ, Курсера •

    Python и машинное обучение, Себастьян Рашка
  3. Scikit-learn: Python + машинное обучение • npm install --user scikit-learn

    • scikit-learn.org • Обширная документация, руководства, примеры • Входные данные — массивы NumPy • Плюс SciPy scipy.org для математики
  4. Здесь и дальше договоримся обозначать • X - выборка (таблица)

    из n элементов (n строк), у каждого элемента m признаков (m столбцов) • x — произвольный элемент (<=> объект, строка) выборки, • x j — j-й признак элемента x • x(i) (верхний индекс в круглых скобках) — i-й элемент выборки x=(x 1 ,..., x m ) x(i)=(x 1 (i) ,..., x m (i))
  5. Здесь и дальше договоримся обозначать X= (x(1) ... x(n) )=

    (x 1 (1) ,..., x m (1) ... x 1 (n) ,..., x m (n) ) x(i)=(x 1 (i) ,..., x m (i)) x=(x 1 ,..., x m ) или
  6. Категориальные признаки • Нечисловые (текст или отдельные символы) признаки, «монолитные»

    (ячейка целиком) значения из словаря • Порядковые: можно сравнивать между собой: размер одежды (S, M, L, XL), диапазон возрастов (ребенок, юноша, взрослый, старик) и т.п. • Номинальные: нельзя сравнивать между собой: теги, города, цвета и т. п. • Можем по ним фильтровать и искать • Но обычно мы хотим иметь дело с числами • Задача: превратить текстовые категории в числа
  7. Может просто назначить каждой категории отдельное число? • Для порядковых

    признаков решение норм: назначить числовые значения так, чтобы сохранить порядок сравнения оригинальных категорий ([S → 0] < [M → 1] < [L → 2] < [XL → 3]) • Для номинальных признаков: номинальные категории сравнивать нельзя, а числа сравнивать можно • Просто пронумеровав номинальные категории, мы внесем в данные информацию, которой там не было
  8. Самостоятельно: пример кода Python • DataFrame.map • sklearn.preprocessing.LabelEncoder

  9. Дамми-кодирование номинальных категорий • (dummy — наивный, глупый) • Категориальный

    признак x j принимает значения из множества W={w 1 , ..., w l } — все категории: теги, города, цвета и т.п. • Создадим l [эль] (столько же, сколько всего категорий) новых бинарных фиктивных признаков-индикаторов u 1 , …, u l : • k-й индикатор u k показывает, равен ли категориальный признак x j на данном объекте значению k-й категории w k u k (i)= {1, x j (i)=w k 0, x j (i)≠w k ,k=1,...,l
  10. Пример: графа «город проживания» в анкете • W = {Нижний

    Новгород, Самара, Архангельск} • Кодируем тремя бинарными признаками (u 1 , u 2 , u 3 ): • Нижний Новгород →(1, 0, 0): (u 1 =1, u 2 =0, u 3 =0) • Самара → (0, 1, 0): (u 1 =0, u 2 =1, u 3 =0) • Архангельск → (0, 0, 1): (u 1 =0, u 2 =0, u 3 =1)
  11. Имя Город Плоскостопие u 1 u 2 u 3 Александр

    Нижний Новгород да 1 0 0 Сергей Самара да 0 1 0 Лев Самара да 0 1 0 Николай Архангельск нет 0 0 1 Петр Нижний Новгород нет 1 0 0 Илья Архангельск нет 0 0 1 u 1 = город_Нижний_Новгород u 2 = город_Самара u 3 = город_Архангельск
  12. • Получили вместо одного категориального признака (1 колонка в таблице)

    3 бинарных признака (3 колонки в таблице) • Из всех новых признаков только один может принимать ненулевое значение для одного объекта (одна единица на строку)
  13. Самостоятельно: пример кода Python • DataFrame.get_dummies • sklearn.preprocessing.OneHotEncoder

  14. Проблемы • Уникальные (или редкие) категории: алгоритм не выявит зависимостей

    (решение: объединить редкие категории в одну) • Большое количество возможных значений категории (провести замену как-то по- другому)
  15. ЕЯ — естественные языки (NLP — Natural language processing)

  16. Текстовые признаки • x j — текстовый признак: • Значение

    признака x j — последовательность слов (w 1 , w 2 , …, w m ) • В отличие от категорий, мы не рассматриваем признак как монолитное значение (значение ячейки целиком), а разбиваем его на составляющие и работаем с ними
  17. Мешок слов • Выводы о тексте можно сделать, даже если

    слова перемешаны (частое употребление спец-терминов, эпоха, стиль, привычки автора и т.п.) • Все слова из всех текстов принадлежат словарю W = {w 1 , …, w l } • Создадим l [эль] новых фиктивных признаков-индикаторов u 1 , …, u l : • n(w k , x j ) — число вхождений слова w k в текст x j • k-й признак u k показывает, сколько раз k-е слово w k встречается в тексте x j • (похоже на дамми-кодирование, только вместо двоичных признаков числовые, ненулевых значений столько, сколько слов в тексте) u k (i)=n(w k , x j (i)),k=1,...,l
  18. Пример • W = {спят, усталые, игрушки, книжки} (спят усталые

    игрушки, книжки спят) → (2, 1, 1, 1) (усталые игрушки усталые) → (0, 2, 1, 0) (книжки спят) → (1, 0, 0, 1) • Минус: общеупотребительная лексика → топ
  19. word-bag.py # coding=utf-8 import numpy as np from sklearn.feature_extraction.text import

    CountVectorizer count = CountVectorizer() docs = np.array([ u'спят усталые игрушки, книжки спят', u'усталые игрушки усталые', u'книжки спят' ]) bag = count.fit_transform(docs)
  20. word-bag.py # посмотрим словарь # (ascii-фашисты атакуэ, TODO: проверить на

    Python 3) #print(count.vocabulary_) print(repr(count.vocabulary_).decode("unicode-escape")) {u'игрушки': 0, u'усталые': 3, u'спят': 2, u'книжки': 1} (пересортируем вручную) {u'игрушки': 0, u'книжки': 1, u'спят': 2, u'усталые': 3}
  21. word-bag.py {u'игрушки': 0, u'книжки': 1, u'спят': 2, u'усталые': 3} [[1

    1 2 1] : 'спят усталые игрушки, книжки спят' [1 0 0 2] : 'усталые игрушки усталые' [0 1 1 0]] : 'книжки спят' # мешок для текстов print(bag.toarray())
  22. Метрика TF-IDF • TF — term frequency (частота слова) •

    IDF — inverse document frequency (обратная частота документа) • Улучшение подхода: вычисляем не количество слов, а оценку важности слова для текста • Чем чаще встречается слово, тем оно более важно (этот текст про это слово) • Чем реже встречается слово в других текстах, тем оно еще важнее (это не общеупотребительная лексика)
  23. TF-IDF • TF(w, d) — term frequency (частота слова): отношение

    числа вхождений слова в документ к количеству слов в документе (могут быть другие варианты определения, например, просто число вхождений) • IDF(w) — inverse document frequency (обратная частота документа): логарифм отношения общего количества документов к числу документов, содержащих слово
  24. • n(w, d) — число вхождений слова w в документ

    d • |d| - количество слов в документе d • N(w) — число документов, содержащих слово w • L — число документов • Мера важности слова w для документа d: TF−IDF(w ,d)= n(w ,d) |d| ⏟ TF(w ,d) ∗log( L N (w) ) ⏟ IDF(w)
  25. Значения IDF • IDF(w) = log(L/N(w)) • Если N(w) =

    L (слово встречается во всех текстах), то IDF = log(L/L) = log(1) = 0 = min (минимальный коэффициент) • Если N(w) = 1 (слово встречается только в одном тексте), то IDF = log(L) = max (максимальный коффициент) • Чем меньше N(w), тем больше IDF • На ноль здесь не делим, т.к. любое слово должно встретиться хотя бы в одном тексте, иначе оно не попадет в словарь
  26. Почему логарифм?? o_O

  27. None
  28. Встречается редко Встречается везде 1≤N (w)≤L 1≤ L N (w)

    ≤L
  29. Эффект логарифма — нелинейное распределение штрафов • Для редких терминов

    — большой штраф за каждый дополнительный текст • Чем чаще встречается слово, тем меньше штраф • Есть заметная разница, встречается слово в 1-м или уже в 2-х текстах • Нет примерно никакой разницы, встречается ли слово в 80-ти или в 110 текстах
  30. tf-idf.py # coding=utf-8 import numpy as np from sklearn.feature_extraction.text import

    CountVectorizer from sklearn.feature_extraction.text import TfidfTransformer count = CountVectorizer() tfidf = TfidfTransformer() docs = np.array([ u'спят усталые игрушки, книжки спят', u'усталые игрушки усталые', u'книжки спят' ])
  31. tf-idf.py bag = count.fit_transform(docs) # на входе алгоритма — мешок

    слов bag_tfidf = tfidf.fit_transform(bag)
  32. tf-idf.py # словарь # (ascii-фашисты атакуэ) #print(count.vocabulary_) print(repr(count.vocabulary_).decode("unicode-escape")) # мешок

    для текстов print(bag.toarray()) # tf-idf np.set_printoptions(precision=2) print(bag_tfidf.toarray())
  33. словарь {u'игрушки': 0, u'книжки': 1, u'спят': 2, u'усталые': 3} мешок

    [[1 1 2 1] : 'спят усталые игрушки, книжки спят' [1 0 0 2] : 'усталые игрушки усталые' [0 1 1 0]] : 'книжки спят' tf-idf (в sklearn немного другая формула) [[0.38 0.38 0.76 0.38] [0.45 0. 0. 0.89] [0. 0.71 0.71 0. ]]
  34. База отзывов на фильмы IMDB • IMDB — internet movie

    database • Скачиваемая база отзывов: Large Moview Review Dataset (80 Мб) ai.stanford.edu/~amaas/data/sentiment/ • Задание-0: Скачайте архив, распакуйте, склейте все отзывы в один файл csv с колонками «текст отзыва» + «мнение» (neg=0/pos=1)
  35. Задание-1 • Мешок слов • Сделайте мешок слов для текста

    при помощи sklearn.feature_extraction.text.CountVectorizer Выведите: • топ 5 слов для комментариев с позитивным отзывом, • топ 5 слов для комментариев с негативным отзывом
  36. Задание-2 • Посчитайте метрики TF-IDF для документов с отзывами IMDB

    при помощи sklearn.feature_extraction.text.TfIdfTransformer Выведите: • топ 5 слов (максимальный tf-idf) для комментариев с позитивным отзывом, • топ 5 слов для комментариев с негативным отзывом
  37. • Как по-вашему, можно ли по этим словам делать вывод

    о положительности или отрицательности отзыва? • Будет ли IDF выводить характерные для всего класса слова в топ? • Можно ли улучшить алгоритм? например: считать IDF для каждого позитивного отзыва отдельно в группе только с негативными Задание-3