Архив автора: zab88

Реализация алгоритма кластеризации шумных данных DBSCAN на python

Самым известным алгоритмом кластеризации является k-means, с него начинаются все обучающие примеры по кластеризации. Но несмотря на простоту и скорость k-means, у него есть одна очень большая проблема — это наперед заданное количество кластеров. В реальном же мире чаще всего нам не известно на сколько групп следует разбить данные, более того часть данных могут быть вредными выбросами. DBSCAN отлично разбивает множество на оптимальное количество кластеров и не учитывает выбросы, неудивительно что в 2014ом году алгоритм получил метку «проверено временем» на одной из конференций по анализу данных.
Мы будет рассматривать реализация на основе библиотеки sklearn
* В алгоритма два входных параметра min_samples и eps. Если в заданной окрестности eps есть минимальное необходимое количество объектов min_samples, то данная окрестность будет считаться кластером.
* Если в заданной области нет необходимого количества объектов, то инициирующая эту область точка считается выбросом
Кластеры, найденные DBSCAN могут иметь любую форму, в отличии от алгоритма k-means (которые предполагают только выпуклую форму)

Ниже приведём простой пример кластеризации с помощью DBSCAN.

from sklearn.datasets import load_iris
from sklearn.cluster import DBSCAN

iris = load_iris()
dbscan = DBSCAN(eps=0.5, min_samples=5)

dbscan.fit(iris.data)

# Готово! Распечатаем метки принадлежности к кластерам
print(dbscan.labels_)

Теперь давайте визуализируем полученный результат

from sklearn.decomposition import PCA
import matplotlib.pyplot as pl

pca = PCA(n_components=2).fit(iris.data)
pca_2d = pca.transform(iris.data)
for i in range(0, pca_2d.shape[0]):
    if dbscan.labels_[i] == 0:
        c1 = pl.scatter(pca_2d[i, 0], pca_2d[i, 1], c='r', marker='+')
    elif dbscan.labels_[i] == 1:
        c2 = pl.scatter(pca_2d[i, 0], pca_2d[i, 1], c='g', marker='o')
    elif dbscan.labels_[i] == -1:
        c3 = pl.scatter(pca_2d[i, 0], pca_2d[i, 1], c='b', marker='*')

pl.legend([c1, c2, c3], ['Cluster 1', 'Cluster 2', 'Noise'])
pl.title('DBSCAN finds 2 clusters and noise')
pl.show()

В результате получим вот такое разбиение по кластерам и шум
кластеризация dbscan

Hyperopt и xgboost: Пример поиска гиперпараметров с помощью Hyperopt для xgboost

Xgboost пожалуй самая популярная библиотека градиентного бустинга, поэтому именно на её примере покажу как можно улучшить качество простым техническим приёмом — автоматическим подбором параметров. Чтобы не усложнять поиск оптимальных гиперпараметров, возьмем лишь несколько основных: n_estimators, eta и max_depth. Основная идея библиотеки hyperopt — это построение математической гипотезы о том как выглядит функция результа на множества параметров и проверка этой гипотезы с каждой итерацией. Т.к. перебор и обучение может быть весьма продолжительны — то на вход задается количество итерации, после которого происходит остановка поиска. Но все равно предсказать, когда закончится поиск проблематично т.к. при разных гиперпараметрах обучение и предсказание занимает разное время. Поэтому я и советую начинать с небольшого количества итерации и небольшого количества параметров. К сожалению останова по истечению заранее заданного времени нет, поэтому мощный комьютер для data-sciece вам в руки и вперед!

import numpy as np
from sklearn import datasets
from sklearn.model_selection import cross_val_score
from xgboost import XGBClassifier

from hyperopt import hp, tpe
from hyperopt.fmin import fmin

# Для теста возьмем классический сет "ирисы Фишера"
# Разумеется вместо X и y Вам следует взять свои фичи и таргет
iris = datasets.load_iris()
X = iris.data
y = iris.target


def hyperopt_xgb_score(params):
    clf = XGBClassifier(**params)
    # усреднение по 3ем фолдам, для уменьшения влияния стахостичности
    # для ускорения можно использовать train_test_split один раз
    current_score = cross_val_score(clf, X, y, cv=3).mean()
    print(current_score, params)
    return -current_score


simple_space_xgb = {
            'n_estimators': hp.choice('n_estimators', range(100, 1000)),
            'eta': hp.quniform('eta', 0.025, 0.5, 0.025),
            'max_depth':  hp.choice('max_depth', np.arange(1, 14, dtype=int)),
}

