Добрый день, уважаемые слушатели, сегодня мы с вами посмотрим, как заниматься текстовым анализом интеллектуальным в RapidMiner приложении. Для этого нужно скачать расширение, которое находится в MarketPlace. Сейчас мы посмотрим, как оно выглядит. Оно находится в разделе Топ скачиваний и называется TextMining, точнее TextProcessing. Вот у меня сейчас стоит версия более-менее актуальная, и это расширение позволяет выполнять основные все элементы, которые вообще с текстовым анализом связаны. Все остальное можно делать на уровне оператора в RapidMiner, который мы уже раньше изучали. Само это расширение находится в папочке Расширения (extensions), внизу. И вот здесь мы видим основные методы, которые здесь присутствуют. Но в целом напомню, что текстовый анализ, в общем-то, требует применения нескольких этапов (обязательных) обработки. Первый этап — это токенизация теста, то есть разделение текста на какие-то отрезки, не обязательно именно слова. Иногда это может быть и какой-то кусок строки, иногда это могут быть, например, только цифры. То есть в любом случае, токен — это совокупность каких-то символов, может быть даже и служебных. Дальше, после токенизации, когда мы извлекли, например, слова какие-то, их имеет смысл дальше отфильтровать. Скажем, мы не хотим видеть в нашем конечном тексте, который мы отсюда извлекли, предлоги, потому что они не несут информации какой-то. Вот для этого можно использовать фильтрацию токенов по длине. Скажем, оставить всё, все токены, длина которых больше, чем два символа. Дальше, если мы извлекли какие-то токены, то, естественно, может так случиться, что в реальном живом тексте одно и тоже слово может иметь разные формы, разную морфологию. Для того чтобы привести эти слова в какую-то более-менее стандартную форму, в данном случае присутствует стемминг; то есть обрубка всех окончаний у слов-приставок, для того чтобы оставить, фактически, только корень. В английском языке это, конечно, работает лучше, чем в русском. Но тем не менее, даже в русском языке, в принципе, можно с этим более-менее работать. Алгоритмов здесь тоже несколько, как видите. Чаще всего используются два алгоритма — это Портер и Снежок. Есть поддержка стемминга для некоторых других языков. Дальше, для того чтобы сами наши токены в дальнейшем можно было подсчитывать наиболее эффективно, тоже требуется иногда их преобразовывать каким-то образом. Например, можно, для начала, все это токены перевести в один и тот же регистр, потому что что-то с большой буквы, что-то с маленькой — это будет считаться двумя разными токенами по умолчанию при прочих равных. Поэтому, какой-нибудь «Бегун», который упомянут в начале текста в большой буквы и «бегун» в середине текста будут считаться как два разных слова. Соответственно, частота будет в два раза меньше (у каждого из этих слов). Чтобы такого не было, желательно всегда, не зависимо не от чего преобразовывать эти случаи в один и тот же регистр. Единственное исключение — если нам требуется анализ имен. Тогда, естественно, имена желательно отдельно каким-то образом обрабатывать. Для этого желательно сохранять именно сами большие регистры тоже. Дальше, некоторые токены можно заменять, если это требуется. Например, есть какие-нибудь обработки, которые требуют во всех токенах вставить какое-нибудь число дополнительное, для того чтобы затем эти числа отдельно использовать в некотором анализе. Вот это здесь можно тоже сделать. Дальше, в некоторых случаях нам может потребоваться сгенерировать n-граммы, то есть это совокупность токенов. Например, Mercedes Benz. Если мы отдельно только униграммы будем сохранять, окажется, что это два разных слова. Но мы понимаем, что это название марки, и нам желательно сохранить название целиком. Поэтому, мы можем сделать тогда биграммы. Это делается именно из этого метода. Но необязательно делать это по токенам. Можно делать это посимвольно, точно также. В некоторых вариантах анализа это более эффективно. Здесь это тоже поддерживается. Отдельно здесь есть загрузка самих документов, что тоже, естественно, важно. В данном случае нам потребуется для данного примера метод, который называется «Обработать документы из файлов». Давайте посмотрим, как этот процесс выглядит, что с ним можно сделать, с этим текстовым объемом данных, который у нас есть. И собственно, о том, что у нас есть. Значит, у нас есть директория, в которой находятся отзывы на различные книги. Это открытый DataSet, взят с отзывов с Amazon. Для того чтобы его использовать, что мы должны сделать? Итак, перетаскиваем этот метод на экран — Process Documents from Files. Дальше, выбираем текстовую директорию, в которой находятся наши текстовые документы. Дальше, в принципе, для нашего анализа можно изначально каким-то образом фильтровать наши данные по разным папкам и каждой папке присваивать свое имя. Но это нужно, если мы будем заниматься дальше классификацией для обучения алгоритмов. Например, можно прошу прощения здесь сразу пометить, если мы обрабатываем какую-нибудь почту, что здесь лежат письма Спам, здесь, соответственно, Деловые письма, здесь — Личные письма и так далее. В нашем случае мы просто назовем, что это отзывы (reviews) — один единственный класс, и дальше посмотрим, что из этих документов у нас получится. Значит, этот метод делает одновременно и токенизацию, и векторизацию, но векторизация дается на выходе, а токенизация вся осуществляется внутри этого процесса. Пока что ее здесь нет, поэтому требуется ее добавить. Напомню, что векторизация — это преобразование каждого документа в вектор, в котором каждое измерение — это, обычно, токен, а значение этого измерения — это частота этого токена, которая так или иначе подсчитывается. Вот по умолчанию здесь используется метрика TF-IDF. Отдельно можно подсчитывать частоты термов, отдельно можно встречаемость можно подсчитывать, можно подсчитывать еще бинарную встречаемость. Давайте, остановимся на начальном выборе TF-IDF. Дальше, давайте посмотрим простейший процессинг. Значит, для начала мы токенизируем все, что у нас есть. В данном случае мы можем задать режим токенизации — можно задать регулярное выражение конкретное, можно задать предустановленные варианты. Вот видите, здесь даже на английском языке можно даже лингвистические токены пытаться выделить. Это уже регулярное выражение, которое пытается отделить не просто слова, но и выражения. Ну и наконец, можно просто разделить на какие-то токены чисто по служебным символам. В данном случае, все, что не является буквами — режим включен по умолчанию. И давайте посмотрим, что из этого выйдет. Вот внизу указано, как идет процесс, указано, сколько документов уже обработано. Соответственно, всего у нас, если посмотреть здесь, 880 документов, 4 мета-атрибута, метка, дата создания файлика, название файла и папка, и дальше — сами токены, которые у нас получились. Вот, как видите, есть большие буквы, есть маленькие буквы. В принципе, чтобы их посмотреть, можно список слов в данном случае увидеть в отдельном выходе. Вот здесь, как видите, указаны частоты. И уже здесь видно, что в целом есть большие буквы, маленькие буквы; есть вообще какие-то непонятные аббревиатуры, которые, возможно, связаны с какой-то пометкой у каждого отзыва; есть нераспознанные какие-то символы. Чаще всего такие символы с вязаны с тем, что в самих отзывах могут быть всевозможные смайлики или какие-то еще эмодзи прочие, которые тоже требуется очистить. Давайте посмотрим, ради интереса, какие слова мы можем, в принципе, здесь ожидать? Вот видите, есть marvels, то есть «прекрасный»; есть «мастерский» — masterful; есть, очевидно, много всевозможных слов good… Для того чтобы это проверить, можно сделать следующий этап, чтобы сейчас не считать, а именно сразу отфильтровать соответствующие слова и посмотреть, сколько они встречаются. Значит, вот у нас есть фильтрация по контенту. Добавляем после токена. Значит, дальше, если говорим про contains-метод, то он буквально ищет нужную строчку. Вот если мы говорим про good… Давайте посмотрим, сколько у нас таких документов появится. Вот видите, все слова, которые содержат этот good, они у нас здесь выявлены. Значит, всего порядка 300 документов… или, точнее, 300 раз встречается вообще это слово, примерно; в двухстах документах — видите, Document Occurrence — 200. И итог, что в данном классе — этот у нас единственный — встречается всего тоже почти 300 раз это слово. Что касается документов, давайте посмотрим на статистику. Это частоты и, соответственно, действительно с нулевым значением good встретился почти в 700 документах, и с оставшимися частотами не нулевыми вот в данном случае. Вот уже видно, на самом деле, примерно, какие документы требуется дальше пытаться анализировать. Ну и кстати, здесь мы видим, что в принципе, если бы мы тоже избавились от кейса конкретного — большой буквы — все перевели в маленькую, то это тоже добавило бы встречаемости этого слова good сюда же. Но вот, тем не менее, есть еще «товары» goods, есть goodness — доброта, good reads — это явно относится, скорее к good в нашем случае, если мы хотим оценить качество этой книги по отзывам. Поэтому с этим тоже придется что-то сделать. Ну, давайте для начала довольно грубо попытаемся первое, в качестве трансформации все наши кейсы, то есть регистры, заменить на одну и туже форму. Выбираем метод Transform Cases, выбираем, чтобы все символы преобразовались в нижний регистр. И кроме этого, давайте еще отфильтруем не только слово «хороший», но и, например, «плохой». Значит, для этого нужно регулярное выражение. Соответственно, здесь пишем matches либо bad, либо good слова. Давайте, еще добавим «скучное чтение» и «превосходное». Напоминаю, что в регулярных выражениях вертикальная черта означает «или». То есть мы фильтруем только токены, оставляем только токены, которые относятся либо к bad, либо к good, либо к dull, либо к awesome. Вот смотрим. Как видите, после преобразования good у нас уже теперь содержат 336. Всего раз встречаемость документов, соответственно, 228; «скучный» — 10; «плохо» 58; и «превосходно» — 44. Естественно, если посмотреть сюда, то это не значит, что эти слова не могут встречаться одновременно в одном и том же документе. Поэтому, для того чтобы понять само соотношение, надо посмотреть все-таки в нашу статистику. Как видите, соотношения довольно близкие этих документов. Вот пример, кстати, документ, когда bad и good одновременно встретились, причем у bad довольно большая частота. Есть документы, где только bad встретилось. Есть сочетание «превосходного» с «хорошим», скорее всего, это действительно позитивный отзыв. Ну и вот опять сочетание bad и good одновременно, причем bad имеет больше частоту, чем good. Это, что касается вот такой вот простейшей фильтрации. Теперь давайте посмотрим, может быть, если мы отключим в данном случае фильтрацию токенов наших, мы узнаем, все-таки, какие именно символы еще или слова встречаются со словом нашим каждым. Для этого генерируем, собственно, биграммы, потому что может оказаться там написано где-то not good, и тогда смысл отзыва меняется, естественно, на противоположный. Так, смотрим результат, сейчас он досчитается. Так как биграммы, естественно, требуют отдельного подсчета, надо сначала токенизировать все, затем, все варианты биграмм построить — это уже очень много вариантов — и затем уже посчитать все эти варианты в качестве переменных и их частот. Поэтому, в данном случае процесс может немножко затянуться. Для того чтобы столько не ждать, можно сразу проверить какую-нибудь гипотезу. Давайте пока прервем этот процесс, если получится. Как видите, сейчас почти вся доступная память машины уходит на этот подсчет. К счастью, прервать удалось. Давайте ограничим тогда наш процесс, иначе это может затянуться, сначала тем, что оставим только как раз часть токенов и затем из них уже сгенерируем n-граммы. Для этого добавим кроме токенов, которые мы уже указывали, еще слово not, для того чтобы понять, действительно ли в каких-то текстах встречается оценка именно не хорошая, а именно плохая и наоборот. Соединяем опять нашу фильтрацию с основным процессом, выставляем ее до генерации n-грамм, добавляем not. На всякий случай сейчас выключим биграммы и посмотрим, вообще, слово not встречается или нет в наших документах. Встречается, еще как. Это хорошо. Это означает, что наша гипотеза, в принципе, перспективна. Так, опять соединяем то, что у нас получилось с n-граммами и проверяем результат. Как видите, есть not bad, действительно, not good, причем, довольно много. Проблема только в том, что так как мы отфильтровали эти токены, то мы не знаем на самом деле через сколько слов, в данном случае, такие вообще у нас словосочетания встретились. Для того чтобы их полностью выявить, надо все-таки без фильтрации, по исходным данным такие выражения искать. Но тем не менее, потенциально мы видим, что есть not перед good, есть аж дважды упомянутое слово dull (скучный). И для того чтобы тогда проверить эту гипотезу, давайте в качестве выражение так и зададим not bad, просто bad, not good, просто good... ...и остальное — то, что было — оставим как есть. Так как мы пользуемся регулярными выражениями, то мы можем искать любую строку, на самом деле. И в данном случае нам как таковые биграммы может быть и не нужны. Но, как видите, из-за того, что мы кое-что не предусмотрели, а именно сам по себе пробел, который мы удалили раньше при токенизации, поэтому такие словосочетания мы не увидели. Давайте здесь тоже укажем. Значит, мы, соответственно, будем искать все буквы и пробел, а точнее будем разбивать даже, наверное, не так; а собственно, здесь перечислим, скажем, точки и запятые, также тире. Квадратные скобочки означают, что мы именно на эти символы будем делить. Пробел оставим. Вот таких элементов у нас не нашлось. Если добавим пробел, то увидим такой же почти эффект, который был, когда мы выбрали nonletters-вариант. Для того, чтобы здесь выполнить-таки то, что нужно, давайте сделаем вот что. Скопируем пока что это выражение в буфер и поставим именно строку. Здесь оставим nonletters, и токенизацию временно отключим. Ну вот фактически нашлась одна гигантская строка, где встретился этот not god как таковой, конкретный отзыв. И ввиду того, что мы токенизацию не проводили, просто указана конкретная строка, то есть весь отзыв целиком, все, что у нас там нашлось. Как видите, уже из этого видно, что на самом деле, сама гипотеза про not good, она, видимо, не очень релевантная. Хорошо. Возвращаемся к нашему варианту с токенизацией той, которая была. Оставляем наше выражение, которое было. Давайте посмотрим, что с этим можно еще сделать. Значит, в целом видим, что у нас есть вот такие переменные, но, если открыть конкретный отзыв, там можно будет заметить, что существует еще и оценка — обычная, численная — данного произведения, которую тоже желательно выявить. Для того чтобы ее выявить, нам надо что сделать? Возвращаемся в этом процессе сюда, и должны сюда исправить, получается, регулярые выражения, чтобы оставить не только сами буквы, но еще и цифры. И посмотрим, что из этого выйдет. Цифр там может быть больше, чем просто оценка. Более того, сами оценки могут тоже теоретически быть записаны, именно как не обычные оценки целые — пять, четыре, три, а пять-точка-ноль, один-точка-ноль. И из-за этого тоже могут быть определенные проблемы. Но в данном случае точка попадает тоже в служебные символы, поэтому будет что-то вроде один, потом ноль — как отдельные две цифры. Так, ну пока идет токенизация, давайте посмотрим, что еще здесь интересного есть. Вот можно кроме того процесса, который у нас сейчас здесь идет, можно сами документы, кроме как из файла, загружать, в принципе, из хранилища почты; можно считывать документы почтовых форматов, если вы выгрузили из приложения типа outlook их. Сами документы тоже можно преобразовать дальше в данные (dataset), которые дальше использовать каким-то образом. Так. И вот смотрим сюда. Ну вот никаких оценок у нас не появилось, потому что мы забыли их указать вот здесь. То есть, токенизация прошла, а фильтрацию мы здесь не сделали. Давайте здесь это недоразумение исправим. Значит, нас интересуют оценки от одного до девяти. Сейчас мы еще раз все это пересчитаем, дальше покажу, как можно частично запустить только все, что у нас есть. Так, вот уже неплохо. Оценка у нас один, девять появилась. Появилась она так от того, что в этом регулярном выражении возможно потребуется вместо подчеркивания указать две точки — один, две точки, девять — для того, чтобы и один, и два, и три, и все, что между ними находится, тоже сюда попало. И вот, если выбрать здесь «Запустить процесс локально», то пересчитается только вот эта фильтрация заново, а токенизация и так далее останется как есть. Так, ну снова он не распознал эти циферки. Тогда поставим здесь дефис. Если это не поможет, просто поставим другое выражение. Нет, все хорошо. Значит, вот у нас получается. Это оценки, видимо, по десятибалльной шкале. Десятку я не указывал, потому что в данном случае придется указать ее отдельно. Так как здесь мы указали, что просто хотим увидеть цифры от одного до девяти, а не число как таковое. Для того чтобы искать именно числа, нам потребовалось бы другое выражение немножко написать. Но если мы напишем вообще, скажем, числа, которые содержат от одного до двух символов, то может получится, что мы часть лишней информации тоже извлечем. Потому что в тексте любого отзыва могут упоминаться, например, оценки численные... еще что-то, связанное с цифрами, а нам это не нужно сейчас. Так, ну да, вот десятка есть. Таких отзывов немного, всего 19 документов. Единичка — 33 и так далее. Посмотрим, как соотносятся теперь слова «хороший» и «плохой» с этими оценками. Так, ну вот есть десятка. Вот здесь какая-то еще единица встречается и два, и три. Так что все-таки эти числа в одном отзыве все еще могут встретиться к сожалению. Что-нибудь более показательное найдем — там, где оценка, скорее всего, конкретная. Так, ну вот, например, есть awesome. И оценка три. Скорее всего, это связано с тем, что то, что мы вывели — это частично оценки, а частично какие-то дополнительные символы. Для того чтобы не гадать, сейчас мы откроем этот документ какой-нибудь для примера, один из отзывов, и посмотрим, как эти оценки там фиксируются. Так, вот, к сожалению, есть мелкие технические сложности, связанные с тем, что мы не на космической технике работаем. Однако, все это сейчас решиться. И пока это решается, давайте подумаем еще, что мы можем с этими отзывами сделать. Значит, теоретически мы можем наши документы просто-напросто, по нашим словам, и нашим оценкам кластеризовать, и затем открыть документы из разных кластеров и пытаться найти среди них какие-то закономерности. То есть, скорее всего, мы получим кластеры с хорошими оценками, в которых часто встречается слово good, awesome и так далее, и кластеры с плохими оценками, где, соответственно, этих слов меньше. Дальше уже можно эти отзывы, когда они кластеризованы на хорошие и плохие, пытаться обработать еще чем-то. То есть попытаться выявить, например, распределение частот по хорошим отзывам слов, то есть какие еще слова встречаются в таких отзывах. Как это можно сделать? В принципе, процедура такая: сначала нам по-хорошему было бы нужно не фильтровать, например, вот эти токены, а оставить все, как есть. То есть разбить все и цифры, и буквы — все возможные комбинации. Затем эти полные вектора, в которых могут быть тысячи и десятки тысяч отдельных токенов, подать в сегментацию. Дальше, сегментировать. Затем, в этих сегментах вывести распределение только чисел. Понять, что это именно оценки. Определить, какие отзывы являются хорошими. И дальше уже вернуться опять в этот процесс с токенизацией и оставить, скажем, с помощью фильтрации, только те токены, которые встречаются наиболее часто в этих отзывах. И так итеративно идти. Дойти до конца. После сегментации проверить, какие документы попали, что их определяет. Вернуться сюда, чтобы отфильтровать более качественно эти документы и так далее. Это, по сути, есть обучение модели нашей текстовой, которая с каждым таким прогоном будет становиться все более совершенной. Но в целом отзывы, если имеются, желательно именно пытаться кластеризовать на хорошие и плохие, для того чтобы понять в целом оценку этого произведения, чего в нем больше. Можно без сегментации просто подсчитать число слов. Тогда мы, по сути, занимаемся оценкой тональности. Для оценки тональности требуется тоже словарик составить — хороших и плохих слов. Для того чтобы их использовать, можно в общем-то скачать такие вот уже составленные словари на разные случаи жизни, и можно их загружать тоже, если говорить про фильтрацию, с помощью вот такого метода «Со словарем», если словарь — это отдельный документ, который мы откуда-то берем. Кстати говоря, можно еще фильтровать наши слова по так называемой части речи. Это тоже важный элемент. То есть нам для анализа может быть потребуется все существительные только вытащить или только все глаголы. Вот, как видите, здесь есть пример, который говорит о том, что мы, допустим, можем вытащить все прилагательные и существительные в этой разметке. Давайте, кстати, токенизацию пока отключим и все существительные, которые у нас есть, попытаемся извлечь. Сама эта разметка осуществляется отдельно, поэтому, скорее всего, идут те аббревиатуры, которые мы видели вначале, когда токенизацию никак не ограничивали. И должны остаться, по идее, только более-менее адекватные слова, из которых можно уже сделать какой-то выбор. Единственное, сама эта разметка — это тоже не очень быстро, поэтому придется немножко подождать. Ну вот можно, пока мы этим занимаемся, посмотреть, какие еще настройки доступны в основном методе векторизации. Так как мы используем частоты для вектора, то можно использовать очистку по… наших слов… по, собственно, процентам. Фактически, это аналог метода Воскарюня, TF-IDF-векторайзер, который как раз и тоже позволяет ограничивать и самые частые слова, которые у нас встретились, токены, и самые редкие слова, и оставлять только между ними что-то. Также можно только название файла с конкретным токеном оставить. То есть можно, например, сделать выборку только тех отзывов, которые, скажем, содержат цифры от одного до ста. Или по каким-то еще принципам это ограничить. Также можно сами токены, которые мы извлекаем использовать для описания наших документов. То есть все токены, которые содержат, ну вот допустим, оценку, использовать как мета-данные. Так, давайте, наверное, мы сейчас еще раз прервемся и попробуем ограничить наши вычисления частью документов, потому что этих документов явно здесь слишком много для нашей текущей конфигурации в записи. Если, конечно, даже это у нас идет не быстро… замечательно… вот мы берем нашу папку с отзывами и, допустим, оставим в ней 50 отзывов только, а все остальное сейчас исключим. Можно это, в принципе, и ограничивать на уровне самого RapidMiner, что именно извлекать. Однако, чтобы что-то ограничить, ему все равно надо скачать все документы из папки, для начала, потом уже делать из них выборку. Поэтому, чтобы сейчас его этим не напрягать, мы сделаем это рабоче-крестьянским способом. Так, оставили только 50 документов. Вроде бы все хорошо. Теперь возвращаемся к нашему подсчету. Теперь, не смотря на то, что документов всего 50, тем не менее, в каждом документе достаточно много символов, и он каждый из них должен еще разметить на части речи. Уже из-за этого тоже мы несколько ограничены. Ну ладно, давайте тогда мы пока прервемся. Просто поверьте на слово, что эти части речи вполне можно использовать. Возвращаемся к обычным токенам. Вот мы получили то, что получили. Соответственно, вот видите, здесь 13 лет, 150, 1500, то есть какие-то годы указаны. Соответственно, это тоже на оценки не похоже. Так. Открываем любой отзыв сходный. И в блокноте сейчас мы увидим, как он выглядит на самом деле. Итак, да, вот в начале есть оценка — 4.0. Значит, на самом деле, оценка — это вот эти цифры, все остальное нас волновать не должно. Для того чтобы эту оценку выявить, нам по идее в таком виде и нужно ее искать. Значит, для этого мы должны внести сюда изменения. Значит, точка — это символ, который нам нужен. Поэтому мы на \W не можем ориентироваться. Значит, нам придется вручную, как мы будем токенизировать. Запятая — должна быть, тире — должно быть, знак вопроса — тоже, также двоеточие, точка с запятой и всевозможные кавычки. Так, проверяем. Понимаем, что такими экспериментами желательно заниматься на чем-то более существенном. Всякие замечательные символы сюда попали. Вот видите, в данном случае цифры у нас отсутствуют. Давайте себя проверим. В данном случае мы видим, что разделение идет по всем символам служебным. Здесь, наоборот, оставляем только, наоборот, служебные символы, а слова все убираем. Здесь разделение идет по пробелам. И давайте еще раз посмотрим после проверки нашего выражения, что произойдет. Так, открываем результаты и видим, что у нас всевозможные теги остались. Ну и сами по себе оценки тоже. Значит, нам нужно тогда ограничить еще символы больше-меньше слэшами. И дальше можно для того, чтобы только оценку, например, выбрать уже сделать тоже фильтрацию по контенту, и в качестве контента выбрать числа. Выбираем регулярное выражение и пишем вот такое выражение. Значит, \d означает число. Дальше, точка — это обычно служебный символ, который обозначает любой символ для регулярных выражений, мы его экранируем слэшом. Знак вопроса означает, что она может встретиться либо нет, то есть либо точка есть, либо нет. Но, скорее всего, в нашей оценке на самом деле она всегда будет. И после этой точки опять число. В нашем случае это, скорее всего, будет ноль. Можно его напрямую указать, но давайте оставим как есть. В данном виде он ничего не нашел. Давайте, опять-таки, себя проверим. Вот видите, он пока не хочет это находить. Значит, тогда мы можем попытаться просто найти все числа и здесь выбросить только, например, запятую для того, чтобы токенизовать все, что у нас есть… и пробел… Итак, и после точки — любой символ. Прямо можно вот так написать. Или оставить вот так, с вопросом. Эти числа он не хочет искать, давайте поймем почему. Очевидно, это снова проблема из-за наличия точки. Так, в данном случае мы просто должны отделить этот слэш, поэтому в токенизации нам нужно было бы это указать. Итак, теперь почти то, что нам нужно. Он уже нашел, как видите, несколько оценок. 4.5 — это явно то, что нужно. И вот здесь по идее возникают трудности с тем, что мы не все отфильтровали. Из-за того, что токены не везде корректно получились, кое-где оценка получилась привязанной к какой-то строчке. И из-за того, что строчка не отделена, то есть где-то в наших отзывах сразу после начальной цифры после токеницазии получилось привязано что-то еще. Вот это «что-то еще», как отдельное слово не посчиталось, поэтому мы не можем этот токен отфильтровать. То есть вот здесь, например, 4.0, все хорошо; дальше идут пробелы, потом идет слэш. И когда мы делаем токенизацию по пробелу, все эти пробелы убираются, и получается, 4.0 — один токен, вот этот кусок — следующий токен, перевод каретки — это то, что надо предусмотреть, на самом деле, в токенизации. Поэтому попробуем, все-таки, ограничиться не служебными символами. И видим, что при этом оценки отфильтровались не слишком корректно. Значит, для того чтобы проблему эту решить, давайте не будем сейчас на это время тратить, требуется, первое — в квадратных скобочках указывать потенциальные элементы, на которые мы эти токены делить будем. То есть чаще всего это пробел, точка, запятая. Точка в нашем случае — это часть предложений. Поэтому, скорее всего, нам придется сделать несколько прогонов, чтобы отдельно оценку взять и отдельно — все остальное. Например, можно сделать так. Тогда у нас, как минимум, первая оценочка отделиться от всего остального, а остальное нас уже волновать не так будет. Из того, что получится, мы тогда хотим найти вот такие числа. Вот они — один, два… точнее, с одним баллом здесь нет, есть два, три, четыре. Значит, теперь мы должны отделить этот атрибут с помощью слэша. Убеждаемся, что слэш у нас не везде корректно распознался. Означает это, что, скорее всего, в нашем документе здесь есть служебный символ, который мы сейчас не видим. Значит, что это может быть за символ? Фактически, это может быть табуляция. Да, это она и есть, и отсюда были основные проблемы. В данном случае у нас есть 26 отзывов, в которых наблюдалась табуляция после 4.0. Дальше мы поняли, раз табуляция есть, то, например, можно указать пробел. Но пробел ничего не дает. Кроме табуляции может быть перевод каретки. Но он нам ничего не прибавил, значит, 2 и 3 тоже нам ничего не дают. Давайте мы перечислим все это в квадратных скобочках. Вот видим, что на самом деле, какие-то еще символы мешают нам эти оценки отделить. Но так или иначе смысл примерно такой. Значит, теперь, если мы получили эти оценки, то можно добавить к ним еще отдельные слова. Добавляем сюда пробел. Добавляем сюда, кроме оценок, еще обычные слова. Ну и как видите, в данном случае это выражение это выражение сработало не очень корректно. Связано это тоже с тем, что вот, как видите, мы получили немножко больше, чем хотели. Поэтому, как только мы извлекли вот такие токены, имеет смысл их ограничить еще и по длине. Итак, возвращаемся к нашему анализу. Мы разобрали часть документов, и теперь мы хотим использовать эти документы для дальнейшего изучения. Первое, что требовалось сделать, — это отделить оценки из наших документов. Оценки — это, соответственно, числа нецелые вида 4.0, 5.0, которые находятся в начале документа. И вот, соответственно, от каждого документа хотелось бы получить эту оценку и какие-то слова, которые его описывают. В токенизации для этого используем регулярное выражение. В самом выражении пишем табуляцию \t и пробел, для того чтобы отделить, по крайней мере, основную часть слов и плюс отделить основную оценку, которая табуляцией именно в начале отделяется. Дальше, в качестве контента фильтруем наши токены полученные тоже по регулярному выражению. Отделяем саму оценку. \d — это число от нуля для девяти, \. — это точка экранированная, и ноль, соответственно — просто цифра ноль, либо — это вертикальная черта, и все буквы от a до z в любой комбинации. То, что получилось фильтруем не менее, чем три символа по длине оставляем, для того чтобы оставить саму оценку, выкинуть различные предлоги и некоторые длинные слова для нашего анализа тоже можно исключить. Дальше, в процессе документов мы добавили ограничение процентное. Prune означает обрезка. В данном случае мы обрезаем все самые редкие слова не меньше десяти процентов встречаемости метрики TF-IDF. Оставляем все самые частые, на всякий случай. Убираем метаинформацию, пока что нам она не нужна. Дальше, здесь для примера можно, скажем, оставить только те кейсы, у которых оценка не меньше двух, а точнее, оставить только те кейсы, у которых оценка равна двум. Для этого мы используем вот такой вот атрибутный фильтр. 2.0 — это название атрибута. И больше или равно нулю означает, что в этом атрибуте должно стоять значение, больше, чем ноль. Давайте, пока, его выключим для примера. И то, что получилось, можно кластеризовать на сколько-то кластеров. Например, потенциально мы можем увидеть, скажем, три кластера с хорошими узорами отывами, с плохими и с нейтральными. И эти кластеры попытаемся визуализировать с помощью визуализатора кластеризации. Находится это в новой версии RapidMiner в сегментации, в разделе «Моделирование», «Сегментация» и внизу — Cluster module visualizer. Давайте посмотрим, что из этого выйдет. Во-первых, указывает по всем трем кластерам, какие самые частые атрибуты, а точнее, в данном случае, какие значения данные атрибуты применяют, самые большие. Дальше можно по нашей карте Heat map посмотреть некоторые характеристики каждого кластера. Также можно пословно увидеть, какие слова здесь встречаются в каждом сегменте. Можно увидеть центроиды, например, в среднем, или точнее, в первом кластере у нас сгруппированы в основном оценки 2, 3 и 4 в среднем. Второй кластер более размазанный, то есть здесь оценки встречаются более-менее равномерно. И третий кластер. В нем встречается либо плохая оценка, либо хорошая, причем хорошая довольно редкая — в два раза меньше, чем плохая. То есть, исходя из этого текущего вектора, получается, что кластеры достаточно перемешаны. Вот если посмотреть это с точки зрения соотношения слов, которые в них встречаются, можно увидеть эти точки, как они выбираются. Видно, что конкретно average в первом кластере встречается наиболее часто, premise — наиболее часто, скучно — тоже наиболее часто. Звезды, reads и слово average, наоборот, во втором кластере встречаются реже всего. Отсюда у них получается типовое значение очень маленькое. И во втором кластере feels, reads и stars принимают большое значение. Всего-то это три такие комбинации по три переменных, которые в целом-то кластер и определяют. Вот мы видим, что получилось не очень, в основном от того, что слова в данном случае у нас оказались довольно-таки разнообразными. Если посмотреть word list — эта вкладочка получается от того, что word-выход соединен с результатом. Видно, что в целом, исходя из того, что у нас всего 50 отзывов, довольно много слов повторяются в каждом отзыве. То есть какой-то типичности здесь, пока что, мы не видим. Следует вернуться вот сюда, и, например, добавить еще одну фильтрацию по нашим токенам, по контенту. Давайте вернемся к концепции хороших и плохих слов. Вот мы видим, что надо еще добавить наши оценки. Оценки — это то, что мы уже ранее писали. Почему я не добавляю этот фильтр себе сюда, в начало? Потому что хочется себе ограничить свободу выбора для того, чтобы в дальнейшем можно было довольно тонко настраивать уже токены, которые мы максимально полно получили. Так, вот у нас есть все оценки — есть good и есть bad слова. И теперь смотрим на центроид. Значит, вот у нас есть… наверное, вот так будет более показательно… в перовом сегмент — оценки 4, 5 и чаще встречается слово good. В первом кластере — тут все понятно. Второй кластер — это, в основном, плохая оценка, два, чаще всего встречается слово bad. И наконец, оставшийся кластер — оценка три, и в общем-то, встречается чаще слово «хороший» примерно в соотношении, похожем на самый первый наш сегмент. Но, тем не менее, соотношение отличается bad и good. Вот уже здесь видно, что первый кластер — это, скорее всего, хорошие отзывы, второй — это плохие, и третий кластер — неопределившиеся. То есть вот уже из этого можно наш анализ дальше развернуть. Допустим, добавить кроме слов good и bad слово «скучный». Мы в данном случае стемминг не производили, поэтому boring можно написать, как есть. Это слово встречается. Смотрим в кластере — оно, как не удивительно, встречается и в первом, и во втором кластере примерно одинаково, а в третьем кластере (неопределившиеся) встречается почти также часто, как слово «плохо». Почему здесь пересчитались частоты? От того, что частоты пересчитываются, исходя из уже оставшихся вот этих токенов, то есть частота внутри документа на частоту по всем документам сразу. Это метрика TF-DF, означает, частота внутри документа, она считается от общего числа слов. Поэтому изменилось именно из-за того, что «скучно» присутствует везде в данном случае. Давайте еще добавим, все-таки, для контроля еще одно слово, уже хорошее, которое в данном случае не нашлось. Тогда добавим слово «мастерски». Оно тоже не встретилось, потому что оно слишком редкое. Для того чтобы определить,что же еще стоит выбрать, можно опять отключить наш конечный фильтр, посмотреть список слов. Можно фильтровать по убыванию. Вот, например, по документам довольно много, как видите, глаголов. Собственно, есть… можно, наверное, слово interesting взять для нашего фильтра. Оно сюда включается. И видно, по крайней мере, что в первом кластере, в котором оценки лучше, это слово, как и good встречается довольно часто. У него частота больше, чем у bad и boring. Во втором сегменте, где оценка в данном случае, уже после кластеризации, наоборот, средненькая, все представлено более-менее равномерно, однако, «хорошо» и «интересно» встречается, все-таки, довольно часто. И во втором кластере, где оценка плохая, — двойка в основном, плюс еще чуть-чуть четверки — часто встречаются bad и boring, значительно больше, чем good и interesting. В данном случае у нас явно ложно положительное срабатывание произошло, поэтому подмешался отзыв сюда с четверкой. Однако, тем не менее, кластеризация, как видите, более-менее получилась успешно. Вот здесь она показательно видна. Нулевой кластер — хорошие оценки, в которых, скорее, хорошие слова представлены. Второй кластер — средняя оценка, где более-менее равномерно, но в сторону «хорошо» представлены оценочки. И красный кластер, где, в основном, слово bad представлено и плохая оценка. Что с этими кластерами можно было бы затем сделать? Для кластеризации у нас уже все сделано, значит, можно было бы на этой модели обучить классификатор, который дальше словесные наши отзывы ужа автоматически относил бы к хорошим или плохим для дальнейшего подсчета. То есть мы уже вот здесь — в результатах — видим, что у нас всего хороших отзывов — это вот первый кластер — 15, плохих — 17, неопределившихся — 16. То есть по сути, скорее отзывы положительные на этой нашей выборке, если 15 и 16 сложить. То есть нейтральные и позитивные составляют примерно две третьих от всей нашей выборки. Значит, в целом, можно сказать, что выборка наша людей оценила книгу положительно. Сама книга — это «Марсианин» — известная. Поэтому, в целом наша оценка соответствует действительности. Что можно про текстовый анализ в RapidMiner сказать — то, что он, в принципе, конечно больше настроен на английский язык и на европейские языки, русский в нем поддерживается, фактически, очень ограничено. Токенизовать, конечно, можно, подсчитывать частоты можно, если вручную все это указывать. Иногда бывает проблема с кодировкой, которую здесь тоже можно решать. Но в целом, решать эту задачу здесь тоже можно. Основной смысл текстового анализа в данном случае — что сам вот этот конкретный text processing (расширение), оно поддерживает предобработку наших данных. То есть мы текст должны перевести в числа, так или иначе. Эти числа можно дальше по обычной нашей модели провести и кластеризовать, и классифицировать, находить какие-то зависимости, пытаться использовать эти текстовые векторы для предсказывания чего-то еще. То есть в общем-то решать обычные задачи машинного обучения. Надеюсь, этот кусочек видео был вам полезен для того, чтобы научиться работать с текстом, по крайней мере, начать. И желаю вам успеха в этом. Спасибо за внимание.