超越关键字依赖的文本分类并推断实际含义

Text classification beyond the keyword dependency and inferring the actual meaning

我正在尝试开发一个文本 class 化器,它将 class 将一段文本 PrivatePublic。以医疗或健康信息为例。我能想到的典型 classifier 将关键字视为主要区分器,对吗?像下面这样的场景怎么样?如果两段文本都包含相似的关键字但含义不同怎么办?

以下一段文字透露了某人的私人(健康)情况(患者患有癌症):

我去过两次 clinics 和我的 pcp。我有一个 ultrasound 只是被告知它是一个解析 cyst 或一个 hematoma,但它越来越大并开始使我的腿 achePCP 说它不可能是 cyst,因为它开始时太大了,我发誓我的腿从来没有 injured,甚至 bump 也没有。我现在又害怕又害怕cancer。大约 9 个月前,我在蹲下时才注意到有点不舒服的感觉。 3个月前我蹲下来收衣服有点hurtpain 促使我检查我的 leg,那时我注意到我的小腿 muscle 底部有一个 lump,弯曲只会让它更明显。最终在四次 clinic 次访问后,一次 ultrasound 一次 pcp 结果似乎是阳性,并且质量越来越大。
[私有](正确分类)

下面这段文字是医生的评价,绝对不会暴露健康状况。它介绍了典型的 classifier 模型的弱点:

不要害怕,也不要像 cancer 那样假设任何不好的事情。我在 clinic 中经历过几个案例,对我来说似乎很熟悉。正如您提到的,它可能是 cysthematoma,并且它越来越大,它必须需要一些额外的 diagnosis,例如 biopsy。在那个区域有一个 achelump 的大小并不能说明什么 bad。在lump之前,您应该多访问几次专门的clinics并进行一些特定的测试,例如biopsyCT scanpcpultrasound变得更大。
[Private](分类错误,应该是[Public])

第二段被我当前的所有 class 编辑者 class 确定为私有,原因很明显。相似的关键词、有效的词序列、主语的存在似乎让 classifier 非常困惑。甚至,这两个内容都包含 IYou(名词、代词)等主题。我考虑过从 Word2Vec 到 Doc2Vec,从 Inferring meaning 到 semantic embeddings,但想不出解决方法最适合这个问题。

知道我应该用什么方法来处理 class化问题吗?提前致谢。

到目前为止的进度:
我从 public 来源收集的数据,其中 patients/victims 通常 post 他们自己的情况和 doctors/well-wishers 回复那些。我在爬行时假设 - posts 属于我的私人 class,评论属于 public class。总而言之,我从 5K+5K posts/comments 开始,在没有任何主要预处理的情况下使用朴素贝叶斯 classifier 获得了大约 60%。我很快就会尝试神经网络。但是在输入任何 classifier 之前,我只想知道如何更好地进行预处理,以便为 class 中的任何一个赋予合理的权重,以便更好地区分。

这些只是模糊描述,因为整个过程是特定于任务的。不过,您可能想看看这些并从中汲取灵感。

一般提示

  • 从更简单的模型开始(正如您似乎正在做的那样),如果结果不令人满意,则逐渐增加它们的复杂性。在转向神经网络
  • 之前,您可能想尝试著名的随机森林和 xgboost

数据提示