best = fmin(fn=hyperopt_xgb_score, space=simple_space_xgb, algo=tpe.suggest, max_evals=10)
print('best:')
print(best)

Как видимо нет ничего сложного, главное определить:
1) пространство параметров, внутри которых hyperopt будет оптимизировать
2) функцию оценки.
Обратите внимание, что в функции оценки возвращается результат со знаком минус — это сделано специально, т.к. гиперопт минимизирует функционал, а нам надо максимизировать точность.
Для построения пространства в основном используется либо набор возможных значений (hp.choice) либо отрезок в пространстве R hp.quniform(label, low, high, q), где q округление.
Для тех, кто планирует более мощную настройку, оставлю space более мощный для XGB.

space_xgb2 = {
            'n_estimators': hp.choice('n_estimators', range(100, 1000)),
            'eta': hp.quniform('eta', 0.025, 0.5, 0.025),
            'max_depth':  hp.choice('max_depth', np.arange(1, 14, dtype=int)),
            'min_child_weight': hp.quniform('min_child_weight', 1, 6, 1),
            'subsample': hp.quniform('subsample', 0.5, 1, 0.05),
            'gamma': hp.quniform('gamma', 0.5, 1, 0.05),
            'colsample_bytree': hp.quniform('colsample_bytree', 0.5, 1, 0.05),
            'eval_metric': 'auc',
            'objective': 'binary:logistic',
            # Increase this number if you have more cores. Otherwise, remove it and it will default
            # to the maxium number.
            'nthread': 4,
            'booster': 'gbtree',
            'tree_method': 'exact',
            'silent': 1
        }

Теперь с помощью данного поста Вы можете построить оптимизацию гиперпараметров не ограничиваясь xgboost.

Пошаговая инструкция по установке tensorflow-gpu и keras на ubuntu

Как известно, нейронные сети весьма требовательны к вычислительным ресурсам и используя лишь мощность одного процессора обучение сети могут затянуться на часы, а то и дни и недели. Но на помощь пришли графические процессоры, в результате вычисления на графических процессорах, в силу иной архитектуры, проходят быстрее. К слову не только нейронные сети научились использовать GPU, некоторые алгоритмы градиентного бустинга весьма успешно используют GPU для ускорения обучения.

В данном посте будет рассказано об общем процесс установки составляющих, а в конце сравним скорость нейронной сети с использованием GPU и без.

Начальные требования:
операционная система: ubuntu 16, 17 или 18
видеокарта nvidia

Установка драйевров
Проверим какие драйверы установятся командой:

ubuntu-drivers devices

Вы должны увидеть примерно нижеследующий вывод:

== /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0 ==
modalias : pci:v000010DEd00001C81sv00001458sd00003765bc03sc00i00
vendor   : NVIDIA Corporation
model    : GP107 [GeForce GTX 1050]
driver   : nvidia-driver-390 - distro non-free recommended
driver   : xserver-xorg-video-nouveau - distro free builtin

Далее установим драйверы видеокарты:

sudo add-apt-repository ppa:graphics-drivers/ppa
sudo apt update
sudo apt upgrade

sudo ubuntu-drivers autoinstall

sudo reboot

После перезагрузки у вас появится возможность выполнять команду

nvidia-smi

запомните эту команду nvidia-smi — думаю она часто вам будет требоваться, чтобы посмотреть загрузку видеокарт, убить какой-нибудь процесс на видеокарте, да и смотреть текущую температуру для избегания перегрева.

Установка CUDA.
Важно, на данный момент нужна версия 9.0, для совместимости с tensorflow. Скачать можно по ссылке https://developer.nvidia.com/cuda-90-download-archive?target_os=Linux&target_arch=x86_64&target_distro=Ubuntu&target_version=1704&target_type=runfilelocal качаем base installer 1.6Gb и запасаемся терпением. Скорости на сайтах nvidia ограничены на отдачу файлов.
Убедитесь, что выбрана конфигурация загрузки как на изображении:
cuda

sudo sh cuda_9.0.176_384.81_linux.run --override --silent --toolkit

Если всё прошло удачно, то появится папка:
ls /usr/local/cuda-9.0/

Добавляем cuda в PATH

export PATH=/usr/local/cuda-9.0/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64\${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}

Установка cuDNN
Теперь надо вспомнить навыки регистрации, придётся зарегистрироваться на сайте nvidia для скачивания cudnn (это библиотека оптимизирует расчёт глубоких нейронных сетей)
Ссылка для скачивания https://developer.nvidia.com/compute/machine-learning/cudnn/secure/v7.1.4/prod/9.0_20180516/cudnn-9.0-linux-x64-v7.1

