Объект 'Pipeline' не имеет атрибута 'get_feature_names' в scikit-learn

Я в основном группирую некоторые из моих документов, используя алгоритм mini_batch_kmeans и kmeans. Я просто следил за учебником - это веб-сайт scikit-learn, ссылка на который приведена ниже: http://scikit-learn.org/stable/auto_examples/text/document_clustering.html

Они используют некоторые методы векторизации, одним из которых является HashingVectorizer. В hashingVectorizer они создают конвейер с методом TfidfTransformer ().

# Perform an IDF normalization on the output of HashingVectorizer
hasher = HashingVectorizer(n_features=opts.n_features,
                               stop_words='english', non_negative=True,
                               norm=None, binary=False)
vectorizer = make_pipeline(hasher, TfidfTransformer())

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

terms = vectorizer.get_feature_names()
for i in range(true_k):
    print("Cluster %d:" % i, end='')
    for ind in order_centroids[i, :10]:
        print(' %s' % terms[ind], end='')
    print()

Как мне решить эту ошибку?

Весь мой код показан ниже:

X_train_vecs, vectorizer = vector_bow.count_tfidf_vectorizer(_contents)
mini_kmeans_batch = MiniBatchKmeansTechnique()
# MiniBatchKmeans without the LSA dimensionality reduction
mini_kmeans_batch.mini_kmeans_technique(number_cluster=8, X_train_vecs=X_train_vecs,
                                                vectorizer=vectorizer, filenames=_filenames, contents=_contents, is_dimension_reduced=False)

Векторизатор подсчета связан с tfidf.

def count_tfidf_vectorizer(self,contents):
    count_vect = CountVectorizer()
    vectorizer = make_pipeline(count_vect,TfidfTransformer())
    X_train_vecs = vectorizer.fit_transform(contents)
    print("The count of bow : ", X_train_vecs.shape)
    return X_train_vecs, vectorizer

а класс mini_batch_kmeans выглядит следующим образом:

class MiniBatchKmeansTechnique():
    def mini_kmeans_technique(self, number_cluster, X_train_vecs, vectorizer,
                              filenames, contents, svd=None, is_dimension_reduced=True):
        km = MiniBatchKMeans(n_clusters=number_cluster, init='k-means++', max_iter=100, n_init=10,
                         init_size=1000, batch_size=1000, verbose=True, random_state=42)
        print("Clustering sparse data with %s" % km)
        t0 = time()
        km.fit(X_train_vecs)
        print("done in %0.3fs" % (time() - t0))
        print()
        cluster_labels = km.labels_.tolist()
        print("List of the cluster names is : ",cluster_labels)
        data = {'filename':filenames, 'contents':contents, 'cluster_label':cluster_labels}
        frame = pd.DataFrame(data=data, index=[cluster_labels], columns=['filename', 'contents', 'cluster_label'])
        print(frame['cluster_label'].value_counts(sort=True,ascending=False))
        print()
        grouped = frame['cluster_label'].groupby(frame['cluster_label'])
        print(grouped.mean())
        print()
        print("Top Terms Per Cluster :")

        if is_dimension_reduced:
            if svd != None:
                original_space_centroids = svd.inverse_transform(km.cluster_centers_)
                order_centroids = original_space_centroids.argsort()[:, ::-1]
        else:
            order_centroids = km.cluster_centers_.argsort()[:, ::-1]

        terms = vectorizer.get_feature_names()
        for i in range(number_cluster):
            print("Cluster %d:" % i, end=' ')
            for ind in order_centroids[i, :10]:
                print(' %s' % terms[ind], end=',')
            print()
            print("Cluster %d filenames:" % i, end='')
            for file in frame.ix[i]['filename'].values.tolist():
                print(' %s,' % file, end='')
            print()

person Nitesh kumar    schedule 21.06.2017    source источник
comment
Вы смонтировали трубопровод? Пожалуйста, разместите полный код.   -  person Vivek Kumar    schedule 21.06.2017
comment
Я отправлю весь свой код, пожалуйста, проверьте   -  person Nitesh kumar    schedule 21.06.2017
comment
Во-первых, что вы используете? HashingVectorizer или CountVectorizer?   -  person Vivek Kumar    schedule 21.06.2017
comment
Во-вторых, нет необходимости создавать конвейер для CountVectorizer и TfidfTransformer. Вместо этого используйте TfidfVectorizer.   -  person Vivek Kumar    schedule 21.06.2017
comment
В-третьих, в учебнике они вызывают get_feature_names() только в конвейере без хеширования. См. if block чуть выше, где они используют get_feature_names().   -  person Vivek Kumar    schedule 21.06.2017


