如何对类别数组进行编码以输入 sklearn

数据挖掘 scikit-学习 推荐系统 词嵌入 嵌入
2022-02-28 20:05:41

我正在研究一个推荐问题,大致遵循他们的Youtube 论文他们的代理问题是推荐用户将观看的​​下一个视频。他们在模型中包含的一个功能是表示观看历史记录(即用户观看了哪些视频),他们通过嵌入视频 ID 然后对该嵌入进行平均来实现这一点。

所以对于数据,他们可能...

[
    [1234, 5678, 9012],
    [1234],
    [9012, 1234, 8245],
]

并且这些 ID 中的每一个都嵌入到 8 个特征中,这 8 个特征对训练数据中的每个观察值进行平均,这 8 个平均特征输入到网络的深层。

tf.keras.preprocessing.sequence.pad_sequences现在我可以使用plusEmbedding()的组合在 keras 中复制它GlobalAveragePooling1D(),并且效果相当好。我的问题是我想评估其他算法来解决同样的问题(毕竟,我的数据比 Youtube 少得多,所以我不确定我是否需要一个 NN)。我无法真正概念化如何处理这种历史“手表”的编码,尽管它可以在更传统的算法(如 sklearn 中的 XGBoost 或 RandomForests)中工作。Ordinal Encoding 和取平均值看起来很傻,我显然不能 OneHot 编码第 1 到第 n 个视频观看等等。任何有关如何解决此问题的想法将不胜感激。

编辑:

我想可能的FeatureHasher符合要求?它不是一个平均值,而是生成每个散列输入类别的总和。这仍然(默认情况下)会导致成千上万的功能,所以我不确定它是否会比 OneHotEncoding 有重大改进!

编辑2:

或者,也许我可以通过将类别数组连接成单个字符串并使用 CountVectorizer 创建一个 (n_samples, n_categories) 数组,然后使用TruncatedSVD将其减少到更易于管理的组件数量,将其视为文本嵌入问题。

我想我有几个想法,有人知道它们是否值得一试吗?

2个回答

如果手表序列有意义,那么您确实需要某种分类器来从手表序列中创建用户/项目嵌入,因此您可能正在研究 GRU 和 LSTM。神经网络本身并不过分。这是对该主题的一个很好的处理:https ://towardsdatascience.com/introduction-to-recommender-system-part-2-adoption-of-neural-network-831972c4cbf7

然而,上面这个简单的方法确实意味着你有一个具有很多维度的多标签类。这可能很难扩展,如果没有大量数据,可能无法很好地训练。特征散列在输出中没有太大帮助,因为您需要将每个映射回正确的视频

如果你愿意放弃这个序列,除了简单的新近度(最近的手表更重要)之外,它通常不会携带太多信息是的,处理这个问题的常用方法是一个巨大的矩阵分解问题。稀疏 SVD 是可能的,但可能有点矫枉过正;ALS 更简单且几乎同样有效,并且适用于您在此处的隐式输入。您可以轻松地为带有 ALS 的手表添加重量,这可以用来减轻旧手表的重要性。

所以最后我把这个作为一个潜在的语义分析问题来处理,将类别描述数组连接成一个长字符串,然后通过 sklearn 的TfIdfTransformerTruncatedSVD传递它。虽然我已经构建的神经网络优于我尝试过的任何 sklearn 算法,但效果很好。