# разархивируем
tar -xzvf cudnn-9.0-linux-x64-v7.1.tgz 

# копируем файлы в директорию с CUDA
sudo cp cuda/include/cudnn.h /usr/local/cuda/include
sudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64

# немного меняем права, чтобы файлы библиотеки были доступны всем пользователям
sudo chmod a+r /usr/local/cuda/include/cudnn.h /usr/local/cuda/lib64/libcudnn*

Теперь добавляем пути в bashrc (в любом редакторе, я предпочитаю mc)

mcedit ~/.bashrc

И в конец файла пишем:

export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/cuda/lib64:/usr/local/cuda/extras/CUPTI/lib64"
export CUDA_HOME=/usr/local/cuda
export PATH=/usr/local/cuda-9.0/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64\${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}

Перезагрузим конфиг bashrc

source ~/.bashrc
sudo ldconfig

И проверим на наличие корректного пути:

echo $CUDA_HOME
# должно вывестить /usr/local/cuda

Установка tensorflow с поддержкой GPU
Подробная инструкция по установке есть на официальном сайте tensorflow.org/install/ но если не лезть в детали, то достаточно запустить 2 команды:

pip3 install tensorflow
pip3 install tensorflow-gpu

pip3 install keras

Теперь можно запускать пример с обучением и предсказанием нейронной сети, например с использованием keras библиотеки.
Отмечу, что по умолчанию keras использует именно GPU, однако считать можно и на CPU. Для сравнения скоростей расчетов можно использовать код отключения GPU — тогда расчёт будет производиться только за счёт процессора. Добавьте этот код перед импортом tensorflow и keras

import os
os.environ["CUDA_VISIBLE_DEVICES"] = ""

Конфигурация компьютера для машинного обучения. Бюджетный и оптимальный подбор.

Искусственный интеллект уже не первый год наступает на пятки естественному и делает это не в последнюю очередь за счёт роста мощности железа. Поэтому для создания современных алгоритмов ML вам скорее всего потребуется производительный компьютер. В данном посте будет предложена 2 сборки:
первая сборка ПК для ML: начинающая, рассмотрим минимальную систему с которой относительно комфортно работать, стоимостью до 30 тысяч рублей.
вторая сбалансированная цена/производительность: подороже, мощнее, позволяющая решать широкий круг задач. стоимостью 60-90 тысяч рублей.
Изначально думал выделить ещё и сборку для энтузиастов, но потом решил что те, кто готов выкладывать большие деньги на ML, те точно знают что они хотят и скорее всего будут собирать под конкретную задачу.

Процессор:
Основные показатели — количество ядер и производительность одного ядра. У Intel более быстрые ядра, зато у AMD за те же деньги вы получите больше ядер. Что важнее и где найти балланс, зависит от задач. Если будете гонять нейронки на видеокартах, то берите интел. Если хотите решать широкий круг задач, то AMD т.к. в конечном итоге при правильном распараллеливании программы расчёты будут идти бысрее. Но учтите, не всё можно распараллелить. По поводу гипертрэйдинга — он немного ускоряет систему, но в реальности не так значительно, поэтому ядра первостепенней.
Бюджетный вариант: 4-6 ядер
Средний вариант: 6-8 или более ядер с хорошим бустингом на одно ядро.

Оперативныя помять:
Бюджетный вариант: 16Gb
Средний: 32Gb двумя планками по 16, чтобы иметь возможность расшириться до 64 в случае необходимости. Больше 64Gb сокеты 1151-v2 и AM4 не поддерживают. Если хотите получить несколько дополнительный процентов производительности от AMD — берите более быструю память и обязательно 2ух канальную.
Много где в AI советуют чтобы количество оперативной памяти было в 2 раза больше чем видео памяти, у меня пока не сложилось конкретной рекомендации на эту тему, но оставлю это здесь.

