Возвратите None в функции: TypeError: объект типа 'NoneType' не имеет len () - PullRequest
0 голосов
/ 31 августа 2018

Я пытаюсь напечатать свои темы и тексты из каждой темы в LDA. Но никто после печати тем не нарушает мой сценарий. Я могу печатать свои темы, но не тексты.

import pandas
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.decomposition import LatentDirichletAllocation

n_top_words = 5
n_components = 5

def print_top_words(model, feature_names, n_top_words):
    for topic_idx, topic in enumerate(model.components_):
        message = "Topic #%d: " % topic_idx
        message += " ".join([feature_names[i] for i in topic.argsort()[:-n_top_words - 1:-1]])

        return message

text = pandas.read_csv('text.csv', encoding = 'utf-8')
text_list = text.values.tolist()

tf_vectorizer = CountVectorizer()
tf = tf_vectorizer.fit_transform(text_list)

lda = LatentDirichletAllocation(n_components=n_components, learning_method='batch', max_iter=25, random_state=0)

doc_distr = lda.fit_transform(tf)

tf_feature_names = tf_vectorizer.get_feature_names()
print (print_top_words(lda, tf_feature_names, n_top_words))

doc_distr = lda.fit_transform(tf)
topics = print_top_words(lda, tf_feature_names, n_top_words)
for i in range(len(topics)):
    print ("Topic {}:".format(i))
    docs = np.argsort(doc_distr[:, i])[::-1]
    for j in docs[:10]:
       print (" ".join(text_list[j].split(",")[:2]))

Мой вывод:

Topic 0: no order mail received back 

Topic 1: cancel order wishes possible wish 

Topic 2: keep current informed delivery order 

Topic 3: faulty wooden box present side 

Topic 4: delivered received be produced urgent 

Topic 5: good waiting day response share 

После этой ошибки:

  File "lda.py", line 41, in <module>

    for i in range(len(topics)):

TypeError: object of type 'NoneType' has no len()

Ответы [ 3 ]

0 голосов
/ 31 августа 2018

Сложно ответить без знания внутренней работы LatentDirichletAllocation. Тем не менее, его компонент_ имеет к этому какое-то отношение, потому что его повторная итерация дает разные результаты.

Скорее всего, вы можете избежать этой ошибки, изменив:

print (print_top_words(lda, tf_feature_names, n_top_words))

doc_distr = lda.fit_transform(tf)
topics = print_top_words(lda, tf_feature_names, n_top_words)

до:

temp = print_top_words(lda, tf_feature_names, n_top_words)
print (temp)

doc_distr = lda.fit_transform(tf)
topics = print_top_words(temp)

При втором вызове функции model.components_ ничего не возвращает, поэтому цикл пропускается, а функция не возвращает ничего.

Однако я не уверен, является ли это истинным намерением кода. Похоже, вы хотите, чтобы print_top_words был генератором? Вы возвращаетесь в цикл for, который никогда не достигает второй итерации. Вероятно, это не то, для чего предназначен цикл.

0 голосов
/ 31 августа 2018

С вашей функцией print_top_words() (как минимум) четыре проблемы.

Первая проблема, которая вызывает вашу текущую проблему, заключается в том, что если model.components_ пусто, тело цикла for не будет выполняться, и ваша функция затем (неявно) вернет None.

Второе немного более тонкое: если model.components_ НЕ пусто, функция вернет только первое сообщение, затем вернет его и выйдет - что само определение оператора return: вернуть значение ( или None, если значение не указано) и выйдите из функции.

Третья проблема заключается в том, что (когда model.components_ не пусто), функция возвращает строку, где вызывающий код, очевидно, ожидает список. Это небольшая ошибка, поскольку строки имеют длину, поэтому цикл for в range(len(topics)) кажется работающим, но len(topics), безусловно, не то значение, которое вы ожидаете.

И, наконец, функция имеет очень плохое имя, поскольку она ничего не «печатает» - это может показаться тривиальным по сравнению с первыми тремя проблемами, и это не помешает работе кода (если предположить, что первые три проблемы исправлено), но рассуждение о коде само по себе достаточно сложно, поэтому правильное именование важно , поскольку оно значительно снижает когнитивную нагрузку и облегчает обслуживание / отладку.

Короче говоря, подумайте о том, что вы действительно хотите, чтобы эта функция выполняла, и исправьте ее соответствующим образом. Я не буду публиковать здесь «исправленную» версию, поскольку не знаю наверняка, что вы пытаетесь сделать, но приведенные выше примечания должны помочь.

NB: также вы дважды вызываете doc_distr = lda.fit_transform(tf) и print_top_words(lda, tf_feature_names, n_top_words) с одинаковыми аргументами, что является либо абсолютно бесполезным, и пустой тратой циклов процессора (в лучшем случае), или запахом еще одной ошибки если вы получите другие результаты от второго звонка.

0 голосов
/ 31 августа 2018

Вы не предоставляете полный код, но наиболее вероятная причина в том, что переменная topics равна None. Это может произойти только в том случае, если model.components_ в вашей функции print_top_words является пустой коллекцией, поэтому цикл никогда не запускается, и функция (неявно) возвращает None. Проверьте стоимость коллекции. Еще лучше, выберите значение, которое будет возвращено в этом случае.

Другой, не связанный, пункт: вы инициализируете переменную message на каждой итерации и возвращаете ее на каждой итерации. Проверь, что ты собираешься делать.

...