文本分类的特征选择和降维

53
我目前正在进行一个项目,一个简单的情感分析器,使得有 2 和 3 类在不同的情况下。我使用了一个语料库,其中独特单词的数量相当丰富(约 200,000)。我使用了词袋模型方法进行特征选择,并通过出现频率的阈值进行消除,以减少独特功能的数量。最终的特征集大约包括 20,000 个特征,这实际上是一个 90% 的减少,但对于测试预测的预期准确性来说仍然不够。我轮流使用 LibSVM 和 SVM-light 进行训练和预测(线性和 RBF 内核),并且通常使用 Python 和 Bash。
至目前为止观察到的最高精度约为 75%,而我至少需要 90%。这是二元分类的情况。对于多类训练,精度下降到约 60%。我需要在两种情况下都达到至少 90%,但无法确定如何增加:通过优化训练参数还是通过优化特征选择?
我阅读了关于文本分类中的特征选择的文章,发现使用了三种不同的方法,它们实际上彼此之间有明显的相关性。这些方法如下: - 词袋的频率方法(BOW) - 信息增益 (IG) - X^2 统计量 (CHI)第一种方法已经是我使用的方法,但我使用得非常简单,需要指导以更好地使用它,以获得足够高的准确性。我还缺乏有关IG和CHI的实际实现知识,并寻求任何帮助以指导我。
非常感谢,如果您需要任何额外的信息来帮助,只需让我知道。
@larsmans: 频率阈值:我正在寻找示例中唯一词汇的出现次数,以便如果一个单词在不同的示例中频繁出现,它将作为唯一特征包含在特征集中。
  • @TheManWithNoName: 首先感谢您在解释文档分类的一般问题方面所做出的努力。我检查并尝试了您提出的所有方法和其他方法。我发现比例差异(PD)方法最适合特征选择,其中特征是单元词,而术语出现(TP)用于加权(我不明白为什么您标记词频-逆文档频率(TF-IDF)作为索引方法,我认为它是一种特征加权方法)。正如您所提到的,预处理对于这个任务也是一个重要的方面。我使用了某些类型的字符串消除来优化数据,以及形态分析词干提取。还要注意,我正在处理土耳其语,与英语有不同的特性。最后,我成功地达到了约88%二元分类的准确度(f-measure)和约84%多类别分类。这些值是我所使用的模型成功的坚实证据。这是我目前所做的事情。现在正在处理聚类和降维模型,尝试了LDALSI,并转向moVMF和可能的球形模型(LDA + moVMF),它似乎在像新闻语料库这样具有客观性质的语料库上运行得更好。如果您对这些问题有任何信息和指导,我将不胜感激。我需要信息,特别是设置界面(面向Python,开源),介于特征空间维度降低方法(LDA、LSI、moVMF等)和聚类方法(k-means、层次等)之间。


  • 你使用了什么样的频率阈值? - Fred Foo
    只是一个猜测。你的简化已经删除了必要的信息。SVM在处理许多维度方面非常出色。你尝试过更大的特征集吗?你在训练中使用的样本大小是多少?如果你不能用更多的特征进行训练,尝试训练第二频繁的20,000个词来验证是否没有留下任何信息。还有第三频繁的单词。 - stefan
    1
    @clancularius,如果可能的话,您能否更详细地解释一下您用于特征提取和特征选择的技术?我也正在处理一个文本分类问题,但是我无法将准确度提高到61%以上。 - ac-lap
    5个回答

    39
    这可能有点晚了,但是正如Bee所指出的,如果在分类之前已经失去了信息,那么使用SVM作为分类器就是浪费的。然而,文本分类过程需要更多的步骤,每个步骤对结果都有重要影响。因此,在研究更复杂的特征选择方法之前,有许多更简单的可能性,通常需要更低的资源消耗。
    在将文档进行标记/表示成词袋格式之前,你是否对文档进行了预处理?简单地删除停用词或标点符号可能会显著提高准确性。
    你是否考虑过改变你的词袋表示方式,例如使用词对或n-gram?你可能会发现,你拥有更多的维度,但它们可以更进一步压缩,并包含更多有用的信息。
    还值得注意的是,降维是特征选择/特征提取。不同之处在于,特征选择以单变量方式减少维度,即按照它们当前的出现方式逐个删除术语,而特征提取(我认为Ben Allison所指的)是多变量的,将一个或多个单个术语组合在一起产生更高的正交术语,(希望)包含更多信息并减少特征空间。
    关于您使用文档频率的问题,您是仅使用包含某个词条的文档的概率/百分比,还是使用在文档中找到的词条密度?如果类别一只有10个文档,它们各自只包含一个词条,那么类别一确实与该文档相关。然而,如果类别二只有10个文档,每个文档都包含相同的词条100次,那么显然类别二与该词条的关系要比类别一高得多。如果不考虑词条密度,这些信息就会丢失,您拥有的类别越少,这种损失就会越大。同样地,仅保留具有高频率的术语并不总是明智的,因为它们可能实际上没有提供任何有用的信息。例如,如果一个术语在每个文档中出现100次,则被认为是噪声术语,尽管看起来很重要,但在特征集中保留它没有任何实际价值。
    另外,您如何索引数据,您是使用简单的布尔索引的向量空间模型,还是使用更复杂的度量方法,例如TF-IDF?考虑到您场景中类别数量较少,使用更复杂的度量方法将是有益的,因为它们可以考虑到每个类别中的词条重要性与整个数据集中的重要性。
    个人建议首先尝试上述可能性,然后考虑使用(或结合使用)复杂方程来调整特征选择/提取,以获得额外的性能提升。

    附加信息

    根据新的信息,听起来你已经走在了正确的轨道上,对于大多数数据集来说,84%+的准确率(针对多类问题基于精确度和召回率的F1或BEP)通常被认为是非常好的。可能是你已经成功地从数据中获取了所有信息丰富的特征,或者还有一些特征正在被修剪。

    话虽如此,可以用作评估特定数据集上激进降维效果的预测器是“异常值计数”分析,它使用离群特征信息增益的下降来确定在特征选择期间是否可能丢失信息。您可以在原始和/或处理过的数据上使用它,以估计应该多么积极地修剪特征(或者取消修剪,视情况而定)。这里可以找到描述它的论文:

    具有异常值计数信息的论文

    关于将TF-IDF描述为索引方法,您是正确的,它是一种特征加权度量,但我认为它主要用作索引过程的一部分(尽管它也可以用于降维)。原因在于,某些度量更适合于特征选择/提取,而其他度量则更适合于特征加权,特别是在您的文档向量中(即索引数据)。这通常是由于降维度量是基于每个类别确定的,而索引加权度量倾向于更具有文档导向性,以提供更优秀的向量表示。
    至于LDA、LSI和moVMF,我恐怕没有足够的经验来提供任何指导。不幸的是,我也没有使用过土耳其数据集或Python语言。

    我在上面的问题中回答了你。请看一下。顺便说一句,谢谢你的回答。 - clancularius
    根据您提供的新信息,我已更新了我的答案。很抱歉目前我无法提供更多帮助,因为我即将完成博士论文的最后期限......这讽刺的是,我的论文正是关于简化、接口化和标准化文本分类中使用的阶段!如果我完成了它,我会尽力记得在这个问题中无私地推广它。 - TheManWithNoName
    我很感激你的努力,也非常感谢你。我会查看你附上的论文,并尝试加以利用。相比分类问题,聚类问题更加棘手且更加模糊,因此我现在只能靠运气了 =) 顺便祝愿你的论文成功,祝你有美好的一天。 - clancularius
    @TheManWithNoName:非常好的回答!喜欢阅读它。 - Yavar

    5
    我建议使用降维而非特征选择。考虑使用奇异值分解主成分分析,或者更好的是针对词袋表示量身定制的潜在狄利克雷分配。这将使您保留包含所有单词的表示,但通过利用它们之间的相似性(甚至同义关系)将它们折叠到较少的维度中。
    所有这些方法都有相当标准的实现,您可以访问并运行——如果您告诉我们您使用的语言,我或其他人将能够指导您正确的方向。

    首先感谢您的回复。我正在使用Python和Bash脚本。我已经快速搜索了奇异值分解、主成分分析和特别是LDA,但我需要时间来理解如何使用它们。我同意您的观点,降维似乎是我的任务的有效选择,但我不清楚是否需要基于这些方法的理论基础生成自己的降维算法,或者使用已有的实现是否足够(我不知道是否有任何已有的实现)? - clancularius
    使用现有的实现已经足够了。如果你正在使用Python,gensim可以用于LDA(http://radimrehurek.com/gensim/),或者maplotlib.mlab有一个SVD/PCA的实现:http://matplotlib.org/api/mlab_api.html#matplotlib.mlab.PCA。两者都应该有一些简单的示例,让你看看它们是如何工作的。 - Ben Allison
    非常感谢,我会查看并告知您改进的情况。 - clancularius

    4

    有一个针对特征选择的Python库TextFeatureSelection。该库提供了每个单词标记、二元组和三元组等的得分来衡量其区分能力。

    熟悉机器学习中特征选择方法的人们知道,它基于过滤方法,为自然语言处理(NLP)和深度学习模型的工程师提供了必要的工具来提高分类准确性。它有四种方法,即卡方检验互信息比例差异信息增益,可帮助选择词汇作为机器学习分类器的特征。

    from TextFeatureSelection import TextFeatureSelection
    
    #Multiclass classification problem
    input_doc_list=['i am very happy','i just had an awesome weekend','this is a very difficult terrain to trek. i wish i stayed back at home.','i just had lunch','Do you want chips?']
    target=['Positive','Positive','Negative','Neutral','Neutral']
    fsOBJ=TextFeatureSelection(target=target,input_doc_list=input_doc_list)
    result_df=fsOBJ.getScore()
    print(result_df)
    
    #Binary classification
    input_doc_list=['i am content with this location','i am having the time of my life','you cannot learn machine learning without linear algebra','i want to go to mars']
    target=[1,1,0,1]
    fsOBJ=TextFeatureSelection(target=target,input_doc_list=input_doc_list)
    result_df=fsOBJ.getScore()
    print(result_df)
    

    编辑:

    现在它还具有用于特征选择的遗传算法。

    from TextFeatureSelection import TextFeatureSelectionGA
    #Input documents: doc_list
    #Input labels: label_list
    getGAobj=TextFeatureSelectionGA(percentage_of_token=60)
    best_vocabulary=getGAobj.getGeneticFeatures(doc_list=doc_list,label_list=label_list)
    

    编辑2

    现在还有另一种方法TextFeatureSelectionEnsemble,它结合了特征选择和集成学习。它通过文档频率阈值进行基模型的特征选择。在集成层,它使用遗传算法来确定最佳的基模型组合,并只保留这些模型。

    from TextFeatureSelection import TextFeatureSelectionEnsemble 
    
    imdb_data=pd.read_csv('../input/IMDB Dataset.csv')
    le = LabelEncoder()
    imdb_data['labels'] = le.fit_transform(imdb_data['sentiment'].values)
    
    #convert raw text and labels to python list
    doc_list=imdb_data['review'].tolist()
    label_list=imdb_data['labels'].tolist()
    
    #Initialize parameter for TextFeatureSelectionEnsemble and start training
    gaObj=TextFeatureSelectionEnsemble(doc_list,label_list,n_crossvalidation=2,pickle_path='/home/user/folder/',average='micro',base_model_list=['LogisticRegression','RandomForestClassifier','ExtraTreesClassifier','KNeighborsClassifier'])
    best_columns=gaObj.doTFSE()`
    

    请查看项目详情:https://pypi.org/project/TextFeatureSelection/


    1
    我确定这篇文章已经太晚了,对于发帖者没有用处,但也许对其他人有用。使用卡方检验进行特征降维相当简单。假设将BoW二元分类为C1和C2类,对于候选特征中的每个特征f,计算f在C1中的频率;计算C1中的总词数;重复计算C2;计算卡方值,并根据p值是否低于某个阈值(例如 p < 0.05)来确定过滤的候选特征。可以在此处查看使用Python和nltk的教程:http://streamhacker.com/2010/06/16/text-classification-sentiment-analysis-eliminate-low-information-features/(尽管如果我记得正确,我认为作者错误地将该技术应用于他的测试数据,这会使报告的结果产生偏差)。

    1

    线性支持向量机适用于高维特征。根据我的经验,SVM准确度的最终限制取决于正负“特征”。您可以进行网格搜索(或在线性SVM的情况下,只需搜索最佳成本值)以找到最大准确度的最优参数,但最终您受到特征集可分离性的限制。您没有达到90%的事实意味着您仍需要努力寻找更好的特征来描述类别成员。


    @larsmans 这已经是我所要求的了。正如我上面解释的那样,我正在寻找一种更好的“特征选择”方法,你建议我做什么。在训练数据集之前,我已经使用了网格函数进行参数选择,然而参数值迭代结束后,参数值让我无法获得高于约70-75%的预测准确度。是的,我需要选择我的特征来获得更好的准确度结果,但怎么选择呢?您知道如何使用IG和CHI特征选择方法吗?您知道如何优化词频方法的实现吗? - clancularius

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接