Видеокарты:
В бюджетной сборке предлагаю обойтись вообще без видекарты (если в процессоре есть встроенная графика) или с самой дешевой, которую найдёте. Так можно сэкономить, приобретя более мощные остальные компоненты и оставляя возможность апргрейда. На ней Вы считать не будете — она только для вывода изображения на монитор и всё! Как же так, возможно кто-то спросит? Ответ простой — GPU в первую очередь нужна для нейронных сетей, но на слабой видеокарте вроде geforce 1050 скорость расчётов будет в большинстве случаев такой же как на мощном CPU. Некоторые алгритмы градиентного бустинга также умеют использовать мощь GPU, но на опыте — в сравнении с 1050 выигрыша никакого нет. А при покупке карты дороже, уже вылезем из бюджета в 30т.р.
В средней сборке видеокарта однозначно нужна и желательно помощнее. Выбор производителя однозначе — это nvidia. Стоит сразу отметить важную деталь — SLI вам никак не понадобится, tensorflow c cuda отлично распараллелены и вы можете использовать разные типы карт nvidia, вовсе не обязательно одинаковые. Однако в нейронных сетях есть такое понятие как батч (batch) и чтобы он был больше — нужно больше памяти на видеокарте. Чем больше batch тем лучше и дабы не быть ограниченным снизу слабой видеокартой по размеру batch — лучше брать видеокарты с одинаковым объёмом памяти.
Времена майнинга прошли и купить карту стало легче, брать ли БУ или нет — каждый пусть решит для себя самостоятельно. Чтобы облегчить выбор, напишу сравнительную производительность разных карт, за базу (1X) пусть выступит 1050. Это позволит вам лучше соотнести мощность с ценой и подобрать оптимум.
1050 1X
1050Ti 1.12X
1060 3Gb 1.95X
1060 6Gb 2.09X
1070 2.91X
1070Ti 3.39X
1080 3.7X
2070 3.9X
1080Ti 4.42X
2080 4.45X
2080Ti 5.79X
Меньше 4 Gb лучше не брать, может оказаться мало даже для простых задач.

Материнская плата:
В выборе материнской плате надо знать следующее — будете ли вы разгонять процессор и сколько видеокарт планируете подключать. Я не являюсь сторонником разгона, но если Вы планируйте выжимать из системы максимум — то обратите внимание на возможность разгона. Более тонкий момент с количеством видекарт, а точнее с количеством PCI-E линий. практически все материнки поддерживают 16 линий для одной видеокарты. Проблемы начинаются при использовании большего количества видеокарт для машинного обучения. Конфигурация 8PCI-E на 8PCI-E для двух видеокарт мне кажется оптимальной для среднего решения. Но если в планах использование только одной видеокарты, то можно и сэкономить не покупая более дорогой сокет.

Жесткий диск:
Бюджетная сборка: берите HDD, скажем на террабайт. Конечно система будет загружаться медленнее чем с ssd. но его можно будет потом докупить. А если сразу выложиться на ssd — то есть опасения что не влезут большие датасеты. Учтите, что на установку всех нужных библиотек и программ вполне может уйти под 100Gb жесткого диска.
В оптимальной сборке предлагается взять SSD + HDD. Некоторые модели SSD-M2 имеют повышенную скорость чтения и записи, по сравнению с обычными SATA3 ssd но с пользовательской стороны значительного ускорения не заметно, однаком любителям топчика — SSD-M2 советую, особенно если оперативной памяти маловато — будет очень быстрый swap.

Охлаждение и корпус:
В бюджетной версии можно обойтись самым простым корпусом, а вот в оптимальном уже стоит задуматься об охлаждении видеокарт/ы и процессора. Если видеокарты всё же две и между ними мало места — то верхняя будет греться ощутимо сильнее. Одно из самый простых и действенных решения — поставить вентилятор аля 140мм сбоку, дующий сразу на видеокарты. Ещё один лайфхак — дабы пыли внутри скапливалось поменьше — рекомендуется вентиляторы на вдув ставить мощнее вентиляторов на выдув.

Блок питания:
Основной параметр — мощность в ватах. Чтобы понять на сколько ватт нужен вам блок, рекомендую в поисковике вбить «power supply calculator» и Вы найдете несколько приятных интерфейсов для расчетов. Для самого бюджетного варианта вполне подойдёт блок на 400-500W, для систем с двумя видеокартами блока на 850W будет достаточно, 850W хватит даже для двух 2080Ti. Для одной 1080Ti или 2080Ti будет достаточно 600W. Для двух средних карт вроде 1070/2070 650/700W тоже будет достаточно. Цены на разные блоки питания скачут существенно, и параметров у них много, но обычно более дорогой блок питания оснащается большим количеством защит и если начинка стоит дорого, лучше взять блок качественнее.

Большинство компонентов можно приобрести на вторичном рынке — это будет заметно дешевле. Конечно, в покупке БУ комплектующих есть некоторый риск, но за те же деньги вы сможете получать результат вычислений быстрее. Меньше всего опасаться можно за процессоры и оперативную память, если они работают — то почти наверняка, при нормальной эксплуатации, они ещё будут работать лет десять.

Два примера Label Encoding или переводим строки в числа в pandas.

