我正在处理一个仅包含类别特征的数据框。为了重现我遇到的问题,我将创建以下示例:
d = {'col1':['a','b','c','a','c','c','c','c','c','c'], 'col2':['a1','b1','c1','a1','c1','c1','c1','c1','c1','c1'], 'col3':[1,2,3,2,3,3,3,3,3,3]}data = pd.DataFrame(d)
我将数据分为测试集和训练集,并将col3设为我的目标特征。
train_data, test_data = train_test_split(data, test_size=0.2)train_data = train_data.reset_index(drop=True)test_data = test_data.reset_index(drop=True)X_train = train_data.drop(['col3'], axis = 1)X_test = test_data.drop(['col3'], axis = 1)y_train = train_data["col3"]y_test = test_data["col3"]
在X_train中,col1和col2是我的类别特征,因此索引为0和1,所以我使用SMOTE-NC如下:
from imblearn.over_sampling import SMOTENCcat_indx =[0,1]sm = SMOTENC(categorical_features= cat_indx, random_state=0)X_train_res, y_train_res = sm.fit_resample(X_train, y_train)
对此我得到了以下错误:
ValueError: SMOTE-NC is not designed to work only with categorical features. It requires some numerical features.
考虑到SMOTE-NC旨在处理类别变量,我很好奇如何解决这个问题?另外请注意,我的目标变量是多类的而不是二元的,我认为这在当前阶段不会造成任何问题。
回答:
请注意,算法名称中的NC首字母代表的是名义-连续;正如错误消息明确指出的那样,该算法不设计用于仅处理类别(名义)特征的情况。
要了解为什么会这样,您需要深入研究一下原始的SMOTE论文;引用相关部分(强调部分为我所加):
虽然我们当前的SMOTE方法不处理全部为名义特征的数据集,但它被推广到处理混合数据集,即连续和名义特征。我们称这种方法为Synthetic Minority Over-sampling TEchnique-Nominal Continuous [SMOTE-NC]。我们在UCI存储库的Adult数据集上测试了这种方法。SMOTE-NC算法描述如下。
- 中位数计算:计算少数类所有连续特征标准差的中位数。如果样本与其潜在最近邻之间的名义特征不同,则将此中位数包含在欧几里得距离计算中。我们使用中位数来根据连续特征值的典型差异来惩罚名义特征的差异。
- 最近邻计算:使用连续特征空间计算要识别k最近邻的特征向量(少数类样本)与其他特征向量(少数类样本)之间的欧几里得距离。对于所考虑的特征向量与其潜在最近邻之间每个不同的名义特征,将之前计算的标准差中位数包含在欧几里得距离计算中。
因此,很明显,为了使算法正常工作,它需要至少一个连续特征。在这种情况下并非如此,所以算法在第一步(中位数计算)时相当意外地失败了,因为没有可用于中位数计算的连续特征。