假设需要在包含某些分类参数的数据集上训练机器学习算法。(刚开始机器学习,但我的想法是.)即使将所有的分类数据转换为1热编码的向量,训练后如何“记住”这个编码地图?
例如:在训练前将初始数据集转换为使用1-热编码,例如
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模型时)?我需要把它保存在某个地方吗?(如果是,我如何获得显式映射)?或者有一种方法可以让模型在内部自动处理分类输入,这样就可以在培训和将来使用期间输入原始标签数据了吗?
如果这个问题中有任何东西表明我对某件事有任何严重的混淆,请告诉我(同样,对于ML非常陌生)。
**不确定这是否属于https://stats.stackexchange.com/,但在这里张贴,因为它特别想知道如何处理这个问题的实际代码实现。
发布于 2018-07-27 00:09:44
我的想法是在培训/测试dataset D上执行类似的操作(使用python和普通psudo代码的混合):
# Before: D.schema == {num_col_1: int, cat_col_1: str, cat_col_2: str, ...}
# assign unique index for each distinct label for categorical column annd store in a new column
# 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)
# After: D.schema == {num_col_1: int, cat_col_1: str, cat_col_2: str, ..., cat_col_1_index: int, cat_col_2_index: int, ...}
对于所有的分类列
map = {}
for all categorical column names colname in D:
map[colname] = []
# create mapping dict for all categorical values for all
# see 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))
# for cats that may appear later that have yet to be seen
# (IDK if this is best practice, may be another way, see 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))
# sort by index encoding
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热编码向量。例如:
for all categorical column names colname in ds:
enc_from = ds[colname]
# make zero vector for 1-hot for category
col_onehot = zeros.(size = map[colname].len)
for label, index in map[colname]:
if (label == enc_from):
col_onehot[index] = 1
# make new column in sample for 1-hot vector
ds['%s_onehot' % colname] = col_onehot
break
pickle.dump( map, open( "cats_map.pkl", "wb" ) )
,以便在以后进行实际预测时与分类列值进行比较。**可能有更好的方法,但我认为需要更好地理解这篇文章(https://medium.com/@satnalikamayank12/on-learning-embeddings-for-categorical-data-using-keras-165ff2773fc9)。如果有什么新的答案。
发布于 2021-03-03 05:18:39
我一直在做的是:
在使用StringIndexer.fit()之后,可以保存它的元数据(包括实际的编码器映射,比如"good“是第一列)
下面是我使用的代码(使用java,但可以调整为python):
StringIndexerModel sim = new StringIndexer()
.setInputCol(field)
.setOutputCol(field + "_INDEX")
.setHandleInvalid("skip")
.fit(dataset);
sim.write().overwrite().save("IndexMappingModels/" + field + "_INDEX");
稍后,在尝试对新数据集进行预测时,可以加载存储的元数据:
StringIndexerModel sim = StringIndexerModel.load("IndexMappingModels/" + field + "_INDEX");
dataset = sim.transform(dataset);
我想你已经解决了这个问题,自从2018年发布以来,但是我没有在其他地方找到这个解决方案,所以我相信它值得分享。
https://stackoverflow.com/questions/51548041
复制相似问题