При решении задач машинного обучения, часто приходится иметь дело со строковыми параметрами. Чаще всего это категориальные фичи, например названия городов, цвета, должность итд. Некоторые библиотеки могут изначально работать со строковыми параметрами, но для большинства предварительно надо перевести буквы в цифры. Более того, это даже очень рекомендуется т.к. в числовом виде будет использоваться меньше оперативной памяти для хранения обучающей матрицы. Процесс перевода строковых фич (labels) в числовые фичи называется label encoding.

В данном посте будет предложено два практических способа label encoding (не путать с onehot encoding) для дата фреймов pandas. Таким образом у нас есть DataFrame train с категориальными фичами, которые надо преобразовать с помощью метода label encoding.

Способ 1.
Используя библиотеку sklearn.

from sklearn import preprocessing
import pandas as pd

train = pd.read_csv('train.csv')
test = pd.read_csv('test.csv')
cat_cols = ['city', 'color', 'position']

for col in cat_cols:
    lbl = preprocessing.LabelEncoder()
    lbl.fit(list(train[col].values.astype('str')) + list(test[col].values.astype('str')))
    print(lbl.classes_)  # взглянем на категориальные классы
    train[col] = lbl.transform(list(train[col].values.astype('str')))
    test[col] = lbl.transform(list(test[col].values.astype('str')))

Способ 2.
Этот способ основан на методе factorize из библиотеки pandas, поэтому если Вы не используете sklearn — можно «cэкономить» на импортах

import pandas as pd
# Сначала покажем классический пример
labels, uniques = pd.factorize(['b', 'b', 'a', 'c', 'b'])
print(labels)  # array([0, 0, 1, 2, 0])
print(uniques)  # ['b', 'a', 'c']

# а теперь пройдемся по всем категориальным колонкам
cat_cols = ['city', 'color', 'position']
for col in cat_cols:
    train[col], _ = pd.factorize(train[col])

Таким образом в обоих способах все строковые значения фич будут заменены на соответсвующие целочисленные значения, что позволит использовать меньше памяти и без дополнительной обработки запускать обучение в разных библиотеках.

Важное замечание, если Вы планируете использовать только линейные модели то onehot encoding сделать всё-таки придется, иначе линейная разделимость будет недостаточной. Для методов же, основанных на деревьях и градиентном спуске label encoding будет достаточно.

Генератор фич на основе математических операций

(Статья не закончена)
Для быстрого поиска фич, коррелируемых с таргетом. Использует перебор по алгебраическим операциям. На новую фичу ставится условие, что абсолютное значение корреляции нового должно превосходить максимальную из двух составных фич более чем в 1.5 раза и быть больше 0.25

import pandas as pd
import numpy as np


def search_features_by_correlation(df: pd.DataFrame, target):
    # only 1000 rows taken for better speed
    mx = df.copy()
    mx['target'] = target
    mx = mx.sample(min(df.shape[0], 1000))
    target = mx.target.values
    mx = mx.drop('target', axis=1)

    # определяем корреляция отдельно для каждой фичи
    single_cc = {}
    real_columns = []
    for k1, c1 in enumerate(mx.columns):
        if not str(c1).startswith('number'):
            continue
        if np.unique(mx[c1].values).shape[0] < 50:
            continue
        single_cc[c1] = np.corrcoef(mx[c1], target)[0][1]
        real_columns.append(c1)

    if len(real_columns) > 100:
        real_columns = real_columns[:100]

    all_combinations = combinations(real_columns, 2)

    def is_cc(col_names: list) -> list:
        cc_base = 0.25
        cc_base_x = 1.5
        res = []
        # signs_to_check = ['*', '/', '-', '+']
        signs_to_check = ['*', '/']

        if len(col_names) == 2:
            for s in signs_to_check:
                if s == '*':
                    prod = mx[col_names[0]] * mx[col_names[1]]
                elif s == '/':
                    prod = mx[col_names[0]] / mx[col_names[1]]
                elif s == '-':
                    prod = mx[col_names[0]] - mx[col_names[1]]
                elif s == '+':
                    prod = mx[col_names[0]] + mx[col_names[1]]

                prod_c = np.corrcoef(prod, target)[0][1]

                if abs(prod_c) > cc_base and abs(prod_c) > cc_base_x * max(abs(single_cc[col_names[0]]),
                                                                           abs(single_cc[col_names[1]])):
                    res.append([s])


        return res

    all_combinations = list(all_combinations)
    corr_results = list(map(is_cc, all_combinations))

    corr_results = {all_combinations[k]: el for k, el in enumerate(corr_results) if el}

    return corr_results

Простой пример классификации текста на python sklearn

