{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Лабораторная работа 2\n", "\n", "## Общая информация\n", "\n", "Дата выдачи: 18.03.2016\n", "\n", "Срок сдачи: 5.04.2016 09:00MSK\n", "\n", "### О задании\n", "Домашнее задание направлено на реализацию наивного байесвского классификатора для многоклассового случая.\n", "\n", "### Оценивание и штрафы\n", "Каждая из задач имеет определенную «стоимость» (указана в скобках около задачи). Максимально допустимая оценка за работу — 10 баллов. Обратите внимание, что только за реализацию функций без подтверждения их корректной работы оценка выставляться не будет.\n", "\n", "Сдавать задание после указанного срока сдачи нельзя. При выставлении неполного балла за задание в связи с наличием ошибок на усмотрение проверяющего предусмотрена возможность исправить задание на указанных в ответном письме условиях.\n", "\n", "Задание выполняется **САМОСТОЯТЕЛЬНО**. «Похожие» решения считаются плагиатом и все задействованные студенты (в том числе те, у кого списали) не могут получить за него больше 0 баллов. Если вы нашли решение какого-то из заданий (или его часть) в открытом источнике, необходимо указать ссылку на этот источник в отдельном блоке в конце данного ноутбука (скорее всего вы будете не единственным, кто это нашел, поэтому чтобы исключить подозрение в плагиате, необходима ссылка на источник). \n", "\n", "\n", "### Формат сдачи\n", "Для сдачи задания переименуйте получившийся файл \\*.ipynb в соответствии со следующим форматом: *HW3_Username.ipynb*, где *Username* — Ваша фамилия на латинице (например, *HW3_Zinnurova.ipynb*). Далее отправьте этот файл на используемую в Вашей группе почту курса (hse.minor.dm+13@gmail.com для ИАД-13)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Наивный байесовский классификатор" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Обучение методом наивного Байеса основывается на достаточно сильном предположении, что все признаки независимы в совокупности. По формуле Байеса\n", "$$P(y|x) = P(y|(x^1,\\dots,x^d))=\\frac{P(y)P(x^1,\\dots,x^d|y)}{P(x^1,\\dots,x^d)}.$$\n", "В предположении, что признаки независимы, получаем, что \n", "$$P(y|x^1,\\dots,x^d)=\\frac{P(y)\\prod_{i=1}^d P(x^i|y)}{P(x^1,\\dots,x^d)}$$\n", "Т.к. $P(x^1,\\dots,x^d)$ не зависит от $y$, то формула наивного байесовского классификатора записывается следующим образом:\n", "\n", "$$\\hat y (x) = \\arg\\max_y P(y)\\prod_{i=1}^d P(x^d|y).$$\n", "\n", "\n", "Библиотека `sklearn` поддерживает несколько реализаций наивного Байеса: `sklearn.naive_bayes.GaussianNB`, `sklearn.naive_bayes.MultinomialNB` и др." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from sklearn.cross_validation import train_test_split\n", "from sklearn.datasets import fetch_20newsgroups\n", "from sklearn.naive_bayes import MultinomialNB\n", "from sklearn.feature_extraction.text import CountVectorizer\n", "import pandas as pd\n", "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Данные\n", "\n", "Данными для задачи будет выступать подмножество одного из популярных датасетов [20 News Groups](http://qwone.com/~jason/20Newsgroups/), который является набором статей, разбитых по категориям (темам).\n", "\n", "Пример статьи на тему космоса:\n", " \n", " From: MUNIZB%RWTMS2.decnet@rockwell.com (\"RWTMS2::MUNIZB\") \n", " \n", " Subject: Alaska Pipeline and Space Station! \n", " \n", " X-Added: Forwarded by Space Digest \n", " \n", " Organization: [via International Space University] \n", " \n", " Original-Sender: isu@VACATION.VENARI.CS.CMU.EDU \n", " \n", " Distribution: sci \n", " \n", " Lines: 16 \n", " \n", " on Date: 01 Apr 93 18:03:12 GMT, Ralph Buttigieg writes: \n", " \n", " Why can't the government just be a tennant? Private commercial concerns could just build a space station system and charge rent to the government financed researchers wanting to use it. I believe that this was the thought behind the Industrial Space Facility. I don't remember all the details, but I think Space Services (?) wanted NASA to sign an anchor tenancy deal in order to help secure some venture capital but NASA didn't like the deal. (I'm sure I'll hear about it if I'm wrong!) \n", " \n", " Disclaimer: Opinions stated are solely my own (unless I change my mind). \n", " \n", " Ben Muniz \n", " MUNIZB%RWTMS2.decnet@consrt.rockwell.com w(818)586-3578 Space Station \n", " Freedom:Rocketdyne/Rockwell:Structural Loads and Dynamics \"Man will not fly for fifty years\": Wilbur to Orville Wright, 1901\n", "\n", "Можно заметить, что данные никак не предобработаны, пунктуация и служебная информация сохранены.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Задание 1. (2 балла)** Выберите 2 произвольные категории текстов из списка ниже, с которыми вы будете работать в рамках данного задания. В переменной text находится список статей выборки, в переменной y — вектор ответов для них. Обратите внимание, что в качестве ответов выступают индексы тем в списке theme_list, а не сами названия тем. Выберите тексты, относящиеся к выбранным Вами темам (и сохраните сами тексты и вектор ответов для них в переменные text и y соответственно) и случайным образом, в пропорции 70/30, разделите наборы текстов на обучающую и контрольную выборки. В результате выполнения данного задания у вас должно получится 5 переменных: text, text_train, text_test, y_train, y_test.\n", "\n", "Обратите внимание, что данные уже \"перемешаны\", поэтому можно проивести разделение аналогично п. 5' ДЗ №2." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Список новостных заголовков\n", "theme_list = \n", "['alt.atheism',\n", " 'comp.graphics',\n", " 'comp.os.ms-windows.misc',\n", " 'comp.sys.ibm.pc.hardware',\n", " 'comp.sys.mac.hardware',\n", " 'comp.windows.x',\n", " 'misc.forsale',\n", " 'rec.autos',\n", " 'rec.motorcycles',\n", " 'rec.sport.baseball',\n", " 'rec.sport.hockey',\n", " 'sci.crypt',\n", " 'sci.electronics',\n", " 'sci.med',\n", " 'sci.space',\n", " 'soc.religion.christian',\n", " 'talk.politics.guns',\n", " 'talk.politics.mideast',\n", " 'talk.politics.misc',\n", " 'talk.religion.misc']" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [], "source": [ "dataset = fetch_20newsgroups(subset = 'train')\n", "perm = np.random.permutation(pd.Series(dataset.data).index)\n", "text = pd.Series(dataset.data).reindex(perm)\n", "y = pd.Series(dataset.target).reindex(perm)\n", "## Your code here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Задание 2. (2 балла)** На данный момент данные имеют текстовый вид, и не очень понятно, как с ними работать дальше. В этом задании мы приведем их к числовому представлению. Для каждого текста признаками будут являться количество вхождений конкретного слова в данный текст. Например, для выборки из двух текстов {\"one two two\", \"one three two\"} матрицей \"объект-признак\" будет являться\n", "\n", "$$\\left[ \\begin{matrix} 1 & 2 & 0 \\\\ 1 & 1 & 1 \\end{matrix} \\right],$$\n", "\n", "где номер строки в матрице совпадает с номером текста в выборке, признаки обозначают количество вхождений слова \"one\", \"two\" или \"three\" соответственно (слева направо).\n", "\n", "[CountVectorizer](http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.CountVectorizer.html) — объект, позволяющий привести выборку, состоящую из текстов, к указанному выше виду. Необходимый объект уже создан в ячейке ниже.\n", "* Метод **fit** объекта CountVеctorizer позволяет \"сохранить\" в его внутренней структуре набор всех уникальных слов из передаваемого параметра.\n", "* Метод **transform** этого же объекта позволяет привести набор текстов, переданный в качестве параметра, к указанному выше виду.\n", "\n", "Вызовите метод fit объекта vectorizer из ячейки ниже, передав в качестве параметра набор текстов text, — таким образом он \"запомнит\" все имеющиеся в выборке слова. Затем дважды вызовите метод transform, передав ему параметры text_train и text_test соответственно — таким образом вы получите необходимое представление ваших обучающей и контрольной выборок. Сохраните их в переменные X_train и X_test соответственно — таким образом, вы получили 2 матрицы \"объекта-признак\". Обратите внимание, что эти матрицы являются сильно разреженными, поэтому вызовите для каждой из них метод .toarray(), чтобы привести их в типу np.ndarray." ] }, { "cell_type": "code", "execution_count": 65, "metadata": { "collapsed": false }, "outputs": [], "source": [ "vectorizer = CountVectorizer(analyzer='word', stop_words='english', lowercase=True)\n", "## Your code here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Задание 3. (3 балла)** По матрице X_train выведите 50 наиболее часто встречающихся слов.\n", "\n", "Для этого вам сначала необходимо сложить все строки X_train, чтобы найти общее количество вхождений для каждого слова. Далее используйте метод argsort() (выполняет сортировку вектора по возрастанию, однако возвращает вектор не значений, а их **индексов**). Таким образом, 50 последних значений в получившемся векторе — это номера признаков, которые отвечают за самые частые слова. Теперь, чтобы получить сами слова, используйте метод vectorizer.get_feature_names() (возвращает список слов в том порядке, в котором расположены отвечающие им столбцы в матрице X_train)." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [], "source": [ "## Your code here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Задание 4. (2 балла)** Обучите наивный байесовский классификатор MultinomialNB с параметром alpha=1 на выборке train. Примените его к данным контрольной выборки test и выведите долю верно классифицированных текстов.\n", "\n", "[Пример](http://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.MultinomialNB.html) использования MultinomialNB (раздел Examples).\n", "Данный объект имеет 2 необходимых вам метода:\n", "* fit(X_train, y_train) — обучение наивного байесовского классификатора\n", "* predict(X_test) — предсказание ответов обученного классификатора на контрольной выборке" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [], "source": [ "## Your code here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Задание 5. (1 балл)** Обучите наивный байесовский классификатор MultinomialNB с параметром alpha=0 на выборке train. Примените его к данным контрольной выборки test и выведите долю верно классифицированных текстов. Поменяются ли результаты?" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [], "source": [ "## Your code here" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.8" } }, "nbformat": 4, "nbformat_minor": 0 }