【问题标题】:Different types of features to train Naive Bayes in Python Pandas在 Python Pandas 中训练朴素贝叶斯的不同类型的特征
【发布时间】:2015-12-18 21:39:29
【问题描述】:

我想使用一些特征来训练朴素贝叶斯分类器来分类“A”或“非A”。

我具有不同值类型的三个特征: 1) total_length - 正整数 2) 元音比率 - 小数/分数 3) twoLetters_lastName - 一个包含多个双字母字符串的数组

# coding=utf-8
from nltk.corpus import names
import nltk
import random
import numpy as np
import pandas as pd
from pandas import DataFrame, Series
from sklearn.naive_bayes import GaussianNB
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

# Import data into pandas
data = pd.read_csv('XYZ.csv', header=0, encoding='utf-8', 
    low_memory=False)
df = DataFrame(data)

# Randomize records
df = df.reindex(np.random.permutation(df.index))

# Assign column into label Y
df_Y = df[df.AScan.notnull()][['AScan']].values # Labels are 'A' or 'non-A'
#print df_Y

# Assign column vector into attribute X
df_X = df[df.AScan.notnull()][['total_length', 'vowel_ratio', 'twoLetters_lastName']].values
#print df_X[0:10]

# Incorporate X and Y into ML algorithms
clf = GaussianNB()
clf.fit(df_X, df_Y)

df_Y 如下:

[[u'non-A']
 [u'A']
 [u'non-A']
 ..., 
 [u'A']
 [u'non-A']
 [u'non-A']]

df_X 如下:

[[9L 0.222222222 u"[u'ke', u'el', u'll', u'ly']"]
 [17L 0.41176470600000004
  u"[u'ma', u'ar', u'rg', u'ga', u'ar', u'ri', u'is']"]
 [11L 0.454545455 u"[u'du', u'ub', u'bu', u'uc']"]
 [11L 0.454545455 u"[u'ma', u'ah', u'he', u'er']"]
 [15L 0.333333333 u"[u'ma', u'ag', u'ge', u'ee']"]
 [13L 0.307692308 u"[u'jo', u'on', u'ne', u'es']"]
 [12L 0.41666666700000005
  u"[u'le', u'ef', u'f\\xe8', u'\\xe8v', u'vr', u're']"]
 [15L 0.26666666699999997 u"[u'ni', u'ib', u'bl', u'le', u'et', u'tt']"]
 [15L 0.333333333 u"[u'ki', u'in', u'ns', u'sa', u'al', u'll', u'la']"]
 [11L 0.363636364 u"[u'mc', u'cn', u'ne', u'ei', u'il']"]]

我收到此错误:

E:\Program Files Extra\Python27\lib\site-packages\sklearn\naive_bayes.py:150: DataConversionWarning: A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().
  y = column_or_1d(y, warn=True)
Traceback (most recent call last):
  File "C:werwer\wer\wer.py", line 32, in <module>
    clf.fit(df_X, df_Y)
  File "E:\Program Files Extra\Python27\lib\site-packages\sklearn\naive_bayes.py", line 163, in fit
    self.theta_[i, :] = np.mean(Xi, axis=0)
  File "E:\Program Files Extra\Python27\lib\site-packages\numpy\core\fromnumeric.py", line 2727, in mean
    out=out, keepdims=keepdims)
  File "E:\Program Files Extra\Python27\lib\site-packages\numpy\core\_methods.py", line 69, in _mean
    ret, rcount, out=ret, casting='unsafe', subok=False)
TypeError: unsupported operand type(s) for /: 'unicode' and 'long'

我的理解是我需要将特征转换为一个 numpy 数组作为特征向量,但我不认为我是否正在准备这个 X 向量,因为它包含非常不同的值类型。

【问题讨论】:

  • 让我们从顶部的错误开始。在回溯之前,错误提示您需要重塑您的 df_Y。你试过搞砸吗?
  • 我不确定它想要什么最终格式。我唯一能想到的就是在每行之间添加一个“,”。那是问题吗?明天早上我会尝试编码它,因为它已经很晚了

标签: python-2.7 pandas machine-learning scikit-learn nltk


【解决方案1】:

我不是 100% 确定,但我认为 scikit-learn.naive_bayes 需要一个纯数字特征向量,而不是文本和数字的混合。尝试将 unicode 字符串除以长整数时,它看起来会崩溃。