Классификация текста — классическая задача в области обработки естественного языка. Лет 10-15 назад тема классификации бурлила в научных журналах, однако со временем бум утих. Это связоно с тем, что подход на основе TF-IDF показал точность близкую к 95%-99.9%. При такой точности на качество классификации больше уже влияют методы предобработки и особенности текста, чем непосредственно выбор самого алгоритма. Появление ембеддингов в 2013 году сильно повлияло на методы в обработке текстов, открыв новую эпоху. Сейчас практически все «production» решения основываются на ембеддингах, но! Тут надо сделать оговорку — ембеддинги чрезвычайно хороши для анализа коротких текстов, которыми сейчас полон интернет, а вот для средних и больших текстов — TF-IDF по прежнему на высоте!

Ниже я приведу базовый подход классификации на основе библиотеки sklearn в python. Код максимально короткий и понятный

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.ensemble import RandomForestClassifier
from sklearn.pipeline import Pipeline


texts = ['текст номер один', 'текст номер два', 'комьютеры в лингвистике', 'компьютеры и обработка текстов']
texts_labels = [1, 1, 0, 0]

text_clf = Pipeline([
                     ('tfidf', TfidfVectorizer()),
                     ('clf', RandomForestClassifier())
                     ])

text_clf.fit(texts, texts_labels)

res = text_clf.predict(['текст номер три'])
print(res)  # [1]

На входе у нас список из текстов и список размеченных классов, далее делаем Pipeline, который включает в себя векторизацию слов на основе TfIdf и классификатор RandomForest . Далее обучаем «пайплайн-классификатор» и пытаемся предсказать новый текст. Как видим классификацию тексто на python сделать очень просто.

Если у Вас получилось запустить первый пример, то наверно вы зададитесь вопросом, как поднять качество существующей модели. Для этого я дам список улучшений, которые следует попробовать.

1. предобработка текста. Попробуйте нормализовать слова, тогда одно смысловое слово в разных склонениях/спряжениях будет интерпретироваться программой одинаково и возможно поднимет качество.
2. У TfIdf есть много разных параметров, наиболее существенные это
2.1 добавить список стоп слов: параметр stop_words
2.2 добавить n-gramm ы слов : параметр ngram_range, например ngram_range=(1,2)
2.3 ограничить список фич, взяв только самые важные и отрезав менее важные: параметр max_features
3. попробовать другой классификатор, например from sklearn.linear_model import SGDClassifier или SVM , XGB итд. соответсвенно подбирая в каждом из них свои гиперпараметры

С помощью перечисленных шагов, Вы достаточно быстро подберёте оптимальный вариант для классификации и получите точность более 90% (основываясь на моём опыте). Если не так, то возможно надо посмотреть внимательнее корректность входных данных.

Примеры curl запросов из командной строки

Для быстрого тестирования запросов к web сервисам очень удобно использовать curl запросы из командной строки. Простой GET запрос легко ввести прямиком в браузере, но вот с POST уже будет сложнее. Разумеется есть множество программ с удобным интерфейсом, но часто бывает что они не всегда под рукой, не установлены или надо написать универсальную инструкцию. В таком случае гораздо быстрее открыть терминал, ввести команду и сразу получить результат. Для установки curl на linux достаточно выполнить команду

sudo apt-get update && sudo apt-get install curl

Здесь я приведу несколько наиболее типичных примеров CURL запросов.

Пример CURL POST запроса и CURL GET запроса
curl -X POST http://127.0.0.1/page
curl -X GET http://127.0.0.1/page

Пример отправки данных постом
вариант 1: curl -X POST -d «data1=1&data2=2″ http://127.0.0.1/page
вариант 2: curl -X POST -d ‘{«data1″: «1″, «data2″: «2″}’ http://127.0.0.1/page
О том как программно загружать файлы с помощью curl смотрите в статье о загрузке файлов курлом

Пример отправки файла
curl -i -X POST —form datafile=@/path/to/file.pdf http://127.0.0.1/page
Обратите внимание на параметр -i, определяющий получение от сервера только заголовка. Параметр не обязательный, но ведь обычно достаточно только знать загрузился файл или нет.

Пример CURL запроса с авторизацией
curl -u username:password http://127.0.0.1/page -XPOST -d «id=123″ -v
О полезном параметре -v ниже.

Пример CURL JSON запроса
curl -X POST http://127.0.0.1/page -d ‘{«id»: «123″}’ -H «Content-Type:application/json»
Некоторые сервисы бракуют запросы без указания content-type, поэтому в случае json запроса — лучше всегда отправлять хэдер json.

Из полезных параметров стоит рассмотреть команду -v (verbose) чтобы получить максимум информации по запросу.
О том как работать с curl запросом через прокси смотрите в данной статье.

