获取ValueError:y在使用scikit learn的LabelEncoder时包含新标签

时间:2017-09-18 21:32:00

标签: python machine-learning scikit-learn prediction

我有一个类似的系列:

df['ID'] = ['ABC123', 'IDF345', ...]

我正在使用scikit的LabelEncoder将其转换为数字值,以便输入RandomForestClassifier

在培训期间,我的工作如下:

le_id = LabelEncoder()
df['ID'] = le_id.fit_transform(df.ID) 

但是,现在对于测试/预测,当我传入新数据时,我想基于le_id从这些数据转换'ID',即,如果存在相同的值,则根据上面的内容对其进行转换标签编码器,否则分配新的数值。

在测试文件中,我的操作如下:

new_df['ID'] = le_dpid.transform(new_df.ID)

但是,我收到以下错误:ValueError: y contains new labels

我该如何解决这个问题?谢谢!

更新:

所以我的任务是使用下面的(例如)作为训练数据,并预测新的BankNum,ID组合的'High', 'Mod', 'Low'值。模型应该学习给出“高”的特征,其中从训练数据集给出“低”。例如,当存在多个具有相同BankNum和不同ID的条目时,会给出低于'高'。

df = 

BankNum   | ID    | Labels

0098-7772 | AB123 | High
0098-7772 | ED245 | High
0098-7772 | ED343 | High
0870-7771 | ED200 | Mod
0870-7771 | ED100 | Mod
0098-2123 | GH564 | Low

然后用类似的东西预测它:

BankNum   |  ID | 

00982222  | AB999 | 
00982222  | AB999 |
00981111  | AB890 |

我正在做这样的事情:

df['BankNum'] = df.BankNum.astype(np.float128)

    le_id = LabelEncoder()
    df['ID'] = le_id.fit_transform(df.ID)

X_train, X_test, y_train, y_test = train_test_split(df[['BankNum', 'ID'], df.Labels, test_size=0.25, random_state=42)
    clf = RandomForestClassifier(random_state=42, n_estimators=140)
    clf.fit(X_train, y_train)

6 个答案:

答案 0 :(得分:2)

我认为错误信息非常明确:您的测试数据集包含ID标签,这些标签尚未包含在您的训练数据集中。对于此项目,LabelEncoder无法找到合适的数值来表示。有几种方法可以解决这个问题。您可以尝试平衡数据集,以确保每个标签不仅存在于测试中,还存在于训练数据中。否则,您可以尝试遵循提出的一个想法here

其中一种可能的解决方案是,您在开始时搜索数据集,获取所有唯一ID值的列表,在此列表中训练LabelEncoder,并保留剩下的你的代码就像现在一样。

另一种可能的解决方案是,检查测试数据是否只有在培训过程中看到的标签。如果有新标签,则必须将其设置为某些后备值,例如unknown_id(或类似的内容)。在这个问题上,你将所有新的,未知的ID放在一个班级中;对于这些项目,预测将失败,但您可以使用现在的其余代码。

答案 1 :(得分:2)

您可以尝试使用“sklearn.LabelEncoder以前从未见过的值”https://stackoverflow.com/a/48169252/9043549 问题是用类创建字典,而不是映射列,并用一些“已知值”填充新类

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
suf="_le"
col="a"
df[col+suf] = le.fit_transform(df[col])
dic = dict(zip(le.classes_, le.transform(le.classes_)))
col='b'
df[col+suf]=df[col].map(dic).fillna(dic["c"]).astype(int) 

答案 2 :(得分:1)

我希望这对某人有所帮助,因为它是最新的。

sklearn 使用 fit_transform 来执行针对标签编码的拟合函数和变换函数。 要解决 Y 标签因未见过的值而抛出错误的问题,请使用:

return next(filter(lambda x: x.type == 'equity', self.accounts))

这就解决了!

答案 3 :(得分:0)

通过这种方式,您可以在测试/看不见的数据中将所有看不见的标签都映射为0

for feat in ['BankNum', 'ID']:

    lbe = LabelEncoder()
    lbe.fit(X_train[feat].values)
    diz_map_train = dict(zip(lbe.classes_, lbe.transform(lbe.classes_)+1))

    for i in set(X_test[feat]).difference(X_train[feat]):
        diz_map_train[i] = 0

    X_train[feat] = [diz_map_train[i] for i in X_train[feat].values]
    X_test[feat] = [diz_map_train[i] for i in X_test[feat].values]

答案 4 :(得分:0)

在处理DataFrames时,我能够在心理上更好地处理操作。下面的方法使用训练数据拟合LabelEncoder()并将其转换,然后使用一系列pd.merge联接将训练后的拟合/转换编码器值映射到测试数据。当训练数据中没有看到测试数据值时,代码默认为最大训练编码器值+ 1。

# encode class values as integers
import numpy as np
import pandas as pd
from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
encoder.fit(y_train)
encoded_y_train = encoder.transform(y_train)

# make a dataframe of the unique train values and their corresponding encoded integers
y_map = pd.DataFrame({'y_train': y_train, 'encoded_y_train': encoded_y_train})
y_map = y_map.drop_duplicates()

# map the unique test values to the trained encoded integers
y_test_df = pd.DataFrame({'y_test': y_test})
y_test_unique = y_test_df.drop_duplicates()
y_join = pd.merge(y_test_unique, y_map, 
                  left_on = 'y_test', right_on = 'y_train', 
                  how = 'left')

# if the test category is not found in the training category group, then make the 
# value the maximum value of the training group + 1                  
y_join['encoded_y_test'] = np.where(y_join['encoded_y_train'].isnull(), 
                                    y_map.shape[0] + 1, 
                                    y_join['encoded_y_train']).astype('int')

encoded_y_test = pd.merge(y_test_df, y_join, on = 'y_test', how = 'left') \
    .encoded_y_test.values

答案 5 :(得分:-4)

我用过

       le.fit_transform(Col) 

,我得以解决此问题。它确实适合并变换了两者。我们不必担心测试拆分中的未知值