当使用Keras时,验证集中的未见类别给出了错误信息。

问题描述 投票:0回答:1

我有一个由数字变量和分类变量组成的数据,其中分类变量有很多类别,所以我使用Embeddings来表示这些数据。分类变量有很多类别,所以我使用Embeddings来表示这些。我的模型是一个简单的神经网络.我知道当你定义Embedding层时,你需要通过 input_dim=number of categories + 1 以便说明未见过的培训类别。这就是我所做的。另外,在将这些类别编码为数值以便输入神经网络时,我做了以下工作。1. 枚举所有的唯一值,在 训练集 并将它们放入一个字典中。同时保存一个名为 num_values 即唯一的类别数+1.2。对于验证集,如果该值不在字典中,那么我给它的值为 num_values.

这就带来了一个问题,因为当我想评估模型时(使用 model.predict())我得到一个错误,比如

tensorflow.python.framework.errors_impl.InvalidArgumentError: indices[0,0] = 118752 is not in [0, 118752)

这是因为我在某个变量的验证集中有一个未见过的类别,而它被映射到了 num_valuesnum_values 从未被分配到训练集中的任何类别中去 因为字典的建立发生在训练集上。我不知道该如何解决这个问题,我使用的是Keras 2.3.1和Tensorflow 1.13.1。

我使用的是Keras 2.3.1和Tensorflow 1.13.1。

相关代码。

class EmbeddingMapping:
    """
    An instance of this class should be defined
    for each categorical variable you want to use.
    """
    def __init__(self, series: pd.Series) -> None:
        # get a list of unique values
        values = series.unique().tolist()

        # dictionary mapping
        self.embedding_dict: Dict[str, int] = {value: int_value + 1 for int_value, value in enumerate(values)}
        self.num_values: int = len(values) + 1  # +1 for unknown categories

    def get_mapping(self, value: str) -> int:
        # return value if it was seen in training
        if value in self.embedding_dict:
            return self.embedding_dict[value]
        # else return num_values which is the same for all
        # unseen values
        else:
            return self.num_values


# build mappings
res_dict_train: Dict[str, EmbeddingMapping] = {}
res_dict_val: Dict[str, EmbeddingMapping] = {}
for var in categorical_features:
    embd_train = EmbeddingMapping(X_train_categorical[var])


    temp_series_train = X_train_categorical[var].apply(embd_train.get_mapping)
    temp_series_val = X_val_categorical[var].apply(embd_train.get_mapping)

    res_dict_train[var] = temp_series_train
    res_dict_val[var] = temp_series_val

X_train_categorical = X_train_categorical.assign(**res_dict_train)
X_val_categorical = X_val_categorical.assign(**res_dict_val)

# Keras
# Categorical vars
models_lst = []
inputs = []
for cat_feature in categorical_features:
    print('---------------------------------------')
    print(f'Info for categorical feature {cat_feature}')
    input_i = Input(shape=(1,), dtype='int32')
    inputs.append(input_i)
    num_categories = EmbeddingMapping(X_train_categorical[cat_feature]).num_values
    print(f"Number of categories: {num_categories}")
    embedding_size = min(np.ceil(num_categories/2), 50)     # rule of thumb
    embedding_size = int(embedding_size)
    print(f'Embedding size: {embedding_size}')
    model_i = Embedding(input_dim=num_categories, output_dim=embedding_size, input_length=1, name=f'embedding_{cat_feature}')(input_i)
    model_i2 = Reshape(target_shape=(embedding_size,))(model_i)

    models_lst.append(model_i2)

# layer for numerical
input_numerical = Input(shape=(len(numerical_features),), dtype='float32')
numerical_model = Reshape(target_shape=(2,))(input_numerical)
models_lst.append(numerical_model)
inputs.append(input_numerical)

concatenated = concatenate(models_lst, axis=-1)
mymodel = Dense(50, activation="relu")(concatenated)
mymodel2 = Dense(15, activation="relu")(mymodel)
mymodel3 = Dense(1, activation='sigmoid')(mymodel2)

final_model = models.Model(inputs, mymodel3)

final_model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['acc', 'binary_accuracy'])

final_model.fit(x=train_input_list, validation_data=(val_input_list, y_val), y=y_train, epochs=1, batch_size=128)

当纪元结束,模型试图计算验证统计时,我得到了错误。

python tensorflow keras deep-learning neural-network
1个回答
0
投票

用这一行。

self.embedding_dict: Dict[str, int] = {value: int_value + 1 for int_value, value in enumerate(values)}

你在所有的整数编码上加了+1 所以你把你的值从[0,max_cat]转换到[1,max_cat+1],这是正确的。

但这样做,最好的方式是用0编码未见类别,所以你必须修改。

    def get_mapping(self, value: str) -> int:
        # return value if it was seen in training
        if value in self.embedding_dict:
            return self.embedding_dict[value]
        # else return 0 which is the same for all unseen values
        else:
            return 0

希望这能帮到你

© www.soinside.com 2019 - 2024. All rights reserved.