Два списка, необходимо сопоставить названия (Python)

307 просмотра
0
0 Комментариев

Есть примерно 50000 строк, 2 столбца, в первом — наименования товаров, во втором столбце коды товаров (все коды уникальные).
Есть тестовый набор — 2000 товаров, без кодов, естественно. Надо каждому товару из тестового набора найти свой товар из тренировочного.
1. У меня есть идея множественной классификации — для начала добавить группы товаров (их примерно 50 штук), всякие промтовары, соки, и т.д.
И вот я эти 2000 из тестового набора разобью на группы… Но что дальше делать не пойму — как найти соответствие. Подскажите, у кого есть какие мысли по этому поводу?

Code    Name
1     Диск Смарт Трек CD-R 80min 52x SL-50 (Эталон-М)
2     Луковицы цветов Бегония Пендула Пинк (СИ)
3     BURTI Деликат Color гель д/ст цв/тонк.белья 1,5л(Бурнус):6

тестовая выборка

Луковица цвета Пендула

надо определить, что это код 2


Добавить комментарий

1 Ответы

Python Опубликовано 12.12.2018
0

Вот пример построения простой модели линейной классификации.

Перед построением модели попытаемся нормализовать текст (насколько это возможно).

Пример входного pandas.DataFrame:

In [114]: df
Out[114]:
   Code                                               Name
0     1    Диск Смарт Трек CD-R 80min 52x SL-50 (Эталон-М)
1     2          Луковицы цветов Бегония Пендула Пинк (СИ)
2     3  BURTI Деликат Color гель д/ст цв/тонк.белья 1,...

после нормализации получим приблизительно следующее:

In [115]: data = [' '.join([en.stem(ru.stem(w)) for w in tok.tokenize(line)])
     ...:         for line in df['Name'].values.tolist()]
     ...:
 
In [116]: data
Out[116]:
['диск смарт трек cd-r 80min 52x sl-50 эталон-м',
 'луковиц цвет бегон пендул пинк си',
 'burti деликат color гел д/ст цв/тонк бел 5л бурнус']

увеличим DataFrame в 5 раз, чтобы избежать