Приведённых примеров должно хватить для использования в 95% , если понадобятся более тонкие запросы, то используйте

curl --help

DataFrame pandas базовые манипуляции с данными

Pandas — очень мощный инструмент для работы и манипуляций над данными с помощью python. Можно сказать, что pandas предоставляет возможности SQL базы данных, дополненные мощью python. Однако, работа с данной библиотекой иногда вызывает некоторые трудности, так как работать приходится по сути с матричными данными и объектами pandas да numpy, а переход к стандартным python типам и циклам неминуемо грозит кратной потерей функциональности. Поэтому для себя создал шпаргалку по работе с дата-фреймами:

Работа начинается с загрузки данных в DataFrame, поэтому для начала считаем данные:

df = pd.read_csv('some.csv')
# если Вам заранее известны типы, то чрезвычайно полезно задать типы колонок сразу - это сэкономит оперативную память.
# также можно использоть лишь несколько колонок, а не все колонки в файле
df = pd.read_csv('some.csv', usecols=["user_id", "id3"], dtype={"user_id": np.int64, "id3": np.uint16})

Возможно и самостоятельно создать DataFrame и добавить строки

# пример создания объекта дата-фрейм
pd.DataFrame(columns=['A', 'B'])
# пример добавления строки в дата-фрейм
df.append({'A':1, 'B':2}, ignore_index=True)

После создания или загрузки DF полезно посмотреть чтоже там за данные, для этого можно воспользоваться следующими операциями:

df.head()       # первые строки
df.tail()       # последние строки
df.sample(5)    # случайно выбранное кол-ва строк, полезно использовать для уменьшения матрицы для прогонки тестов
df.shape        # по аналогии с numpy - размерность матрицы
df.describe()   # математические данные
df.info()       # использование памяти

Возможно далее вам захочется получить точечное значение по координатам из дата фрема, тогда используйте ix

some_value = df.ix[2, 'som_col']  # похожие функции loc и iloc

Для фильтрации по колонкам пандас использует булевую логику, проще показать на примере:

filtered_data = df[df.some_col == 'apple']
filtered_data = df[(df.price > 10.0) & (df.some_col == 'apple')]

Далее приведём несколько примеров манипуляции с данными:

# пример удаления колонки:
df = df.drop("A", axis=1)
# удалит дубликаты
df = df.drop_duplicates()
# Создание новой колонки со значением по умолчанию
df['new_col'] = 1
# а вот так можно добавлять колонку с условием
df['new_col2'] = np.where(df['score']>=10.0, True, False)

Применение произвольной функции ко всей колонке

def get_score(s):
    return s * 0.21

df['score'] = df.some_col.apply(get_score)

Переименование колонки, сортировка

# переименовываем колонку A на колонку C
df = df.rename(columns={'A': 'C'})
# сортировка по одной колонке
df = df.sort_values('price', axis=0, ascending=False)
# сортировка сразу по нескольким колонкам
df = df.sort_values(['price', 'score'], ascending=[1, 0])

пример на соединение или конкатенацию дата-фреймов

df = pd.concat([df1, df2], ignore_index=True, axis=0)

группировка в дата-фрейме без мультииндекса

df.groupby(['A'], as_index=False).agg({'B': lambda series: series.iloc[0]})

После всех манипуляций, вас скорее всего надо будет данные куда-то выгрузить в другом формате или сохранить до следующего раза новый фрагмент таблицы дата-фрейма:

# в numpy массив
df.values
# в numpy массив, но сразу всю матрицу
df.as_matrix
# сохранить в файл
df.to_csv('submission.csv', index=False)

Примеры использования Random Forest из scikit-learn для классификации

Один из классических алгоритмов классификации является, алгоритм использования ансамбля решающих деревьев Random Forest (далее просто RF). Его выбирают по следующим причинам:

  • Random Forest хорош для не нормализованных данных, многие алгоритмы машинного обучения (ML) дают плохие результаты и данные предварительно надо обрабатывать. Для RF этот шаг можно попробовать опустить и быстро получить работающей прототип
  • Быстрота обучения классификатора, поэтому для обучения можно использовать большое количество данных не беспокоясь в времени (в отличии от SVM). Распараллеливание алгоритма.
  • Можно получить важность / веса параметров из пространства признаков а также вероятность предсказания

Из некоторых минусув можно выделить то, что обучившись на одних и тех-же данных несколько раз — подход будет предсказывать немного разные значения с разными вероятностями. Т.е. детерминированности вы не получите. От этого не уйдешь, т.к. выборка ансамбля решающих деревьев происходит случайным образом. Для заморозки случайности используйте random_seed.

