如何在训练后为实际预测“记住”分类编码?

假设想要在一个包含一些分类参数的数据集上训练机器学习算法。(刚接触机器学习,我的想法是……)即使将所有分类数据转换为1-hot编码向量,这种编码映射在训练后如何被“记住”呢?

例如,在训练前将初始数据集转换为使用1-hot编码,假设

某列c的类别宇宙是{"good","bad","ok"},所以将行转换为[1, 2, "good"] ---> [1, 2, [1, 0, 0]],[3, 4, "bad"]  ---> [3, 4, [0, 1, 0]],... 

在训练模型后,所有未来的预测输入都需要对列c使用相同的编码方案。

那么在未来的预测中,数据输入如何记住这种映射(例如,“good”映射到索引0,等等)?(特别是,当计划使用keras的RNN或LSTM模型时)我需要将它保存到某个地方吗(例如,python pickle)(如果是的话,我如何获得明确的映射)?或者有没有一种方法让模型自动处理分类输入,从而在训练和未来使用时只需输入原始标签数据?

如果这个问题中的任何内容显示了我对某事的严重困惑,请告诉我(再次强调,我对ML非常新手)。

** 我不确定这是否应该发布在https://stats.stackexchange.com/,但在这里发布是因为特别想知道如何处理此问题的实际代码实现。


回答:

我的想法是对训练/测试数据集D做类似的事情(使用Python和伪代码的混合):

  1. 做类似的事情
    # 之前:D.schema == {num_col_1: int, cat_col_1: str, cat_col_2: str, ...}    # 为每个分类列的不同标签分配唯一索引,并存储在一个新列中    # http://spark.apache.org/docs/latest/ml-features.html#stringindexer    label_indexer = StringIndexer(inputCol="cat_col_i", outputCol="cat_col_i_index").fit(D)    D = label_indexer.transform(D)    # 之后:D.schema == {num_col_1: int, cat_col_1: str, cat_col_2: str, ..., cat_col_1_index: int, cat_col_2_index: int, ...}

对所有分类列进行操作

  1. 然后对D中所有这些分类名称和索引列,创建以下形式的映射
    map = {}    for all categorical column names colname in D:        map[colname] = []        # 为所有分类值创建映射字典        # 见 https://spark.apache.org/docs/latest/sql-programming-guide.html#untyped-dataset-operations-aka-dataframe-operations        for all rows r in D.select(colname, '%s_index' % colname).drop_duplicates():            enc_from = r['%s' % colname]            enc_to = r['%s_index' % colname]            map[colname].append((enc_from, enc_to))        # 为可能稍后出现的尚未见过的分类        # (不知道这是不是最佳实践,可能有其他方法,参见 https://medium.com/@vaibhavshukla182/how-to-solve-mismatch-in-train-and-test-set-after-categorical-encoding-8320ed03552f)        map[colname].append(('NOVEL_CAT', map[colname].len))        # 按索引编码排序        map[colname].sort(key = lamdba pair: pair[1])    

最终得到类似于下面的结果

    {        'cat_col_1': [('orig_label_11', 0), ('orig_label_12', 1), ...],        'cat_col_2': [(), (), ...],        ...        'cat_col_n': [(orig_label_n1, 0), ...]    }

然后可以使用它为任何后续数据样本行ds中的每个分类列生成1-hot编码向量。例如

    for all categorical column names colname in ds:        enc_from = ds[colname]        # 为分类创建零向量以进行1-hot编码         col_onehot = zeros.(size = map[colname].len)        for label, index in map[colname]:            if (label == enc_from):                col_onehot[index] = 1                # 在样本中为1-hot向量创建新列                ds['%s_onehot' % colname] = col_onehot                break
  1. 然后可以将这个结构保存为pickle pickle.dump( map, open( "cats_map.pkl", "wb" ) ),以便在稍后进行实际预测时与分类列的值进行比较。

** 可能有更好的方法,但我认为需要更好地理解这篇文章(https://medium.com/@satnalikamayank12/on-learning-embeddings-for-categorical-data-using-keras-165ff2773fc9)。如果有任何更新,我会更新答案。

Related Posts

Keras Dense层输入未被展平

这是我的测试代码: from keras import…

无法将分类变量输入随机森林

我有10个分类变量和3个数值变量。我在分割后直接将它们…

如何在Keras中对每个输出应用Sigmoid函数?

这是我代码的一部分。 model = Sequenti…

如何选择类概率的最佳阈值?

我的神经网络输出是一个用于多标签分类的预测类概率表: …

在Keras中使用深度学习得到不同的结果

我按照一个教程使用Keras中的深度神经网络进行文本分…

‘MatMul’操作的输入’b’类型为float32,与参数’a’的类型float64不匹配

我写了一个简单的TensorFlow代码,但不断遇到T…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注