Соответствие названий компаний в Python через Cosine Similarity, TF-IDF и pyspark - PullRequest
0 голосов
/ 03 января 2019

Я пытаюсь сопоставить названия компаний из 2 списков вместе, чтобы проверить, действительно ли компания из списка А внесена в список Б. Поскольку названия компаний записаны во всех различных формах, я склонился к совпадениюиспользуя сходство в кодировке.Для этого я следил за заметкой в ​​этом блоге, сделанной Раном Тавори: Ссылка здесь

Вот общий план:

  1. Рассчитать TF-IDF матрицы на драйвере.
  2. Распараллелить матрицу A;Матрица широковещания B
  3. Теперь каждый работник отображает часть своей работы, умножая ее часть матрицы A на всю матрицу B. Поэтому, если работник работает с A [0:99], он умножит эти сто строк ивернуть результат, скажем, A [13] соответствует имени, найденному в B [21].Умножение выполняется с использованием numpy.
  4. Драйвер соберет все результаты от разных рабочих и сопоставит индексы (A [13] и B [21]) с фактическими именами в исходном наборе данных - и мыготово!

Мне удалось запустить точный код, описанный в примечании, но одна его часть кажется странной: b_mat_dist = broadcast_matrix(a_mat)

При трансляцииa_mat, а также распараллеливание a_mat, я получаю логический результат идеального соответствия для всех названий компаний (как мы ищем в одном источнике).

Когда я пытаюсь передать b_mat: b_mat_dist = broadcast_matrix (b_mat), Я получаю следующую ошибку: Incompatible dimension for X and Y matrices: X.shape[1] == 56710 while Y.shape[1] == 2418

Любая помощь будет принята с благодарностью!Заранее спасибо!

Вот мой код:

import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from pyspark.sql import SQLContext, SparkSession
from pyspark import SparkContext
from scipy.sparse import csr_matrix
vectorizer = TfidfVectorizer()

if 'sc' in locals():
    sc.stop()

sc = SparkContext("local", "Simple App")

pd.set_option('display.max_colwidth', -1)
RefB =  pd.read_excel('Ref.xlsx')
ToMatchB =  pd.read_excel('ToMatch.xlsx')

Ref = RefB['CLT_company_name']
ToMatch = ToMatchB ['Name1']

a_mat = vectorizer.fit_transform(Ref)
b_mat = vectorizer.fit_transform(ToMatch)

def find_matches_in_submatrix(sources, targets, inputs_start_index,
                              threshold=.8):
    cosimilarities = cosine_similarity(sources, targets)
    for i, cosimilarity in enumerate(cosimilarities):
        cosimilarity = cosimilarity.flatten()
        # Find the best match by using argsort()[-1]
        target_index = cosimilarity.argsort()[-1]
        source_index = inputs_start_index + i
        similarity = cosimilarity[target_index]
        if cosimilarity[target_index] >= threshold:
            yield (source_index, target_index, similarity)

def broadcast_matrix(mat):
    bcast = sc.broadcast((mat.data, mat.indices, mat.indptr))
    (data, indices, indptr) = bcast.value
    bcast_mat = csr_matrix((data, indices, indptr), shape=mat.shape)
    return bcast_mat

def parallelize_matrix(scipy_mat, rows_per_chunk=100):
    [rows, cols] = scipy_mat.shape
    i = 0
    submatrices = []
    while i < rows:
        current_chunk_size = min(rows_per_chunk, rows - i)
        submat = scipy_mat[i:i + current_chunk_size]
        submatrices.append((i, (submat.data, submat.indices, 
                                submat.indptr),
                            (current_chunk_size, cols)))
        i += current_chunk_size
    return sc.parallelize(submatrices)

a_mat_para = parallelize_matrix(a_mat, rows_per_chunk=100)
b_mat_dist = broadcast_matrix(b_mat)
results = a_mat_para.flatMap(
        lambda submatrix:
        find_matches_in_submatrix(csr_matrix(submatrix[1],
                                             shape=submatrix[2]),
                                   b_mat_dist,
                                   submatrix[0]))

1 Ответ

0 голосов
/ 04 марта 2019

Попробуйте выровнять словарь для обоих объектов TfidVectorizer:

vect = CountVectorizer()
vocabulary =  vect.fit(Ref + ToMatch).vocabulary_
vectorizer = TfidfVectorizer(vocabulary=vocabulary)

Также в зависимости от того, что вы хотите сделать:

a_mat = vectorizer.fit_transform(ToMatch)
b_mat = vectorizer.fit_transform(Ref)

выглядело как лучший вариант для меня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...