Python TfDif和自定义要素之间的FeatureUnion上的KeyError
我正在尝试创建一个模型,在该模型中,我将在文本列上使用TfidfVectorizer,还将在文本上使用其他两列的额外数据。下面的代码再现了我试图做的事情和我得到的错误Python TfDif和自定义要素之间的FeatureUnion上的KeyError,python,scikit-learn,sklearn-pandas,Python,Scikit Learn,Sklearn Pandas,我正在尝试创建一个模型,在该模型中,我将在文本列上使用TfidfVectorizer,还将在文本上使用其他两列的额外数据。下面的代码再现了我试图做的事情和我得到的错误 import pandas as pd from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.base import BaseEstimator, TransformerMixin from sklearn.pipeline import
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.pipeline import FeatureUnion
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction import DictVectorizer
from sklearn.naive_bayes import BernoulliNB
class ParStats(BaseEstimator, TransformerMixin):
def fit(self, X, y=None):
return self
def transform(self, X):
print(X[0])
return [{'feat_1': x['feat_1'],
'feat_2': x['feat_2']}
for x in X]
class ItemSelector(BaseEstimator, TransformerMixin):
def __init__(self, key):
self.key = key
def fit(self, x, y=None):
return self
def transform(self, data_dict):
return data_dict[self.key]
def feature_union_test():
# create test data frame
test_data = {
'text': ['And the silken, sad, uncertain rustling of each purple curtain',
'Thrilled me filled me with fantastic terrors never felt before',
'So that now, to still the beating of my heart, I stood repeating',
'Tis some visitor entreating entrance at my chamber door',
'Some late visitor entreating entrance at my chamber door',
'This it is and nothing more'],
'feat_1': [4, 7, 10, 7, 4, 6],
'feat_2': [1, 5, 5, 1, 1, 10],
'ignore': [1, 1, 1, 0, 0, 0]
}
test_df = pd.DataFrame(data=test_data)
y_train = test_df['ignore'].values.astype('int')
# Feature Union Pipeline
pipeline = FeatureUnion([
('text', Pipeline([
('selector', ItemSelector(key='text')),
('tfidf', TfidfVectorizer(max_df=0.5)),
])),
('parstats', Pipeline([
('stats', ParStats()),
('vect', DictVectorizer()),
]))
])
tfidf = pipeline.fit_transform(test_df)
# fits Naive Bayes
clf = BernoulliNB().fit(tfidf, y_train)
feature_union_test()
运行此操作时,会收到以下错误消息:
Traceback (most recent call last):
File "C:\Users\Rogerio\Python VENV\lib\site-packages\pandas\core\indexes\base.py", line 3064, in get_loc
return self._engine.get_loc(key)
File "pandas\_libs\index.pyx", line 140, in pandas._libs.index.IndexEngine.get_loc
File "pandas\_libs\index.pyx", line 162, in pandas._libs.index.IndexEngine.get_loc
File "pandas\_libs\hashtable_class_helper.pxi", line 1492, in pandas._libs.hashtable.PyObjectHashTable.get_item
File "pandas\_libs\hashtable_class_helper.pxi", line 1500, in pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: 0
我尝试了管道的几个不同的迭代,我总是会遇到一些错误,所以很明显我遗漏了一些东西。我做错了什么?错误发生在
ParStats
类中的transform
中首先,
pandas
不支持直接索引,因此您的print(X[0])
抛出了您看到的错误而且,您不能以这样的方式迭代数据帧
以下是该函数的可能工作版本:
def transform(self, X):
return [{'feat_1': x[0], 'feat_2': x[1]}
for x in X[['feat_1', 'feat_2']].values]
当然,还有很多其他可能的解决方案,但您已经明白了。错误发生在
ParStats
类中的transform
中首先,
pandas
不支持直接索引,因此您的print(X[0])
抛出了您看到的错误而且,您不能以这样的方式迭代数据帧
以下是该函数的可能工作版本:
def transform(self, X):
return [{'feat_1': x[0], 'feat_2': x[1]}
for x in X[['feat_1', 'feat_2']].values]
当然,还有很多其他可能的解决方案,但是你知道了。好的。在评论中讨论之后,这是你的问题陈述 您希望将列
feat_1
、feat_2
以及text
列的tfidf传递给您的ml模型
所以你唯一需要做的就是:
# Feature Union Pipeline
pipeline = FeatureUnion([('text', Pipeline([('selector', ItemSelector(key='text')),
('tfidf', TfidfVectorizer(max_df=0.5)),
])),
('non_text', ItemSelector(key=['feat_1', 'feat_2']))
])
tfidf = pipeline.fit_transform(test_df)
默认的
ItemSelector
可用于一次选择多个要素,这些要素将附加到要素联合的text
部分返回的最后一个tfidf数据中。确定。在评论中讨论之后,这是你的问题陈述
您希望将列feat_1
、feat_2
以及text
列的tfidf传递给您的ml模型
所以你唯一需要做的就是:
# Feature Union Pipeline
pipeline = FeatureUnion([('text', Pipeline([('selector', ItemSelector(key='text')),
('tfidf', TfidfVectorizer(max_df=0.5)),
])),
('non_text', ItemSelector(key=['feat_1', 'feat_2']))
])
tfidf = pipeline.fit_transform(test_df)
默认的
ItemSelector
可用于一次选择多个要素,这些要素将附加到要素联合的text
部分返回的最后一个tfidf数据中。正如您在管道的第一部分添加了ItemSelector,为什么不将其添加到第二部分(ParStats
)?什么是X[0]
?如果X是一个数据帧,那么它是否有一个名为0
的列?还是要打印数据帧的第一行?此外,DictVectorizer只是将dicts列表中的数据排列为单独的特征(根据dicts中的键)。但您已经将数据分为列(feat_1和feat_2)。所以我不知道你为什么要使用DictVectorizer?@VivekKumar打印(X[0])是我调试的一部分,我应该在发布问题之前删除它。DictVectorizer将转换返回的字典转换为矩阵,用于sklearn。这就是我要说的。您的列feat1
和feat2
是否包含字典作为元素?你能展示一些例子吗?feat1
和feat2
只包含整数。完整的数据帧
在代码中。然而,transform返回一个字典。正如您在管道的第一部分添加了ItemSelector一样,为什么不将它添加到第二部分(ParStats
)?什么是X[0]
?如果X是一个数据帧,那么它是否有一个名为0
的列?还是要打印数据帧的第一行?此外,DictVectorizer只是将dicts列表中的数据排列为单独的特征(根据dicts中的键)。但您已经将数据分为列(feat_1和feat_2)。所以我不知道你为什么要使用DictVectorizer?@VivekKumar打印(X[0])是我调试的一部分,我应该在发布问题之前删除它。DictVectorizer将转换返回的字典转换为矩阵,用于sklearn。这就是我要说的。您的列feat1
和feat2
是否包含字典作为元素?你能展示一些例子吗?feat1
和feat2
只包含整数。完整的数据帧
在代码中。然而,transform返回一个字典。这非常有效。非常感谢。问题在于我对熊猫的使用,而不是我所怀疑的功能联盟。我错误地留下的打印(X[0])是我调试的一部分。这非常有效。非常感谢。问题在于我对熊猫的使用,而不是我所怀疑的功能联盟。我错误地留下的打印(X[0])是我调试的一部分。这实际上是一个比上面@Qusai Alothman提出的更简单的解决方案,因此我将此标记为解决方案。非常感谢。这实际上是一个比上面@Qusai Alothman提出的更简单的解决方案,因此我将其标记为解决方案。非常感谢。