如何使用 Numpy 数组解决 Scikit 学习预处理管道错误?

Posted

技术标签:

【中文标题】如何使用 Numpy 数组解决 Scikit 学习预处理管道错误?【英文标题】:How to solve Scikit learn preprocessing pipeline error with Numpy array? 【发布时间】:2018-02-26 02:53:33 【问题描述】:

我正在使用 scikit-learn 构建一个分类器,用于预测两个句子是否是释义(例如释义:爱因斯坦有多高与阿尔伯特爱因斯坦的长度是多少)。

我的数据包含 2 列带有字符串(短语对)和 1 个带有 0 和 1 的目标列(= 没有释义,释义)。我想尝试不同的算法。

我希望下面的最后一行代码适合模型。相反,预处理管道不断产生我无法解决的错误:“AttributeError:'numpy.ndarray'对象没有属性'lower'。”

代码如下,我已经隔离了显示的最后一行中发生的错误(为简洁起见,我排除了其余部分)。我怀疑是因为目标列包含0和1,不能小写。

我已经在 *** 上尝试过类似问题的答案,但到目前为止没有运气。

您如何解决这个问题?

question1               question2                        is_paraphrase
How long was Einstein?  How tall was Albert Einstein?    1
Does society place too  How do sports contribute to the  0
much importance on      society?
sports?                 
What is a narcissistic  What is narcissistic personality 1  
personality disorder?   disorder?

======

from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
import pandas as pd
import numpy as np

para = "paraphrases.tsv"

df = pd.read_csv(para, usecols = [3, 5], nrows = 100, header=0, sep="\t")

y = df["is_paraphrase"].values
X = df.drop("is_paraphrase", axis=1).values
X = X.astype(str) # I have tried this
X = np.char.lower(X)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, 
random_state = 21, stratify = y)

text_clf = Pipeline([('vect', CountVectorizer()),('tfidf', TfidfTransformer()), 
('clf', MultinomialNB())])

text_clf.fit(X_train, y_train)

【问题讨论】:

您的火车数据集由两列组成,对吗? question1question2 ? 是的,训练集有两列。 您可以使用TfidfVectorizer 代替 CountVectorizer 和 TfidfTransformer,这将简化此操作。但是您需要一次处理一列。 【参考方案1】:

错误不是因为最后一列,而是因为您的训练 xdataset 将包含两列 question1question2。现在这将导致您X_train 将每一行作为值列表。因此,当CountVectorizer 尝试将其转换为小写时,它会返回错误,因为 numpy.ndarray 不包含 lower 函数。

要解决此问题,您需要将数据集 X_train 拆分为两部分,例如 X_train_pt1X_train_pt2。然后对这些单独执行 CountVectorizer,然后对每个单独的结果执行 tfidfTransformer。还要确保您在这些数据集上使用相同的对象进行转换。

最后,将这两个数组堆叠在一起,并将其作为分类器的输入。你可以找到类似的implementation here。

更新: 我认为以下内容应该会有所帮助(我承认这段代码可以进一步改进以提高效率):

def flat_list(my_list):
    return [str(item) for sublist in my_list for item in sublist]


def transform_data(trans_obj_list,dataset_splits):
    X_train = dataset_splits[0].astype(str)
    X_train = flat_list(X_train)

    for trfs in trans_obj_list:
        transformed_vector = trfs().fit(X_train)
        for x in xrange(0,len(dataset_splits)):
            dataset_splits[x] =flat_list(dataset_splits[x].astype(str))
            dataset_splits[x]=transformed_vector.transform(dataset_splits[x])

    return dataset_splits

new_X_train,new_X_test = transform_data([CountVectorizer,TfidfTransformer],[X_train,X_test])

【讨论】:

是否也可以单独将 X_train 小写并在 CountVectorizer 中“关闭”小写?这样代码可以保持更短(更快)。 即使您以某种方式“关闭”小写字母(尽管这是不可能的),CountVectorizer 也被实现为处理单个字符串而不是字符串列表。您将不得不更改整个实现。因此,更好的做法是创建一个接受 tfIdfTransformer 或 CountVectorizo​​r 对象并执行转换并相应地返回数据的通用函数。 非常感谢。已尝试修改后的答案,但现在遇到了一个新错误:TypeError: no supported conversion for types: (dtype(' @twhale 它基本上意味着您的数据包含一些 unicode 字符,您需要将它们编码为 ascii 才能正常工作,因为转换函数仅适用于 ascii 字符串。如果您发现此答案有用,请您投票并将此答案标记为正确答案吗?

以上是关于如何使用 Numpy 数组解决 Scikit 学习预处理管道错误?的主要内容,如果未能解决你的问题,请参考以下文章

Scikit/Numpy/Pandas ValueError:使用序列设置数组元素

使用 scikit 学习的一种热编码和熊猫

无论在 scikit-learn 中使用列表还是 numpy 数组,结果都不同

如果输入是numpy数组,为啥scikit-learns Multiple Regression方法会产生错误?

numpy+scipy+matlotlib+scikit-learn的安装及问题解决

NumPy之:NumPy简介教程