用于文本分类的朴素贝叶斯 - Python 2.7 数据结构问题

Posted

技术标签:

【中文标题】用于文本分类的朴素贝叶斯 - Python 2.7 数据结构问题【英文标题】:Naive Bayes for Text Classification - Python 2.7 Data Structure Issue 【发布时间】:2017-08-28 21:58:30 【问题描述】:

我在训练朴素贝叶斯分类器时遇到问题。我有一个我想使用的功能集和目标,但我不断收到错误。我看过其他有类似问题的人,但我似乎无法弄清楚问题所在。我确定有一个简单的解决方案,但我还没有找到。

这是我试图用来训练分类器的数据结构示例。

In [1] >> train[0]
Out[1] (
         u'profici': [False],
         u'saver': [False],
         u'four': [True],
         u'protest': [False],
         u'asian': [True],
         u'upsid': [False],
         .
         .
         .
         u'captain': [False],
         u'payoff': [False],
         u'whose': [False]
         ,
         0)

其中 train[0] 是列表中的第一个元组,包含:

用于指示文档中是否存在单词的特征和布尔值字典[0]

document[0]二分类的目标标签

显然,火车列表的其余部分包含我想要分类的其他文档的特征和标签。

运行以下代码时

from nltk.classify.scikitlearn import SklearnClassifier
from sklearn.naive_bayes import MultinomialNB

MNB_clf = SklearnClassifier(MultinomialNB())
MNB_clf.train(train)

我收到错误消息:

  TypeError: float() argument must be a string or a number 

编辑:

功能在此处创建。来自包含第 1 列中的帖子和第 2 列中的情绪分类的数据框 post_sent。

  stopwords = set(stopwords.words('english'))
  tokenized = []
  filtered_posts = []
  punc_tokenizer = RegexpTokenizer(r'\w+')

  #  tokenizing and removing stopwords
   for post in post_sent.post:
      tokenized = [word.lower() for word in. 
      punc_tokenizer.tokenize(post)]
      filtered = ([w for w in tokenized if not w in stopwords])
  filtered_posts.append(filtered)    

  # stemming
  tokened_stemmed = []
  for post in filtered_posts:
      stemmed = []
  for w in post:
       stemmed.append(PorterStemmer().stem_word(w))
  tokened_stemmed.append(stemmed)   

  #frequency dist
 all_words =. 
   list(itertools.chain.from_iterable(tokened_stemmed))
   frequency = FreqDist(all_words)

  # Feature selection
  word_features = list(frequency.keys())[:3000]

   # IMPORTANT PART
   #######################
   #------ featuresets creation ---------
  def find_features(list_of_posts):
       features = 
       wrds = set(post)
           for w in word_features:
              features[w] = [w in wrds]
  return features

  # zipping inputs with targets
  words_and_sent = zip(tokened_stemmed, 
   post_sent.sentiment)

   # IMPORTANT PART 
   ##########################
  # feature sets created here
  featuresets = [(find_features(words), sentiment) for 
   words, sentiment in 
   words_and_sent]

【问题讨论】:

您的特征字典的值都是具有单个值的列表:[False]。相反,它们可能应该直接是布尔值True/False,而不是包含在列表中。 好的,现在我有一个不同的问题.. ` In [1] >> train[0] out[1] >> ([False, False, True, ... False, ], 0)`这给了我错误AttributeError: 'list' object has no attribute 'iteritems' 【参考方案1】:

你设置错了火车。正如@lenz 在评论中所说,删除特征字典值中的括号并仅使用单个值。

如official documentation:

labeled_featuresets – (特征集、标签)列表,其中每个 featureset 是一个将字符串映射到数字、布尔值或 字符串。

但是您将映射(dict 中键的值)设置为列表。

你正确的火车应该是这样的:

[(u'profici':False,
   u'saver':False,
   u'four':True,
   u'protest':False,
   u'asian':True,
   u'upsid':False,
   .
   .
  , 0),
     .. 
     ..
 (u'profici':True,
   u'saver':False,
   u'four':False,
   u'protest':False,
   u'asian':True,
   u'upsid':False,
   .
   .
  , 1)]

您可以在此处查看更多示例: - http://www.nltk.org/howto/classify.html

【讨论】:

谢谢 Vivek,这更清楚了。我对字典数据类型不是特别擅长。关于如何将它从我现在拥有的东西转换为我需要的东西,你有什么建议吗?干杯 @DiarmaidFinnerty 您最初是如何创建功能集的?更新您的答案(或发布新答案)以包含生成您标记的功能集的代码,然后它将直接向您展示如何修复它。 嗨,lenz,我已经添加了创建功能集的代码 嗨维韦克,感谢您的帮助。如果您愿意,可以编辑您的帖子以包含使其正确运行的代码(作为答案发布在下面)。感谢所有帮助!【参考方案2】:

感谢 Vivek 和 Lenz 的帮助,他们向我解释了这个问题,我能够重新组织我的训练集,谢天谢地,它现在可以工作了。谢谢大家!

Vivek 的帖子中很好地解释了这个问题。这是将火车数据重新组织成正确格式的代码。

 features_targ = []

for feature in range(0,len(featuresets)):
   dict_test = featuresets[feature]
   values = list(itertools.chain.from_iterable(dict_test[0].values()))
   keys = dict_test[0].keys()
   target = dict_test[1]
   dict_ion = 
   for key in range(x,len(keys)):
     dict_ion[keys[key]] = values[key]
   features_targ.append((dict_ion,target))

【讨论】:

以上是关于用于文本分类的朴素贝叶斯 - Python 2.7 数据结构问题的主要内容,如果未能解决你的问题,请参考以下文章

了解用于文本分类的朴素贝叶斯

如何在文本分类中使用朴素贝叶斯预测所需的类

朴素贝叶斯算法(python)

实现用于文本分类的朴素贝叶斯的对数可能性

将朴素贝叶斯分类器保存在内存中

朴素贝叶斯算法