我想使用一些功能来训练朴素贝叶斯分类器来分类' 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向量,因为它包含非常不同的值类型。
答案 0 :(得分:3)
相关问题: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。
我们可以将所有连续变量转换为分类变量。在我们的例子中,这意味着转换total_length
(在某些情况下,您可能会将此视为一个分类变量,但让我们不要超越自己)和vowel-ratio
。例如,您基本上可以将您在每个要素中看到的值与基于百分位数的5个值中的一个相关联:&#39;非常小&#39;小'&#39;&#39;中&#39; ,&#39; high&#39;,&#39;非常高&#39;。据我所知,在sk-learn中没有真正简单的方法,但是自己做这件事应该非常简单。您唯一想要改变的是,您希望使用MultinomialNB
而不是GaussianNB
,因为您将处理多项分布而非高斯分布更好描述的功能。
我们可以将分类功能转换为数字功能,以便与GaussianNB
一起使用。我个人认为这是更直观的方法。基本上,在处理文本时,您需要确定要从文本中获取的信息并传递给分类器。在我看来,你想提取不同的两个字母姓氏的发生率。
通常情况下,我会问你数据集中是否包含所有姓氏,但由于每一个只有两个字母,我们可以存储所有可能的两个字母名称(包括涉及重音符号的unicode字符)对性能的影响微乎其微。这就像sklearn&#39; CountVectorizer
之类的东西可能有用。假设您的数据中包含两个字母姓氏的所有可能组合,您可以直接使用它将twoLetter_lastname列中的一行转换为N维向量,该向量记录行中每个唯一姓氏的出现次数。然后将这个新的矢量与其他两个特征组合成一个numpy数组。
如果您没有两个字母(包括重音字母)的所有可能组合,您应该考虑生成该列表并将其作为“词汇表”传递给它。对于CountVectorizer。这样您的分类器就知道如何处理所有可能的姓氏。 如果您不处理所有案件,那么这不是世界末日,但在此计划中将忽略任何新的看不见的两个字母对。
在使用这些工具之前,应确保以列表的形式传递姓氏列,而不是字符串,因为这可能导致意外行为。
您可以阅读有关常规sklearn预处理here的更多信息,以及有关CountVectorizer
和sklearn here提供的其他文字特征提取工具的更多信息。我每天都使用很多这些工具,并推荐它们用于基本的文本提取任务。网上还有很多教程和演示。您也可以寻找其他类型的表示方法,如二值化和单热编码。有很多方法可以解决这个问题,主要取决于您的具体问题/需求。
在您能够将所有数据转换为一种形式或另一种形式之后,您应该能够使用高斯或多项式NB分类器。至于你关于1D矢量的错误,你打印了df_Y,它看起来像
[[u'non-A']
[u'A']
[u'non-A']
...,
[u'A']
[u'non-A']
[u'non-A']]
基本上,它期望这是一个平面列表,而不是列向量(一维列表列表)。通过使用像numpy.reshape()或numpy.ravel()这样的命令来重新塑造它(numpy.ravel()可能更合适,考虑到你只处理一个列,因为提到的错误)。
答案 1 :(得分:1)
我不是百分百肯定,但我认为scikit-learn.naive_bayes需要纯数字特征向量而不是文本和数字的混合。当尝试用长整数“划分”unicode字符串时,它看起来像崩溃了。
我找不到文字的数字表示方式帮助不大,但this scikit-learn tutorial可能是一个好的开始。