На этом шаге мы приведем постановку задачи.
В качестве примера мы воспользуемся набором данных, который содержит киноотзывы, оставленные на сайте IMDb (Internet Movie Database) и собранные исследователем Стэнфордского университета Эндрю Маасом.
Этот набор данных содержит тексты отзывов, а также метки, которые указывают тональность отзыва ("положительный" или "отрицательный"). Сайт IMDb имеет собственную систему оценки фильмов от 1 до 10. Чтобы упростить процесс моделирования, эта система оценки будет сведена к двум классам, отзывы с оценкой 6 или выше помечаются как положительные, а остальные отзывы помечаются как отрицательные. Вопрос, касающийся качества подготовки исходных данных, мы оставляем открытым и просто используем данные в том виде, в каком их нам предоставил Эндрю Маас.
После распаковки набор данных представляет собой две отдельные папки с текстовыми файлами, одна папка - для обучения, а вторая - для тестирования. Каждая папка в свою очередь содержит две подпапки, одна называется pos, а другая - neg.
[In 2]: !tree D:/Data/aclImdb D:/Data/aclImdb |---- test | |--- neg | |--- pos |---- train | |--- neg | |--- pos
Папка pos содержит все положительные отзывы, каждый отзыв записан в виде отдельного текстового файла, папка neg содержит все отрицательные отзывы и так же каждый отзыв представлен в виде отдельного текстового файла. В библиотеке scikit-learn есть вспомогательная функция load_files(). Она позволяет загрузить файлы, для хранения которых используется такая структура папок, где каждая вложенная папка соответствует определенной метке. Сначала мы применим функцию load_files() к обучающим данным.
[In 3]: from sklearn.datasets import load_files reviews_train = load_files("D:/Data/aclImdb/train/") # load_files возвращает коллекцию, содержащую обучающие тексты и обучающие метки text_train, y_train = reviews_train.data, reviews_train.target print("тип text_train: {}".format(type(text_train))) print("длина text_train: {}".format(len(text_train))) print("text_train[1]:\n{}".format(text_train[1])) тип text_train: <class 'list'> длина text_train: 75000 text_train[1]: b"Amount of disappointment I am getting these days seeing movies like Partner, Jhoom Barabar and now, Heyy Babyy is gonna end my habit of seeing first day shows.<br /><br />The movie is an utter disappointment because it had the potential to become a laugh riot only if the d\xc3\xa9butant director, Sajid Khan hadn't tried too many things. Only saving grace in the movie were the last thirty minutes, which were seriously funny elsewhere the movie fails miserably. First half was desperately been tried to look funny but wasn't. Next 45 minutes were emotional and looked totally artificial and illogical.<br /><br />OK, when you are out for a movie like this you don't expect much logic but all the flaws tend to appear when you don't enjoy the movie and thats the case with Heyy Babyy. Acting is good but thats not enough to keep one interested.<br /><br />For the positives, you can take hot actresses, last 30 minutes, some comic scenes, good acting by the lead cast and the baby. Only problem is that these things do not come together properly to make a good movie.<br /><br />Anyways, I read somewhere that It isn't a copy of Three men and a baby but I think it would have been better if it was."
Видно, что text_train представляет собой список длиной 75000, в котором каждый элемент представляет собой строку, содержащую отзыв. Мы напечатали отзыв с индексом 1. Кроме того, можно увидеть, что отзыв содержит разрывы строк HTML (<br />). Хотя эти разрывы вряд ли сильно повлияют на модель машинного обучения, лучше выполнить очистку данных и удалить символы форматирования перед тем, как начать работу.
[In 4]: text_train = [doc.replace(b"<br />", b" ") for doc in text_train]
Тип элементов text_train будет зависеть от вашей версии Python. В Python 3 они будут иметь тип bytes, который представляет собой двоичное кодирование строковых данных. В Python 2 text_train состоит из строк. В данном случае мы не будем вдаваться в подробности различных строковых типов данных, имеющихся в Python, но мы рекомендуем вам прочитать разделы документации по Python 2 и/или Python 3, касающиеся строковых данных и Unicode.
Набор данных был собран таким образом, чтобы положительный и отрицательный классы были сбалансированы, поэтому количество строк с положительными отзывами и количество строк с отрицательными отзывами одинаковое:
[In 5]: print("Количество примеров на класс (обучение): {}".format(np.bincount(y_train))) Количество примеров на класс (обучение): [12500 12500 50000]
Аналогичным образом загружаем тестовые данные:
[In 6]: reviews_test = load_files("D:/Data/aclImdb/test/") text_test, y_test = reviews_test.data, reviews_test.target print("Количество документов в текстовых данных: {}".format(len(text_test))) print("Количество примеров на класс (тест): {}".format(np.bincount(y_test))) text_test = [doc.replace(b"<br />", b" ") for doc in text_test] Количество документов в текстовых данных: 25000 Количество примеров на класс (тест): [12500 12500]
Задача, которую мы хотим решить, можно сформулировать следующим образом: каждому отзыву нам нужно присвоить метку "положительный" или "отрицательный" на основе текста отзыва. Это стандартная задача бинарной классификации. Однако текстовые данные представлены в формате, который модель машинного обучения не умеет обрабатывать. Нам нужно преобразовать строковое представление текста в числовое представление, к которому можно применить алгоритмы машинного обучения.
На следующем шаге мы рассмотрим представление текстовых данных в виде "мешка слов".