Scikit Learn OneHotEncoder 拟合和变换错误:ValueError:X 的形状与拟合期间不同
Posted
技术标签:
【中文标题】Scikit Learn OneHotEncoder 拟合和变换错误:ValueError:X 的形状与拟合期间不同【英文标题】:Scikit Learn OneHotEncoder fit and transform Error: ValueError: X has different shape than during fitting 【发布时间】:2018-06-12 22:56:04 【问题描述】:下面是我的代码。
我知道为什么在转换过程中会发生错误。这是因为在拟合和变换期间特征列表不匹配。 我该如何解决这个问题?我怎样才能获得所有其余功能的 0?
之后我想用它来部分拟合 SGD 分类器。
Jupyter QtConsole 4.3.1
Python 3.6.2 |Anaconda custom (64-bit)| (default, Sep 21 2017, 18:29:43)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.1.0 -- An enhanced Interactive Python. Type '?' for help.
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
input_df = pd.DataFrame(dict(fruit=['Apple', 'Orange', 'Pine'],
color=['Red', 'Orange','Green'],
is_sweet = [0,0,1],
country=['USA','India','Asia']))
input_df
Out[1]:
color country fruit is_sweet
0 Red USA Apple 0
1 Orange India Orange 0
2 Green Asia Pine 1
filtered_df = input_df.apply(pd.to_numeric, errors='ignore')
filtered_df.info()
# apply one hot encode
refreshed_df = pd.get_dummies(filtered_df)
refreshed_df
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3 entries, 0 to 2
Data columns (total 4 columns):
color 3 non-null object
country 3 non-null object
fruit 3 non-null object
is_sweet 3 non-null int64
dtypes: int64(1), object(3)
memory usage: 176.0+ bytes
Out[2]:
is_sweet color_Green color_Orange color_Red country_Asia \
0 0 0 0 1 0
1 0 0 1 0 0
2 1 1 0 0 1
country_India country_USA fruit_Apple fruit_Orange fruit_Pine
0 0 1 1 0 0
1 1 0 0 1 0
2 0 0 0 0 1
enc = OneHotEncoder()
enc.fit(refreshed_df)
Out[3]:
OneHotEncoder(categorical_features='all', dtype=<class 'numpy.float64'>,
handle_unknown='error', n_values='auto', sparse=True)
new_df = pd.DataFrame(dict(fruit=['Apple'],
color=['Red'],
is_sweet = [0],
country=['USA']))
new_df
Out[4]:
color country fruit is_sweet
0 Red USA Apple 0
filtered_df1 = new_df.apply(pd.to_numeric, errors='ignore')
filtered_df1.info()
# apply one hot encode
refreshed_df1 = pd.get_dummies(filtered_df1)
refreshed_df1
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1 entries, 0 to 0
Data columns (total 4 columns):
color 1 non-null object
country 1 non-null object
fruit 1 non-null object
is_sweet 1 non-null int64
dtypes: int64(1), object(3)
memory usage: 112.0+ bytes
Out[5]:
is_sweet color_Red country_USA fruit_Apple
0 0 1 1 1
enc.transform(refreshed_df1)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-6-33a6a884ba3f> in <module>()
----> 1 enc.transform(refreshed_df1)
~/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/data.py in transform(self, X)
2073 """
2074 return _transform_selected(X, self._transform,
-> 2075 self.categorical_features, copy=True)
2076
2077
~/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/data.py in _transform_selected(X, transform, selected, copy)
1810
1811 if isinstance(selected, six.string_types) and selected == "all":
-> 1812 return transform(X)
1813
1814 if len(selected) == 0:
~/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/data.py in _transform(self, X)
2030 raise ValueError("X has different shape than during fitting."
2031 " Expected %d, got %d."
-> 2032 % (indices.shape[0] - 1, n_features))
2033
2034 # We use only those categorical features of X that are known using fit.
ValueError: X has different shape than during fitting. Expected 10, got 4.
【问题讨论】:
【参考方案1】:您的编码器安装在包含 10 列的 refreshed_df
上,而您的 refreshed_df1
仅包含 4 列,即错误中报告的字面意思。您必须删除未出现在 refreshed_df1
上的列,或者将编码器安装到仅包含出现在 refreshed_df1
中的 4 列的 refreshed_df
的新版本中。
【讨论】:
我无法删除特征列,因为我想将输出用于 SGDClassifer partial_fit。我需要所有功能,但 0 请检查这个问题***.com/questions/47892066/…。有人建议我使用变换 如果您只添加空列并执行fill_na()
会不会起作用?
是的,它可能会起作用。但我正在寻找 sklearn 中的内容。
是的,partial_fit
需要所有列(特征),但只能在适合您记忆的数据点子集(训练示例)上进行训练。训练一组不同的特征意味着每次训练一个不同的模型。检查***.com/questions/24617356/…【参考方案2】:
您需要LabelEncoder + OneHotEncoder 而不是使用pd.get_dummies()
,它可以存储原始值,然后将它们用于新数据。
像下面这样更改您的代码将为您提供所需的结果。
import pandas as pd
from sklearn.preprocessing import OneHotEncoder, LabelEncoder
input_df = pd.DataFrame(dict(fruit=['Apple', 'Orange', 'Pine'],
color=['Red', 'Orange','Green'],
is_sweet = [0,0,1],
country=['USA','India','Asia']))
filtered_df = input_df.apply(pd.to_numeric, errors='ignore')
# This is what you need
le_dict =
for col in filtered_df.columns:
le_dict[col] = LabelEncoder().fit(filtered_df[col])
filtered_df[col] = le_dict[col].transform(filtered_df[col])
enc = OneHotEncoder()
enc.fit(filtered_df)
refreshed_df = enc.transform(filtered_df).toarray()
new_df = pd.DataFrame(dict(fruit=['Apple'],
color=['Red'],
is_sweet = [0],
country=['USA']))
for col in new_df.columns:
new_df[col] = le_dict[col].transform(new_df[col])
new_refreshed_df = enc.transform(new_df).toarray()
print(filtered_df)
color country fruit is_sweet
0 2 2 0 0
1 1 1 1 0
2 0 0 2 1
print(refreshed_df)
[[ 0. 0. 1. 0. 0. 1. 1. 0. 0. 1. 0.]
[ 0. 1. 0. 0. 1. 0. 0. 1. 0. 1. 0.]
[ 1. 0. 0. 1. 0. 0. 0. 0. 1. 0. 1.]]
print(new_df)
color country fruit is_sweet
0 2 2 0 0
print(new_refreshed_df)
[[ 0. 0. 1. 0. 0. 1. 1. 0. 0. 1. 0.]]
【讨论】:
有效。我更早地想到了这一点。但是 LabelEncoder 不是用于 Y 目标而不是 X 特征吗? sklearn 的里程碑 20 也将发布 CategoricalEncoder。不过谢谢你的回答。 @PunithRaj 是的,它就是为此而生的。但是在 scikit 中,我们没有任何其他实用程序可以一次为 multiplt 功能执行此操作(但是,有 one present in development branch 并且可能在下一个版本中可用,它将 LE 和 OHE 组合到一个包装器中。)除非我们有使用此解决方法。 谢谢。我已经注意到我们稍后升级时会使用新功能。以上是关于Scikit Learn OneHotEncoder 拟合和变换错误:ValueError:X 的形状与拟合期间不同的主要内容,如果未能解决你的问题,请参考以下文章
[机器学习与scikit-learn-2]:如何学习Scikit-learn
[机器学习与scikit-learn-3]:scikit-learn模型地图与模型选择
“OneVsRestClassifier”(Scikit-learn)和“Binary Relevance”(Scikit-multilearn)有啥区别?