Machine learning 如何";记住;培训后实际预测的分类编码?

Machine learning 如何";记住;培训后实际预测的分类编码?,machine-learning,keras,Machine Learning,Keras,假设想要在包含一些分类参数的数据集上训练机器学习算法。(对机器学习来说是新事物,但我的想法是…)即使将所有分类数据转换为1-hot编码向量,在训练后如何“记住”这个编码映射 例如,在训练之前,将初始数据集转换为使用1-hot编码 universe of categories for some column c is {"good","bad","ok"}, so convert rows to [1, 2, "good"] ---> [1, 2, [1, 0, 0]], [3, 4, "b

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

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

universe of categories for some column c is {"good","bad","ok"}, so convert rows to
[1, 2, "good"] ---> [1, 2, [1, 0, 0]],
[3, 4, "bad"]  ---> [3, 4, [0, 1, 0]],
... 
,在训练模型后,所有未来的预测输入都需要对c列使用相同的编码方案

那么,在未来的预测过程中,数据输入将如何记住该映射(其中“良好”映射到指数0等)(特别是在计划使用
keras
RNN或LSTM模型时)?我是否需要将它保存在某个地方(例如python pickle)(如果需要,如何获得显式映射)?或者有没有一种方法可以让模型在内部自动处理分类输入,以便在培训和将来使用时只输入原始标签数据

如果这个问题中有任何东西显示出我对某事的严重困惑,请让我知道(同样,对ML来说是非常陌生的)


**我不确定这是否属于,但发布在这里,因为我特别想知道如何处理此问题的实际代码实现。

我的想法是在培训/测试数据集D上执行类似的操作(使用python和普通psudo代码的混合):

  • 做点像
  • #Before: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\u indexer=StringIndexer(inputCol=“cat\u col\u i”,outputCol=“cat\u col\u i\u index”).fit(D)
    D=标签索引器。转换(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,…}
    
    对于所有分类列

  • 然后,为D中的所有这些分类名称和索引列创建一个表单映射
  • map={}
    对于D中的所有分类列名colname:
    映射[colname]=[]
    #为所有的所有分类值创建映射dict
    #看https://spark.apache.org/docs/latest/sql-programming-guide.html#untyped-数据集操作也称为数据帧操作
    对于D.select(colname,'%s_索引'%colname')中的所有行r.drop_duplicates():
    enc_from=r['%s'%colname]
    enc_to=r['%s_索引'%colname]
    映射[colname]。追加((enc_-from,enc_-to))
    #对于以后可能出现但尚未见到的猫
    #(IDK如果这是最佳实践,可能是另一种方式,请参阅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对:对[1])
    
    以这样的方式结束

        {
            'cat_col_1': [('orig_label_11', 0), ('orig_label_12', 1), ...],
            'cat_col_2': [(), (), ...],
            ...
            'cat_col_n': [(orig_label_n1, 0), ...]
        }
    
    然后可用于为任何后续数据样本行ds中的每个分类列生成1个热编码向量。例如

    对于ColdS中的所有分类列名:
    enc_from=ds[colname]
    #为类别的1-hot设置零向量
    col_onehot=零。(大小=映射[colname].len)
    对于标签,映射[colname]中的索引:
    如果(标签==enc_from):
    col_onehot[索引]=1
    #在样本中为1-热向量创建新列
    ds['%s\u onehot'%colname]=col\u onehot
    打破
    
  • 然后可以将此结构保存为pickle
    pickle.dump(map,open(“cats_map.pkl”,“wb”))
    ,以便在以后进行实际预测时与分类列值进行比较

  • **可能有更好的方法,但我认为需要更好地理解本文()。如果有任何问题,将更新答案。

    我一直在做的是:

    使用StringIndexer.fit()后,可以保存其元数据(包括实际的编码器映射,如“good”作为第一列)

    以下是我使用的代码(使用java,但可以调整为python):

    稍后,在尝试对新数据集进行预测时,可以加载存储的元数据:

    StringIndexerModel sim = StringIndexerModel.load("IndexMappingModels/" + field + "_INDEX");
    
    dataset = sim.transform(dataset);
    

    我想您已经解决了这个问题,因为它是在2018年发布的,但我在其他任何地方都没有找到这个解决方案,所以我相信它值得分享。

    记住这个映射,并在将来使用它predictions@rvinas我打算这么做。Jut希望确保不会错过其他最佳实践方法。我已经提供了我自己对我计划做的草案的答案。如果那里的基本策略有什么问题,请告诉我。
    StringIndexerModel sim = StringIndexerModel.load("IndexMappingModels/" + field + "_INDEX");
    
    dataset = sim.transform(dataset);