Кластеризация ключевых фраз для контекстной рекламы LSA алгоритмом

Простой и крайне эффективный метод кластеризации фраз на смысловые группы:

  1. Получаем частотную матрицу для нормальной формы фраз, встречающихся в выборке 2 или более раз
  2. Матрицу можно заменить на бинарную (есть слово во фразе или нет) или на TF-IDF интерпретацию (должна возрасти точность)
  3. Полученную матрицу преобразуем с помощью сингулярного разложения SVD
  4. Результирующую матрицу W (третья матрица полученная после разложения) отражает вложение фразу в группы
  5. Выбираем число k — количество (примерное) групп в тексте
  6. Разбираем матрицу W на векторы T1..n (по числу документов) длинной k
  7. Вычисляем косинусоидальные расстояние между векторами
  8. Сравниваем с порогом 0.1 и получаем группы фраз

# -*- coding: utf-8 -*-

import pymorphy2
import numpy
from collections import Counter
import random

morph = pymorphy2.MorphAnalyzer()

def cosine_distance(a, b):
    if len(a) != len(b):
    	raise ValueError, "a and b must be same length" #Steve
    numerator = 0
    denoma = 0
    denomb = 0
    for i in range(len(a)):  
    	ai = a[i]            
    	bi = b[i]
    	numerator += ai*bi   
    	denoma += ai*ai      
    	denomb += bi*bi
    result = 1 - numerator / (numpy.sqrt(denoma)*numpy.sqrt(denomb))
    return result

word_list = [u'машина после мойки зимой',
             u'новое красивое платье купить в Москве',
             u'что делать после мойки машины зимой',
             u'мойка машины зимой на улице',
             u'не открывается машина после мойки зимой',
             u'как убрать жир с живота и боков',
             u'как быстро убрать живот бока домашних',
             u'поможет убрать живот бока',
             u'крутить обруч убрать живот бока',
             u'способы убрать живот и бока',
             u'подрезать яблоню весной',
             u'можно ли подрезать яблони зимой',
             u'правильно подрезать яблоню',
             u'подрезать яблоню весной видео',
             u'поменять задние тормозные колодки',
             u'поменять тормозные колодки на тойоте',
             u'поменять тормозные колодки на опель',
             u'самому поменять тормозные колодки',
             u'поменять тормозные колодки приора',
             u'купить детское нарядное платье',
             u'нарядные платья купить магазин',
             u'купить нарядное платье интернете',
             u'купить нарядное платье в интернет магазине',
             u'купить нарядное платье для женщины',
             u'купить нарядное платье недорого',
             u'синтетическое моторное масло роснефть отзывы',
             u'синтетическое моторное масло лукойл 5w40 отзывы',
             u'profix масло моторное синтетическое отзывы',
             u'синтетическое моторное масло 5w40 рольф отзывы',
             u'синтетическое моторное масло тнк 5w40 отзывы']

random.shuffle(word_list)

result_array = {}
result_array_f = {}
i = 0;
for l in word_list:
    result_array['T'+str(i)] = l
    result_array_f['T'+str(i)] = 0
    i = i + 1    

w_norm = []
all_w_norm = [];

i = 0;
for l in word_list:
    words = l.split(' ')
    w_norm.append([])
    w_str = '';
    for w in words:
        w_one_norm = morph.parse(w)[0].normal_form
        w_norm[i].append( w_one_norm )
        all_w_norm.append( w_one_norm )
        w_str = w_str + ' ' + w_one_norm;
    result_array['T'+str(i)] = w_str
    i = i + 1

f_word = Counter(all_w_norm)
f_word_m = {};

for key, l in f_word.iteritems():
    if (l >= 2 and len(key) > 1):
        f_word_m[key] = l;

i = 0;
f_matrix = []
for l in f_word_m:
    f_matrix.append([]);
    for l1 in w_norm:
        l1_f = Counter(l1);
        if (l1_f.has_key(l)):
            f_matrix[i].append(l1_f[l]);
            print l1_f[l],;
        else:
            print '0',;
            f_matrix[i].append(0);
    print '';
    i = i + 1; 

a = numpy.array(f_matrix);

a,b,c = numpy.linalg.svd(a);

v_result = [];
for i in range(0, len(c[0])):
    v_result.append([]);

#число тематик
k = 5;

i = 0;
for l in range(0, k):
    for j in range(0, len(c[l])):
        v_result[j].append(c[l][i]);
        i = i + 1;
    i = 0;     

i = 0; i1 = 0;
for v in v_result:
    if (result_array_f['T'+str(i)] == 0):
        result_array_f['T'+str(i)] = 1;
        print '-------'+result_array['T'+str(i)]+'-------'
        for v1 in v_result:
            if (i1 != i):
                c = cosine_distance(v, v1);
                if (c <= 0.1):
                    #print 'T'+str(i1)+' = '+"%0.5f" % c;
                    print result_array['T'+str(i1)];
                    result_array_f['T'+str(i1)] = 1;
            i1 = i1 + 1;
        i1 = 0;    
    i = i + 1;

Результат работы скрипта:

0 0 0 0 1 0 0 1 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0
0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 1 0 0 1 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0
0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0
1 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0
0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0
0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0

——- можно ли подрезать яблоня зимой——-
подрезать яблоня весной
подрезать яблоня весной видео
правильно подрезать яблоня
——- купить нарядный платье недорого——-
нарядный платье купить магазин
купить нарядный платье для женщина
новое красивый платье купить в москва
купить нарядный платье интернет
купить детский нарядный платье
купить нарядный платье в интернет магазин
——- синтетический моторный масло тнк 5w40 отзыв——-
profix масло моторный синтетический отзыв
синтетический моторный масло 5w40 рольф отзыв
синтетический моторный масло роснефть отзыв
синтетический моторный масло лукойл 5w40 отзыв
——- помочь убрать живот бок——-
как убрать жир с живот и боков
как быстро убрать живот бок домашний
крутить обруч убрать живот бок
способ убрать живот и бок
——- мойка машина зимой на улица——-
машина после мойка зимой
не открываться машина после мойка зимой
что делать после мойка машина зимой
——- поменять тормозной колодка приор——-
поменять тормозной колодка на тойота
поменять тормозной колодка на опель
поменять задний тормозной колодка
самый поменять тормозной колодка

Быстро, просто и эффективно 😉

Facebook Comments

Леонид Чернядьев

Увлекаюсь программированием, интернет маркетингом, прогнозированием, дизайном и версткой. Принимаю заказы на лидогенерацию. Связь через - https://www.facebook.com/lenid.chernyadyev