可能对您有帮助的几个要点:

  • 您没有太多数据点。如果可能的话,我建议你从相同的(或至少非常相似的)source/distribution中收集更多的数据,我认为这对你的帮助最大。
  • 改进数据的表示(更多详细信息见下文),second/first 最佳选择。
  • 您可以尝试 stemming/lemmatization(来自 nltk or spaCy,但我认为这对这种情况没有帮助,可能会忽略这个。

数据表示

我假设您当前的表示是 Bag Of Words or TF-IDF. If you haven't tried the second one, I advise you to do it before delving into more complicated (or is it?) stuff. You could easily do it with sklearn's TfidfVectorizer

如果结果不令人满意(并且您已经尝试过随机 Forest/xgboost(或类似 Microsoft 的 LightGBM),我认为您应该继续进行语义表示。

语义表示

正如你提到的,有一个由 word2vec 或 Doc2Vec 算法创建的表示(我会留下第二个,它可能没有帮助)。

你可能想把你的例子分成句子,并添加像 <eos> 这样的标记来表示句子的,这可能有助于神经网络学习。

另一方面,还有其他一些可能更适合您的任务,例如 BERT。这个是 context dependent,这意味着一个标记 I 会根据它周围的词来表示略有不同(因为这种表示是可训练的,它应该很适合你的任务)。

Flair library offers nice and intuitive approach to this problem if you wish to go with PyTorch. If you are on the Tensorflow side, they have Tensorflow Hub,其中还包含最先进的嵌入,供您轻松使用。

神经网络

如果涉及到神经网络,请从简单的循环模型分类器开始,并使用 GRU 或 LSTM 单元(根据选择的框架,它们的语义略有不同)。

如果这种方法仍然不能令人满意,您应该查看 Attention Networks、分层注意力网络(每个句子一个注意力级别,整个文档另一个注意力级别)或基于卷积的方法。

这些方法将花费您一些时间,并且涵盖相当多的主题供您尝试,这些(或更多)的组合可能会很好地完成您的任务。

(1) 贝叶斯确实是一个弱分类器 - 我会尝试 SVM。如果您看到改进,而不是使用神经网络(也许还有深度学习)可以实现进一步的改进

(2) 特征工程 - 使用 TFiDF ,并尝试其他东西(很多人建议使用 Word2Vec,虽然我亲自尝试过但没有改善)。您也可以删除停用词。

需要考虑的一件事是,因为您给出了两个轶事,所以客观地衡量了人类之间对任务的一致程度。有时会忽略给定相同文本的两个人可能在标签上存在分歧(有些人可能会说某个特定文档是私有的,尽管它是 public)。只是要注意一点 - 因为如果例如一致度为65%,那么构建更准确的算法将非常困难。

如果您发布的数据代表了您要区分的 classes,那么基于关键字的功能可能不是最有效的。看起来一些有时被视为停用词的术语将是关于什么是 Private 什么是 Public 的很好的线索。

你提到代词,我认为这可能仍然是一个很好的前进方向。如果您正在使用 unigram/bag-of-words 种功能,请确保您的矢量化器没有删除它们。

对第一人称代词的实例进行计数(ImyI'vemine)得出 Private case 为 13,Public案例。

Public 示例有第二人称代词(例如 you),而第一个示例没有。因此,关于第一人称代词和第二人称代词的计数或平滑比率的特征可能会有效。

如果您具有句法结构或通过 n-gram 或类似表示跟踪位置信息,那么涉及第一人称代词和关键字的功能可能会有效。

此外,动词首句结构(Don't be ...Having an...)是第二人称定向语言的特征,在 public 中可能比私人文本中出现得更多。

最后一个推测性想法:这两段话的情绪非常不同,所以如果您可以进行情绪分析,那可能会提供额外的线索。我希望 Public class 比 Private class.

更中立

将您的 Public 示例插入到 Watson Tone Analyzer 演示中得到了显着的结果:

{
  "sentence_id": 3,
  "text": "I am now scared and afraid of cancer.",
  "tones": [
    {
      "score": 0.991397,
      "tone_id": "fear",
      "tone_name": "Fear"
    }
  ]
},

Public 语句也包含一个带有恐惧标记的句子,但得分不高,伴随着其他注释,并且在句子中包含明确的否定。因此,也可能值得利用这些功能。

"sentences_tone": [
    {
      "sentence_id": 0,
      "text": "Don’t be scared and do not assume anything bad as cancer.",
      "tones": [
        {
          "score": 0.874498,
          "tone_id": "fear",
          "tone_name": "Fear"
        },
        {
          "score": 0.786991,
          "tone_id": "tentative",
          "tone_name": "Tentative"
        },
        {
          "score": 0.653099,
          "tone_id": "analytical",
          "tone_name": "Analytical"
        }
      ]
    },