ValueError: n_splits=3 cannot be greater than the number of members in
each class.`

ошибки во время обучения модели.


Вывод программы (листинг внизу):

Input Data Set:
    Code                                               Name
0      1    Диск Смарт Трек CD-R 80min 52x SL-50 (Эталон-М)
1      2          Луковицы цветов Бегония Пендула Пинк (СИ)
2      3  BURTI Деликат Color гель д/ст цв/тонк.белья 1,...
3      1    Диск Смарт Трек CD-R 80min 52x SL-50 (Эталон-М)
4      2          Луковицы цветов Бегония Пендула Пинк (СИ)
5      3  BURTI Деликат Color гель д/ст цв/тонк.белья 1,...
6      1    Диск Смарт Трек CD-R 80min 52x SL-50 (Эталон-М)
7      2          Луковицы цветов Бегония Пендула Пинк (СИ)
8      3  BURTI Деликат Color гель д/ст цв/тонк.белья 1,...
9      1    Диск Смарт Трек CD-R 80min 52x SL-50 (Эталон-М)
10     2          Луковицы цветов Бегония Пендула Пинк (СИ)
11     3  BURTI Деликат Color гель д/ст цв/тонк.белья 1,...
12     1    Диск Смарт Трек CD-R 80min 52x SL-50 (Эталон-М)
13     2          Луковицы цветов Бегония Пендула Пинк (СИ)
14     3  BURTI Деликат Color гель д/ст цв/тонк.белья 1,...
 
Fitting 3 folds for each of 640 candidates, totalling 1920 fits
[Parallel(n_jobs=-1)]: Done  34 tasks      | elapsed:    4.0s
[Parallel(n_jobs=-1)]: Done 635 tasks      | elapsed:    6.5s
[Parallel(n_jobs=-1)]: Done 1920 out of 1920 | elapsed:    9.2s finished
done in 9.859s
 
best parameters:
    clf__alpha: 1e-07
    clf__max_iter: 10
    clf__penalty: 'l2'
    tfidf__max_features: None
    tfidf__ngram_range: (1, 1)
 
 
test data set after prediction:
                           Name  Code
0        Луковица цвета Пендула     2
1  порошок стиральный для белья     3
2                 Какой-то диск     1

Работая с реальным набором данных, вам, скорее всего, вам придется дополнительно:

  • обрабатывать текст
  • выбрать наиболее важные/весомые features (слова)
  • попробовать другие классификаторы (например: sklearn.naive_bayesюMultinomialNB)

Весь код целиком:

from functools import reduce
from time import time
import logging
import numpy as np
import pandas as pd
from nltk.tokenize import word_tokenize, RegexpTokenizer
from nltk.stem.snowball import RussianStemmer
from nltk.stem.porter import PorterStemmer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import SGDClassifier
#from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import Pipeline
 
 
def read_input_data_set(filename):
    # read CSV into a DF
    df = pd.read_csv('d:/temp/text.csv')
    # make DF bigger: 3 rows -> 15 rows
    return pd.concat([df]*5, ignore_index=True)
 
# tokenize and stem text
def normailize_text(
        data,
        tok=RegexpTokenizer(r'\w[\w\/\-]+'),
        stemmers=[RussianStemmer(ignore_stopwords=True), PorterStemmer()]
):
    # tokenize text into words
    # sequentially apply all stemmers to tokenized words
    # join stemmed words back to sentences
    return [' '.join([reduce(lambda v,f: f.stem(v), stemmers, w) for w in tok.tokenize(line)])
            for line in data]
 
 
 
if __name__ == "__main__":
 
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s %(levelname)s %(message)s')
 
    # read CSV into a DF
    df = read_input_data_set('d:/temp/text.csv')
    print('Input Data Set:')
    print(df)
    print()
 
    # word tokenizer
    tok = RegexpTokenizer(r'\w[\w\/\-]+')
    en = PorterStemmer()
    ru = RussianStemmer(ignore_stopwords=True)
 
    data = normailize_text(df['Name'].values.tolist(), tok=tok, stemmers=[ru,en])
 
    pipeline = Pipeline([
        ('tfidf', TfidfVectorizer()),
        ('clf', SGDClassifier()),
    ])
 
    parameters = {
        #'tfidf__max_df': (0.5, 0.75, 1.0),
        'tfidf__max_features': (None, 10000, 50000, 100000),
        #'tfidf__stop_words': ['russian','english'],
        'tfidf__ngram_range': ((1, 1), (1, 2)),  # unigrams or bigrams
        'clf__alpha': np.logspace(-7, 2, 10),
        'clf__penalty': ('l2', 'elasticnet'),
        'clf__max_iter': (10, 50, 100, 1000),
    }
 
    grid_search = GridSearchCV(pipeline, parameters, n_jobs=-1, cv=3, verbose=1)
 
    # train model
    t0 = time()
    grid_search.fit(data, df['Code'])
    print("done in %0.3fs" % (time() - t0))
    print()
 
    print('best parameters:')
    best_parameters = grid_search.best_estimator_.get_params()
    for param_name in sorted(parameters.keys()):
        print("\t%s: %r" % (param_name, best_parameters[param_name]))
    print()
 
    best_parameters = grid_search.best_estimator_.get_params()
 
    test = pd.DataFrame({'Name':['Луковица цвета Пендула', 'порошок стиральный для белья', 'Какой-то диск']})
    print()
 
    # predict codes
    test['Code'] = grid_search.predict(normailize_text(test['Name'].values.tolist()))
 
    # print results
    print('test data set after prediction:')
    print(test)

Добавить комментарий
Напишите свой ответ на данный вопрос.
Scroll Up