Ручная реализация и преобразователь tfidf Scikit learn показывают разные результаты? - PullRequest
0 голосов
/ 30 мая 2020

Я пытался реализовать преобразователь tfidf с нуля, аналогичный тому, который реализован в sklearn. Мои векторы IDf такие же, как и в версии sklearn, но когда я умножаю TF и ​​IDF и нормализую их с помощью нормализации L2, я получаю другой результат, чем у sklearn. словарь с ключами в виде слов и значений в качестве индексов

def fit(dataset):

    unique_words = set() # at first we will initialize an empty set

    if isinstance(dataset, list): # check if its list type or not
        lower_dataset = [doc.lower() for doc in dataset]
        for doc in lower_dataset: # for each review in the dataset
            for word in doc.split(" "): # for each word in the review. #split method converts a string into list of words
                if len(word) < 2:
                    continue
                unique_words.add(word)
        unique_words = sorted(list(unique_words))
        vocab = {j:i for i,j in enumerate(unique_words)}
        return vocab
    else:
        return "You need to pass list of sentances"

Это моя функция для преобразования его в векторы Tf-idf

def transform(dataset, vocab, show_tf=False, show_idf=False, show_count=False):    

    def compute_tf(dataset, vocab, show_tf=show_tf):
        '''Computes Term Frequency''' 
        count = np.array([doc.count(word) \
                      for doc in dataset \
                      for word in vocab])\
                      .reshape(len(dataset),len(vocab))

        if show_count:
            print('\nCount Vectors\n')
            print(75*'=')
            print(count)
            print(75*'=')        

        tf = np.array([count[i][j]/count.sum(axis=1)[i] \
                   for i in range(len(dataset)) \
                   for j in range(len(vocab))])\
                   .reshape(len(dataset),len(vocab))

        tf[np.isnan(tf)] = 0

        if show_tf:
            print('\nTF Matrix\n')
            print(75*'=')
            print(tf)
            print(75*'=')

        return to


    def compute_idf(dataset, vocab, show_idf=show_idf):
        '''Computes Inverse Document Frequency '''
        presence = np.array([1 if word in doc else 0 \
                         for doc in dataset \
                         for word in vocab])\
                         .reshape(len(dataset),len(vocab))

        idf = np.array([1 + np.log((len(dataset) + 1)/ (presence.sum(axis=0)[j] + 1))\
                     for j in range(len(vocab)) ])\
                    .reshape(1,len(vocab))

        if show_idf:
            print('\nIDF Matrix\n')
            print(75*'=')
            print(idf)
            print(75*'=')

        return idf


    if isinstance(dataset, list):

        dataset = [doc.lower() for doc in dataset]
        tf = compute_tf(dataset, vocab)
        idf = compute_idf(dataset, vocab)


        tf_idf = np.array([(tf[i][j]*idf[0][j]) \
                        for i in range(len(dataset)) \
                        for j in range(len(vocab))])\
                       .reshape(len(dataset), len(vocab))

        tf_idf = normalize(tf_idf, norm='l2')

        rows = [i for i in range(len(dataset)) \
            for j in range(len(vocab)) if tf_idf[i][j] != 0]

        columns = [j for i in range(len(dataset))\
               for j in range(len(vocab)) if tf_idf[i][j] != 0]
        values = [tf_idf[i][j] for i in range(len(dataset)) \
              for j in range(len(vocab)) if tf_idf[i][j] != 0]

        print('\nNormalized TF-IDF Matrix\n')
        return (csr_matrix((values, (rows, columns)),\
                       shape=(len(dataset), len(vocab))))

    else:
        return 'You need to pass a list of sentences'

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

Это результат, который я получаю для этих данных

    corpus = [
              'This is the first document',
              'This document is the second document',
              'And this is the third one',
              'Is this the first document',]

    vocab = fit(corpus)
    print(transform(corpus, vocab, show_count=True, show_tf=True, show_idf=True))

Мой вывод против Вывод Sklearn

...