问题是多元线性回归。X包含8个分类变量,其余的分类变量被编码为0和1。
当尝试构建列转换器并拟合行时,出现了下面的错误。’TypeError: unhashable type: ‘Index”
cat_cols=df_train.select_dtypes(include="object").columnsy.head()0 130.811 88.532 76.263 80.624 78.02Name: y, dtype: float64X.head()X0 X1 X2 X3 X4 X5 X6 X8 X10 X11 ... X375 X376 X377 X378 X379 X380 X382 X383 X384 X3850 k v at a d u j o 0 0 ... 0 0 1 0 0 0 0 0 0 01 k t av e d y l o 0 0 ... 1 0 0 0 0 0 0 0 0 02 az w n c d x j x 0 0 ... 0 0 0 0 0 0 1 0 0 03 az t n f d x l e 0 0 ... 0 0 0 0 0 0 0 0 0 04 az v n f d h d n 0 0 ... 0 0 0 0 0 0 0 0 0 05 rows × 376 columnsct=make_column_transformer((OneHotEncoder(),[cat_cols]),remainder='passthrough')ColumnTransformer(remainder='passthrough', transformers=[('onehotencoder', OneHotEncoder(handle_unknown='ignore'), [Index(['X0', 'X1', 'X2', 'X3', 'X4', 'X5', 'X6', 'X8'], dtype='object')])]) ct.fit(X_train)
在这个阶段出现错误
TypeError Traceback (most recent call last)<ipython-input-180-8ea255dead4d> in <module>----> 1 ct.fit(X_train)D:\Anaconda\lib\site-packages\sklearn\compose\_column_transformer.py in fit(self, X, y) 492 # we use fit_transform to make sure to set sparse_output_ (for which we 493 # need the transformed data) to have consistent output type in predict--> 494 self.fit_transform(X, y=y) 495 return self 496 D:\Anaconda\lib\site-packages\sklearn\compose\_column_transformer.py in fit_transform(self, X, y) 527 self._validate_transformers() 528 self._validate_column_callables(X)--> 529 self._validate_remainder(X) 530 531 result = self._fit_transform(X, y, _fit_transform_one)D:\Anaconda\lib\site-packages\sklearn\compose\_column_transformer.py in _validate_remainder(self, X) 317 318 # Make it possible to check for reordered named columns on transform--> 319 self._has_str_cols = any(_determine_key_type(cols) == 'str' 320 for cols in self._columns) 321 if hasattr(X, 'columns'):D:\Anaconda\lib\site-packages\sklearn\compose\_column_transformer.py in <genexpr>(.0) 317 318 # Make it possible to check for reordered named columns on transform--> 319 self._has_str_cols = any(_determine_key_type(cols) == 'str' 320 for cols in self._columns) 321 if hasattr(X, 'columns'):D:\Anaconda\lib\site-packages\sklearn\utils\__init__.py in _determine_key_type(key, accept_slice) 256 return key_stop_type 257 if isinstance(key, (list, tuple)):--> 258 unique_key = set(key) 259 key_type = {_determine_key_type(elt) for elt in unique_key} 260 if not key_type:D:\Anaconda\lib\site-packages\pandas\core\indexes\base.py in __hash__(self) 3905 3906 def __hash__(self):-> 3907 raise TypeError(f"unhashable type: {repr(type(self).__name__)}") 3908 3909 def __setitem__(self, key, value):TypeError: unhashable type: 'Index'
再次尝试对仅8个分类变量使用OneHot编码,并对一些行样本使用fit_transform,它被逆变换回原始状态。因此,对于值为字母的分类变量,它工作得很好。由于X8之后的其他列已经直接以0和1的形式存在,因此直接传递给转换器。
当我尝试对整个数据集X使用OHE并传递给线性回归时,在以下过程中出现了错误
ohe=OneHotEncoder()X_train_transformed=ohe.fit_transform(X_train)ohe.categories_array(['a', 'b', 'c', 'd', 'e', 'f', 'g'], dtype=object), array(['a', 'b', 'c', 'd'], dtype=object), array(['aa', 'ab', 'ac', 'ad', 'ae', 'af', 'ag', 'ah', 'c', 'd', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 'v', 'w', 'x', 'y'], dtype=object), array(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'], dtype=object), array(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y'], dtype=object), array([0, 1], dtype=int64), array([0], dtype=int64), array([0, 1], dtype=int64), array([0, 1], dtype=int64), array([0, 1], dtype=int64), array([0, 1], dtype=int64), array([0, 1], dtype=int64),linereg=LinearRegression()linereg.fit(X_train_transformed,y_train)X_test_transformed=ohe.fit_transform(X_test)X_train_transformed.shape(2946, 906)X_test_transformed.shape(1263, 872)linereg.predict(X_test_transformed)ValueError: dimension mismatch
不确定为什么训练和测试的维度会被转换。
感谢您的帮助来解决这些问题
回答:
对于您的第一个问题,我认为它来自于列转换器的声明。当您提供转换器应该操作的列时,您以列表的列表形式提供它们(通过在[cat_cols]
中使用[]
)。我在自己这边进行了一个测试,移除[]
解决了我的问题,如下所示:
ct = make_column_transformer((OneHotEncoder(), cat_cols), remainder = 'passthrough')
关于您的第二个问题,我认为测试数据和训练数据的维度不同是因为您在转换之前对测试数据进行了拟合。测试数据应该只被转换而不被拟合,如下所示:
X_test_transformed = ohe.transform(X_test)
当您在测试数据上再次拟合转换器时,我认为在您的情况下发生的是测试数据中的某些分类列包含的组别比训练数据少,因此一些虚拟列不会被创建,这使得转换后的测试数据的列数少于转换后的训练数据的列数。