如何使用 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)
【问题讨论】:
您的火车数据集由两列组成,对吗?question1
和 question2
?
是的,训练集有两列。
您可以使用TfidfVectorizer 代替 CountVectorizer 和 TfidfTransformer,这将简化此操作。但是您需要一次处理一列。
【参考方案1】:
错误不是因为最后一列,而是因为您的训练 xdataset 将包含两列 question1
和 question2
。现在这将导致您X_train
将每一行作为值列表。因此,当CountVectorizer
尝试将其转换为小写时,它会返回错误,因为 numpy.ndarray 不包含 lower 函数。
要解决此问题,您需要将数据集 X_train
拆分为两部分,例如 X_train_pt1
和 X_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 或 CountVectorizor 对象并执行转换并相应地返回数据的通用函数。 非常感谢。已尝试修改后的答案,但现在遇到了一个新错误:TypeError: no supported conversion for types: (dtype('以上是关于如何使用 Numpy 数组解决 Scikit 学习预处理管道错误?的主要内容,如果未能解决你的问题,请参考以下文章
Scikit/Numpy/Pandas ValueError:使用序列设置数组元素
无论在 scikit-learn 中使用列表还是 numpy 数组,结果都不同
如果输入是numpy数组,为啥scikit-learns Multiple Regression方法会产生错误?