Ответы (2)


В конвейере нет метода get_feature_names (), поскольку реализовать этот метод для конвейера непросто - необходимо учитывать все этапы конвейера, чтобы получить имена функций. См. https://github.com/scikit-learn/scikit-learn/issues/6424, https://github.com/scikit-learn/scikit-learn/issues/6425 и т. д. - много связанных тикетов и несколько попыток исправить.

Если ваш конвейер простой (TfidfVectorizer, за которым следует MiniBatchKMeans), вы можете получить имена функций из TfidfVectorizer.

Если вы хотите использовать HashingVectorizer, это более сложно, поскольку HashingVectorizer не предоставляет имена функций по дизайну. HashingVectorizer не хранит словарный запас и вместо этого использует хеши - это означает, что его можно применять в онлайн-настройках и что для него не требуется ОЗУ, но компромисс заключается именно в том, что вы не получаете имена функций.

Тем не менее, все еще можно получить имена функций из HashingVectorizer; для этого вам нужно применить его к образцу документов, сохранить, какие хэши соответствуют каким словам, и таким образом узнать, что означают эти хэши, то есть каковы названия функций. Могут возникнуть коллизии, поэтому невозможно быть на 100% уверенным, что имя функции правильное, но обычно этот подход работает нормально. Этот подход реализован в библиотеке eli5; см. http://eli5.readthedocs.io/en/latest/tutorials/sklearn-text.html#debugging-hashingvectorizer в качестве примера. Вам нужно будет сделать что-то подобное, используя InvertableHashingVectorizer:

from eli5.sklearn import InvertableHashingVectorizer
ivec = InvertableHashingVectorizer(vec)  # vec is a HashingVectorizer instance
# X_sample is a sample from contents; you can use the 
# whole contents array, or just e.g. every 10th element
ivec.fit(content_sample)  
hashing_feat_names = ivec.get_feature_names()

Затем вы можете использовать hashing_feat_names в качестве имен ваших функций, поскольку TfidfTransformer не изменяет размер входного вектора, а просто масштабирует те же функции.

person Mikhail Korobov    schedule 21.06.2017

Из make_pipeline документации:

This is a shorthand for the Pipeline constructor; it does not require, and
    does not permit, naming the estimators. Instead, their names will be set
    to the lowercase of their types automatically.

Итак, чтобы получить доступ к названиям функций, после того, как вы настроили данные, вы можете:

# Perform an IDF normalization on the output of HashingVectorizer
from sklearn.feature_extraction.text import HashingVectorizer, TfidfVectorizer
from sklearn.pipeline import make_pipeline

hasher = HashingVectorizer(n_features=10,
                           stop_words='english', non_negative=True,
                            norm=None, binary=False)

tfidf = TfidfVectorizer()
vectorizer = make_pipeline(hasher, tfidf)
# ...    
# fit to the data
# ... 

# use the instance's class name to lower 
terms = vectorizer.named_steps[tfidf.__class__.__name__.lower()].get_feature_names()

# or to be more precise, as used in `_name_estimators`:
# terms = vectorizer.named_steps[type(tfidf).__name__.lower()].get_feature_names()
# btw TfidfTransformer and HashingVectorizer do not have get_feature_names afaik

Надеюсь это поможет. Удачи!

Изменить. После просмотра обновленного вопроса с примером, которому вы следуете, @Vivek Kumar верен, этот код terms = vectorizer.get_feature_names() не будет запускаться для конвейера, но только если:

vectorizer = TfidfVectorizer(max_df=0.5, max_features=opts.n_features,
                                 min_df=2, stop_words='english',
                                 use_idf=opts.use_idf)
person mkaran    schedule 21.06.2017
comment
Спасибо, это мне очень помогло. Обратите внимание, что не все трансформаторы имеют функцию get_feature_names. В моем случае PolynomialFeatures () имеет функцию get_feature_names, а StandardScaler () нет и выдает ошибку. - person Jane Kathambi; 28.06.2021
comment
@JaneKathambi Рад, что это помогло :) Спасибо за заметку, полезно знать, что StandardScaler тоже не имеет этой функции. У меня есть комментарий об отсутствующей функции get_feature_names для TfidfTransformer и TfidfTransformer (# btw TfidfTransformer and HashingVectorizer do not have get_feature_names afaik) - person mkaran; 30.06.2021