Python 使用scikit learn进行文档分类:获取对分类影响更大的单词(标记)的最有效方法

Python 使用scikit learn进行文档分类:获取对分类影响更大的单词(标记)的最有效方法,python,machine-learning,scikit-learn,logistic-regression,document-classification,Python,Machine Learning,Scikit Learn,Logistic Regression,Document Classification,我已经使用训练文档集的tf idf表示构建了一个文档二项分类器,并对其应用逻辑回归: lr_tfidf = Pipeline([('vect', tfidf),('clf', LogisticRegression(random_state=0))]) lr_tfidf.fit(X_train, y_train) 我以pickle格式保存了模型,并使用它对新文档进行分类,结果得到文档处于a类的概率和模型处于B类的概率 text_model = pickle.load(open('text_mo

我已经使用训练文档集的tf idf表示构建了一个文档二项分类器,并对其应用逻辑回归:

lr_tfidf = Pipeline([('vect', tfidf),('clf', LogisticRegression(random_state=0))])

lr_tfidf.fit(X_train, y_train)
我以pickle格式保存了模型,并使用它对新文档进行分类,结果得到文档处于a类的概率和模型处于B类的概率

text_model = pickle.load(open('text_model.pkl', 'rb'))
results = text_model.predict_proba(new_document)
哪种方法是获得在分类中影响更大的单词(或者,通常是标记)的最佳方法?我希望得到:

  • 包含在文档中的N个标记在逻辑回归模型中具有较高的系数作为特征
  • 文档中包含的N个标记,在逻辑回归模型中具有较低的系数作为特征

据我所知,我使用的是sklearn v 0.19,您只需要查看参数并根据系数值对其进行排序。
使用.get_params()函数,可以获得系数。您可以对其进行argsort并选择顶部N,bot N.

GitHub上有一个解决方案,可以打印从管道中的分类器获得的最重要的功能:

您想在脚本中使用
show\u most\u informational\u功能。我用过它,它很好用

以下是Github海报代码的复制粘贴:

def show_most_informative_features(model, text=None, n=20):

"""

Accepts a Pipeline with a classifer and a TfidfVectorizer and computes

the n most informative features of the model. If text is given, then will

compute the most informative features for classifying that text.



Note that this function will only work on linear models with coefs_

"""

# Extract the vectorizer and the classifier from the pipeline

vectorizer = model.named_steps['vectorizer']

classifier = model.named_steps['classifier']



# Check to make sure that we can perform this computation

if not hasattr(classifier, 'coef_'):

    raise TypeError(

        "Cannot compute most informative features on {} model.".format(

            classifier.__class__.__name__

        )

    )



if text is not None:

    # Compute the coefficients for the text

    tvec = model.transform([text]).toarray()

else:

    # Otherwise simply use the coefficients

    tvec = classifier.coef_



# Zip the feature names with the coefs and sort

coefs = sorted(

    zip(tvec[0], vectorizer.get_feature_names()),

    key=itemgetter(0), reverse=True

)



topn  = zip(coefs[:n], coefs[:-(n+1):-1])



# Create the output string to return

output = []



# If text, add the predicted value to the output.

if text is not None:

    output.append("\"{}\"".format(text))

    output.append("Classified as: {}".format(model.predict([text])))

    output.append("")



# Create two columns with most negative and most positive features.

for (cp, fnp), (cn, fnn) in topn:

    output.append(

        "{:0.4f}{: >15}    {:0.4f}{: >15}".format(cp, fnp, cn, fnn)

    )



return "\n".join(output)

下面是一个修改版的
show\u most\u information\u features
函数,可用于任何分类器:

def show_most_informative_features(model, vectorizer=None, text=None, n=20):
# Extract the vectorizer and the classifier from the pipeline
if vectorizer is None:
    vectorizer = model.named_steps['vectorizer']
else:
    vectorizer.fit_transform([text])

classifier = model.named_steps['classifier']
feat_names = vectorizer.get_feature_names()

# Check to make sure that we can perform this computation
if not hasattr(classifier, 'coef_'):
    raise TypeError(
        "Cannot compute most informative features on {}.".format(
            classifier.__class__.__name__
        )
    )    

# Otherwise simply use the coefficients
tvec = classifier.coef_

# Zip the feature names with the coefs and sort   
coefs = sorted(
    zip(tvec[0], feat_names),
    key=operator.itemgetter(0), reverse=True
)

# Get the top n and bottom n coef, name pairs
topn  = zip(coefs[:n], coefs[:-(n+1):-1])

# Create the output string to return
output = []

# If text, add the predicted value to the output.
if text is not None:
    output.append("\"{}\"".format(text))
    output.append(
        "Classified as: {}".format(model.predict([text]))
    )
    output.append("")

# Create two columns with most negative and most positive features.
for (cp, fnp), (cn, fnn) in topn:
    output.append(
        "{:0.4f}{: >15}    {:0.4f}{: >15}".format(
            cp, fnp, cn, fnn
        )
    )

return "\n".join(output)
然后您可以这样调用函数:

vectorizer = TfidfVectorizer()
show_most_informative_features(model,vectorizer, "your text")

您可以访问管道内的
tfidf
,并获取用作功能的单词。然后从
clf
中获取
coef\uu
,并将单词从映射到这些系数。谢谢@VivekKumar。如果我没有错的话,通过这种方式我得到了模型的特性/系数,相反,对于一个新文档,我想要得到的是对选择影响更大的特性(单词)(当然这取决于模型的特性/系数)。您能否提供有效的代码来获得此结果?重要与否的功能将在培训期间确定。在测试或预测时,只使用所学的知识。当然,但要分类的文档将只包含用作特征的单词的子集。我的问题很简单:获取对给定(不属于培训集)文档的分类影响更大的单词的最有效方法是什么?我可以考虑功能集和描述文档的标记集的交叉点,只考虑顶部和底部功能,但可能有更好的方法。你能提供代码吗?你能提供代码吗?据我所知,get_params提供了模型的参数,这不是我想要的。谢谢,我尝试了代码:print(显示信息量最大的功能(text_model,'test content test content…))但是我得到了AttributeError:“LogisticRegression”对象没有属性“transform”。发生错误的原因是transform函数不可用于logistic回归。我对该函数做了一个修改版本,可以与任何分类器模型一起使用,包括logreg。请看我的下一篇文章…谢谢,我尝试了你的功能,但我认为它没有按预期工作,请看我的评论。谢谢,它似乎没有按预期工作;如果我想在模型中使用矢量器,我想我必须不向函数传递任何信息,而不是矢量化,对吗?但我认为在函数的开头缺少一个向量器.fit_变换([text])。。。如果我加上它,我会得到ValueError:X每个样本有474个特征;预计为2795333。我认为您的代码包含一个错误:如果我传递矢量器,feature_names仅包含文本的特征,但coefs包含模型中的所有系数,您能检查它吗?我想你首先要从coefs中得到与所传递文本的特征相对应的系数。