对于查找文本的数字表示我帮不上什么忙,但this scikit-learn tutorial 可能是一个好的开始。

【讨论】:

  • 谢谢,我会调查的。可能做一堆教程加上针对具有字符串功能的教程是要走的路。
【解决方案2】:

相关问题:Choosing a Classification Algorithm to Classify Mix of Nominal and Numeric Data -- Mixing Categorial and Continuous Data in Naive Bayes Classifier Using Scikit-learn

好的,现在有一些事情正在发生。正如 DalekSec 指出的那样,当您将所有功能输入到GaussianNB 之类的模型中时,最好将它们保留为一种类型。回溯表明,在拟合模型时,它会尝试将字符串(可能是您的 unicode 字符串之一,如 u"[u'ke', u'el', u'll', u'ly']")除以整数。所以我们需要做的就是将训练数据转换成sklearn可以使用的形式。我们可以通过几种方式做到这一点,其中两种方式 ogrisel 在这个答案here 中雄辩地描述了。

  1. 我们可以将所有连续变量转换为分类变量。在我们的例子中,这意味着转换total_length(在某些情况下您可能会将其视为分类变量,但我们不要超前)和vowel-ratio。例如,您基本上可以根据百分位数将您在每个特征中看到的值分为 5 个值之一:“非常小”、“小”、“中”、“高”、“非常高”。据我所知,在 sk-learn 中没有真正简单的方法,但自己做应该很简单。您唯一要更改的是您将要使用MultinomialNB 而不是GaussianNB,因为您将处理多项分布而不是高斯分布更好地描述的特征。

  2. 我们可以将分类特征转换为数字特征以用于GaussianNB。我个人认为这是更直观的方法。基本上,在处理文本时,您需要弄清楚要从文本中获取哪些信息并传递给分类器。在我看来,您想提取不同的两个字母姓氏的发生率。

    通常我会问你是否有数据集中的所有姓氏,但由于每个姓氏只有两个字母,我们可以存储所有可能的两个字母名称(包括涉及重音符号的 unicode 字符)对性能的影响最小。这就是 sklearn 的 CountVectorizer 之类的东西可能有用的地方。假设您的数据中有两个字母姓氏的所有可能组合,您可以直接使用它来将 twoLetter_lastname 列中的一行转换为一个 N 维向量,该向量记录您的行中每个唯一姓氏的出现次数.然后将这个新向量与其他两个特征组合成一个 numpy 数组。

    如果您没有两个字母的所有可能组合(包括重音字母),您应该考虑生成该列表并将其作为 CountVectorizer 的“词汇表”传递。这是为了让您的分类器知道如何处理所有可能的姓氏。 如果您不处理所有情况,这不是世界末日,但是在此方案中将忽略任何新的看不见的两个字母对。

    在使用这些工具之前,您应该确保将姓氏列作为列表而不是字符串传递,因为这可能会导致意外行为。

    您可以阅读更多关于通用 sklearn 预处理 here 的信息,以及更多关于 CountVectorizer 和 sklearn here 提供的其他文本特征提取工具的信息。我每天都会使用很多这些工具,并推荐它们用于基本的文本提取任务。网上也有大量的教程和演示。您可能还会寻找其他类型的表示方法,例如二值化和单热编码。有很多方法可以解决这个问题,这主要取决于您的具体问题/需求。


在您能够将所有数据转换为一种或另一种形式之后,您应该能够使用高斯或多项式 NB 分类器。至于你关于一维向量的错误,你打印了 df_Y ,它看起来像

[[u'non-A']
 [u'A']
 [u'non-A']
 ..., 
 [u'A']
 [u'non-A']
 [u'non-A']]

基本上,它期望这是一个平面列表,而不是列向量(一维列表的列表)。只需通过使用 numpy.reshape() 或 numpy.ravel() 之类的命令来相应地对其进行整形(考虑到您只处理一列,如错误所述,numpy.ravel() 可能更合适)。

【讨论】:

    猜你喜欢
    • 2020-03-07
    • 2015-06-25
    • 2020-06-28
    • 2013-04-11
    • 2020-01-13
    • 2019-04-07
    • 2014-02-21
    • 2020-09-13
    相关资源
    最近更新 更多