matplotlib
Основным материалом по matplotlib будет следующий ресурс: http://nbviewer.jupyter.org/gi[..]_python/tree/master/
Задача 1
Глобальная задача: увидеть, что в питоне для умножения больших чисел используется алгоритм Карацубы, а также получить практически его асимптотику.
Должен получиться график в духе такого:
В данной задаче нужно:
- Научиться генерить случайные целые числа длиной k бит;
- Научиться измерять время нескольких операций, используя таймер time.process_time();
- Отобрать набор битовых длин для изучения времени: геометрическую прогрессию с началом в 30 и окончанием в 300000 бит длиной 150-300 челов;
- Вычислить среднее время умножения нескольких пар чисел;
- Построить график времени в log-log шкале (пусть битовые длины k[i], а времёна t[i], нужно построить зависимость log(t[i]) от log(k[i]);
- Найти такую прямую l(x) = ax+b, что сумма квадратов разностей (log(t[i]) – l(log(k[i]))) для битовых длин k[i] > 2000 минимальна;
- Построить график этой прямой в log-log шкале, а также вычислить параметры в обычной шкале (log(y) = a log(x) + b => y = e^(b)*x^(a))
- Подписать эту прямую на графике
Задача 2
В данной задаче нужно:
- Прочитать про датасет по ссылке выше в википедии;
- Научиться загружать эти данные и изучить их;
- Построить графики как в примере ниже;
- Научиться решать следующую задачу: даны два множества точек на плоскости таких, что они разделимы прямой, то есть существует прямая такая, что все точки одного множества лежать по одну сторону от прямой, а точки второго
по другую. Необходимо найти хотя бы одну такую прямую; - Улучшение 4: нужно найти такую прямую, что минимальное расстояние до любой из точек максимально.
- (Подсказка к п. 5: оказывается такая прямая всегда является либо серединным перпендикуляром к отрезку, соединяющему точки разных классов, либо параллельна прямой, проходящей через две точки одного класса (докажите это). Поэтому нужную прямую можно найти за квадратичное время.
- Для простоты будем классифицировать только ирисы видов setosa и virginica, поэтому удалите из выборки по versicolor. Выберите пару параметров, лучше всех разделяющих разные классы Ирисов. Для классификации нужно построить разделяющую прямую в плоскости этих двух параметров.
- После того, как всё это получилось, займёмся валидацией и причёсыванием кода. Для начала создадим класс нашего классификатора со следующей структурой (см. код класса ниже). Добейтесь того, чтобы он на глазок работал.
- После того, как мы создали класс классификатора и научились классифицировать ирисы, нужно проверить качество наших предсказаний. Обычно это делается при помощи кросс-валидации. Идея кросс-валидации в следующем: разобьём нашу обучающую выборку на n частей. Для каждой из этих частей выполним обучение на оставшихся (n-1) части, выполним предсказание на данной части и сравним с ответом. Посчитаем долю правильных ответов. На выходе мы получим строку из n чисел — качеств предсказаний. Посчитаем среднее значение — это и будет качество предсказания на кросс-валидации. Этот пункт обзорный, подробности будут дальше.
- Реализуйте функцию accuracy_score(clf, X, y), принимающую на вход уже обученный классификатор, данные для предсказания и вектор ответов. Функция должна возвращать долю правильных ответов. Проверьте, что ваша функция работает на вашем классификаторе из п.7.
- Следующий шаг — разбивка всего множества на n частей. Здесь нужно реализовать класс KFold с двумя методами: init(self, n_splits=5, random_state=None) и split(self, X, y=None). Конструктор должен только лишь сохранять параметры в своих атрибутах. Метод split должен возвращать список из n_splits элементов. Каждый элемент списка — это пара массивов train_index, test_index. Объединение этих массивов — набор индексов от 0 до X.shape[0]-1. В массиве test_index должно быть примерно (X.shape[0]/n_splits) элементов. Массив индексов от 0 до X.shape[0]-1 перемешивается и делится на n_splits примерно равных частей. Соответственно каждый набор test_index — это набор индексов из этих n_splits частей, а train_index — оставшиеся (n_splits-1) частей. Параметр random_state используется следующим образом: если он передан, то необходимо вызвать np.random.seed(random_state) для того, чтобы при заполненном параметре разбиение каждый раз получалось одинаковым. Параметр y здесь не используется, он потребуется в будущем.
- Финальный шаг — функция cross_val_score(estimator, X, y, scoring, cv). Она принимает на вход классификатор clf (необученный), множество для обучения X, вектор ответов y, функцию для вычисления качества scoring, а также элемент класса KFold для разбивки тестового множества на n_splits классов. Функция должна n_splits раз обучить классификатор clf на данных X[train_index], вычислить качество предсказания при помощи функции scoring (вектор ответов — это y[train_index]). После чего вернуть массив длины n_splits — качество предсказания на каждом из шагов.
- Теперь можно пытаться разделять виды versicolor и virginica. Здесь множества не разделяются, поэтому нужно придумать какой-нибудь штраф за нахождение не в той полуплоскости и каким-нибудь образом находить прямую с минимальным штрафов. Проверьте качество вашей классификации при помощи уже реализованной кросс-валидации.
- Весь набор тестер-фолдер-валидатор очень удобно использовать для проверки качества реализованного классификатора. Он пригодится и в следующей задаче, поэтому после того, как всё заработает, причешите код. Сделайте его красивым и удобным.
from sklearn import datasets
# После этой команды будет загружен словарь (выполнить один раз)
iris = datasets.load_iris()
# Сохраняем данные на компьютер (выполнить один раз)
# data, target, feature_names, target_names = iris['data'], iris['target'], iris['feature_names'], iris['target_names']
# with open(r'M:\np_basic\iris.dump', 'wb') as f:
# pickle.dump((data, target, feature_names, target_names), f)
# Загрузка данных из сохранённого дампа
with open(r'M:\np_basic\iris.dump', 'rb') as f:
(data, target, feature_names, target_names) = pickle.load(f)
import numpy as np
class SimpleSplitLineClassifier():
if len(X.shape) != 2:
if len(y.shape) != 1:
self.classes_ = sorted(set(y)) # Упорядочиваем классы для ответов
if len(self.classes_) != 2:
if X.shape[0] != y.shape[0]:
self.X_ = X
self.y_ = y
# Находим разделяющую прямую ax+by+c=0.
# Для классификации мы будем подставлять точку (x,y) в уравнение этой прямой,
# если полученное значение больше или равно нулю, то классифицируем в self.classes_[0], иначе – в self.classes_[1]
self.a, self.b, self.c = 0, 0, 0 # Вы ведь уже научились находить эту прямую?
return self
if len(X.shape) != 2:
if X.shape[1] != self.X_.shape[1]:
predictions = np.zeros(len(X)) # Вы ведь уже научились определять ирисы?
return predictions
def get_params(self, deep=True): # Получить текущие параметры классификатора (у нас их нет)
# Создаём классификатор
clf = SimpleSplitLineClassifier()
# Обучаем его
clf.fit(np.array( [ [1, 0], [1, 1], [-1, 0], [-1, 1] ] ), np.array([0, 0, 1, 1]))
# Предсказываем
print(clf.predict(np.array( [ [1, 0], [2, 0] ] )))
class KFold:
self.random_state = random_state
return ...
def accuracy_score(clf, X, y):
accuracy = ...
return accuracy
def cross_val_score(estimator, X, y, scoring, cv):
return ...
cv_folder = KFold(n_splits=3, random_state=179)
print(cross_val_score(estimator=clf, X=x_train, y=y_train, scoring=accuracy_score, cv=cv_folder))
Задача 3
Титаник
Данные:
file:/titanic_train.csv
import numpy as np
import pandas as pd
titanic_df = pd.read_csv("titanic_train.csv")
# Вектор ответов
y_train = titanic_df['Survived'].as_matrix()
# Удаляем ненужные столбцы
titanic_df.drop(['PassengerId','Name','Ticket','Survived'], axis=1, inplace=True)
# Данные
columns = titanic_df.columns
x_train = titanic_df.as_matrix()
Описание столбцов:
- PassengerId — идентификатор пассажира
- Survival — поле в котором указано спасся человек (1) или нет (0)
- Pclass — содержит социально-экономический статус:
- высокий
- средний
- низкий
- Name — имя пассажира
- Sex — пол пассажира
- Age — возраст
- SibSp — содержит информацию о количестве родственников 2-го порядка (муж, жена, братья, сетры)
- Parch — содержит информацию о количестве родственников на борту 1-го порядка (мать, отец, дети)
- Ticket — номер билета
- Fare — цена билета
- Cabin — каюта
- Embarked — порт посадки
- C — Cherbourg
- Q — Queenstown
- S — Southampton
Для kaggle:
file:/titanic_test.csv
test_df = pd.read_csv("train.csv")
# Сохраняем ID пассажиров
PassengerIds = test_df['PassengerId'].as_matrix()
# Удаляем ненужные столбцы
test_df.drop(['PassengerId','Name','Ticket','Survived'], axis=1, inplace=True)
# Делаем предсказание
y_pred = np.zeros_like(PassengerIds)
# Генерим ответ
submission = pd.DataFrame({"PassengerId": PassengerIds, "Survived": y_pred})
submission.to_csv('titanic_submission.csv', index=False)