Первый пример c RF: обучаем модель и предсказываем один элемент

from sklearn.ensemble import RandomForestClassifier

x_train = [
    [1, 2],
    [3, 4],
    [-1, 2],
    [-3, 4]
]
y_train = [1, 1, 0, 0]
clf_rf = RandomForestClassifier()
clf_rf.fit(x_train, y_train)

print(clf_rf.predict([[2, 2]]))  # [1] это предсказанный класс
print(clf_rf.predict_proba([[2, 2]]))  # [[0.2 0.8]] вероятности по классам

Пример второй: кросс-валидация или разбиение оценка точности с помощью разбиения на выборки для теста и для тренировки модели RF

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import train_test_split


x_train = [
    [1, 2], [5, 6],
    [3, 4], [7, 8],
    [-1, 2], [-5, 6],
    [-3, 4], [-7, 8], [0, 0]
]
y_train = [1, 1, 1, 1, 0, 0, 0, 0, 1]
clf_rf = RandomForestClassifier()

# разбиваем на два подмножества / фолда, параметр cv и получаем точность для каждого
scores = cross_val_score(clf_rf, x_train, y_train, cv=2)
print(scores)  # [0.8  0.75]

# кстати рабить на обучающую выборку и тестовую можно функцией
X_train, X_test, Y_train, Y_test = train_test_split(x_train, y_train, test_size=0.2)
print(X_test, Y_test)  # [[5, 6], [-3, 4]] [1, 0]

Возможно вы уже задались вопросом, какие параметры подкрутить, чтобы как-то влиять на точность и адаптировать алгоритм для входных данных и для железа.
n_estimators — параметр, напрямую влияющий на качество, при увеличении пространства признаков, следует рассмотреть увеличение этого параметра
max_depth — поможет если модель получилась сильно переобученной
criterion — entropy или gini . Можно с ними поиграться)
n_jobs — когда можно использовать несколько ядер
Пример третий: использование параметров для настройки RF
Здесь показано как с помощью GridSearchCV найти оптимальные параметры для классификатора.

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV


x_train = [
    [1, 2], [5, 6],
    [3, 4], [7, 8],
    [-1, 2], [-5, 6],
    [-3, 4], [-7, 8], [0, 0]
]
y_train = [1, 1, 1, 1, 0, 0, 0, 0, 1]

parameter_grid = {
            'criterion': ['entropy', 'gini'],
            'max_depth': [10, 20, 100],
            'n_estimators': [10, 20, 100]
        }
clf = RandomForestClassifier()
grid_searcher = GridSearchCV(clf, parameter_grid, verbose=2)
grid_searcher.fit(x_train, y_train)
clf_best = grid_searcher.best_estimator_

print('Best params = ', clf_best.get_params())

Пример четвертый — сохранение и распаковка обученной модели:

from sklearn.externals import joblib
# предполагаем что clf - обучен выше
joblib.dump(clf, path_to_pkl, compress=1)
clf = joblib.load(self.path_to_pkl)

Здесь параметр compress — влияет на то на сколько сильно будет сжат файл классификатора, чем больше тем сильнее, однако не советую увлекаться, т.к. это обратнопропорционально вляет на время распаковки.

Пример пятый — рисуем график важности параметров. Вполне может пригодиться для презентации результатов.

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
import matplotlib.pyplot as plt
import numpy as np



x_train = [
    [1, 2], [5, 6],
    [3, 4], [7, 8],
    [-1, 2], [-5, 6],
    [-3, 4], [-7, 8], [0, 0]
]
y_train = [1, 1, 1, 1, 0, 0, 0, 0, 1]

parameter_grid = {
            'criterion': ['entropy', 'gini'],
            'max_depth': [10, 20, 100],
            'n_estimators': [10, 20, 100]
        }
clf_rf = RandomForestClassifier()
clf_rf.fit(x_train, y_train)

importances = clf_rf.feature_importances_
print(importances)
std = np.std([tree.feature_importances_ for tree in clf_rf.estimators_], axis=0)

indices = np.argsort(importances)[::-1]
names_indices = ['x_coor', 'y_coor']

# Plot the feature importances of the forest
plt.figure()
plt.title("Feature importances")

plt.bar(range(len(importances)), importances[indices], color="r")
plt.xticks(range(len(importances)), names_indices, rotation=90)

plt.tight_layout()
plt.xlim([-1, len(importances)])
plt.show()

Как видно из нарисованного графика, первая координа является более ключевой, что действительно так по выборке. важность параметров в random forest