In [1]:
import numpy as np
import pandas as pd
%pylab inline


Populating the interactive namespace from numpy and matplotlib

Загрузка данных


In [2]:
train_data = pd.read_csv('./data/evo_train.csv', sep=',', header=0)
test_data = pd.read_csv('./data/evo_test.csv', sep=',', header=0)

In [3]:
print train_data.shape
print test_data.shape


(55860, 3)
(37240, 2)

In [4]:
train_data.head()


Out[4]:
NAME GROUP_ID id
0 Пиво "Жигулевское" 0,5 л. св. 35 0
1 СОУС ТОМАТНЫЙ БУЗДЯК 670Г ТАТАРСКИЙ /8 6 1
2 Сигареты Esse SS Exchange 7 2
3 Петрушка 6 3
4 пиво ягерь 35 4

Выходная переменная


In [5]:
train_data.GROUP_ID.value_counts()


Out[5]:
7     6045
6     6014
24    5975
14    5972
34    5963
35    5957
30    3050
26    2999
25    2961
29     639
28     633
9      626
37     618
17     616
18     613
16     612
20     608
59     607
27     606
19     604
22     603
21     587
52     586
60     584
36     572
12     568
38     394
15     235
32      13
Name: GROUP_ID, dtype: int64

Посмотрим самые частые и самые редкие категории.


In [6]:
train_data[train_data.GROUP_ID == 6]['NAME'].head(10)


Out[6]:
1                СОУС ТОМАТНЫЙ БУЗДЯК 670Г ТАТАРСКИЙ /8
3                                              Петрушка
5     Детский мармелад "Trolls" Черничка Лакомства д...
33    КОЛБАСА В/К ОХЛ САЛЯМИ ФОРТУНА (ИНД) ИШИМСКИЙ ...
34                                         Кексы шокол.
36                 ШОК.БАТОНЧИК СНИКЕРС лесной орех 81г
37                                     Салат   "Цезарь"
39     Олимп Вэй Протеин Комплекс 2.27 кг. крем печенье
61    КИСЛИЦА ЖЕВ. РЕЗИНКА С ФРУКТОВОЙ НАЧ. (СРОК 12...
66    ТЕМНЫЙ ШОКОЛАД С ЦЕЛЬНЫМИ ЛЕСНЫМИ ОРЕХАМИ 100Г...
Name: NAME, dtype: object
  • 7 = сигареты
  • 6 = продукты питания
  • 32 = позиция по свободной цене

Предобработка данных

!!По-хорошему:

  1. К нижнему регистру
  2. Вычистить стоп-слова и знаки препинания
  3. Лемматизация
  4. CountVectorizer, TFIDF, Word2Vec

In [7]:
# удаление спецсимволов
import re

def remove_special_character(somestring):
    pattern = re.compile(u'[^a-zA-Zа-яА-Я0-9_]+')
    tokens = pattern.sub(' ', somestring).strip()
    return tokens

train_data['NAME'] = train_data['NAME'].str.decode('utf-8')
train_data['NAME'] = train_data['NAME'].apply(remove_special_character)

test_data['NAME'] = test_data['NAME'].str.decode('utf-8')
test_data['NAME'] = test_data['NAME'].apply(remove_special_character)

In [8]:
# лемматизация
from pymystem3 import Mystem

m = Mystem()
def lemmatize(text):
    lemmas = m.lemmatize(text)
    return (''.join(lemmas)).strip()

train_data['NAME'] = train_data['NAME'].apply(lemmatize)
test_data['NAME'] = test_data['NAME'].apply(lemmatize)

In [9]:
train_data['NAME'].head(10)


Out[9]:
0                            пиво жигулевский 0 5 л св
1                соус томатный буздяк 670Г татарский 8
2                            сигарета Esse SS Exchange
3                                             петрушка
4                                           пиво ягерь
5    детский мармелад Trolls черничка лакомство для...
6       ооо продукт 24часа ведение бух учет за февраль
7                        кисточка для тень и хайлайтер
8                    свеча фонтан тортовый 12 5см 1 шт
9                            сумка sti 06CH 634_ black
Name: NAME, dtype: object

Эксперимент с CountVectorizer и RF


In [10]:
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier

In [14]:
max_features = range(100, 1000, 100)

for mf in max_features:
    cv = CountVectorizer(max_features=mf)
    cv_train_data = cv.fit_transform(train_data['NAME'])
    rf = RandomForestClassifier(n_estimators=200, random_state=11)
    scores = cross_val_score(rf, cv_train_data, train_data['GROUP_ID'], cv=2, scoring='accuracy')
    
    print 'Max features: ', mf
    print 'Score: ', scores.mean()


Max features:  100
Score:  0.580737684393
Max features:  200
Score:  0.648299136115
Max features:  300
Score:  0.692051717589
Max features:  400
Score:  0.727013852112
Max features:  500
Score:  0.74677710861
Max features:  600
Score:  0.766003774761
Max features:  700
Score:  0.779412534701
Max features:  800
Score:  0.790099972727
Max features:  900
Score:  0.793913072669

In [11]:
# пробное решение
cv = CountVectorizer(max_features=1200)
cv_train_data = cv.fit_transform(train_data['NAME'])
cv_test_data = cv.transform(test_data['NAME'])

rf = RandomForestClassifier(n_estimators=400, random_state=11)
rf.fit(cv_train_data, train_data['GROUP_ID'])


Out[11]:
RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
            max_depth=None, max_features='auto', max_leaf_nodes=None,
            min_impurity_split=1e-07, min_samples_leaf=1,
            min_samples_split=2, min_weight_fraction_leaf=0.0,
            n_estimators=400, n_jobs=1, oob_score=False, random_state=11,
            verbose=0, warm_start=False)

In [13]:
predict_rf = rf.predict(cv_test_data)
test_data['GROUP_ID'] = predict_rf

In [14]:
test_data.head()


Out[14]:
NAME id GROUP_ID
0 пиво рижский светлый 0 5л 0 35
1 плавленый сыр король сыр 80г 1 6
2 заказ имл 7500342101814 2 9
3 мерриес трусики М58 3 26
4 лупа канц маленький 4 7

In [19]:
test_data[['id', 'GROUP_ID']].to_csv('res_3105.csv', sep=',', header=True, index=False)

NaiveBayes


In [16]:
from sklearn.naive_bayes import MultinomialNB

In [17]:
mnb = MultinomialNB()
scores = cross_val_score(mnb, cv_train_data, train_data['GROUP_ID'], cv=3, scoring='accuracy')

In [18]:
print scores


[ 0.8041868   0.80769024  0.80810361]

In [ ]: