【问题标题】:How to handle correctly sparse features to avoid poor performance of classification neural network?如何正确处理稀疏特征以避免分类神经网络性能不佳?
【发布时间】:2021-06-13 14:01:17
【问题描述】:

我试图了解稀疏神经网络的工作原理。我有两个类的大约 40k 行的非常稀疏的数据。数据集如下所示:

    RA0 RA1 RA2 RA3 RA4 RA5 RA6 RA7 RA8 RA9 RB0 RB1 RB2 RB3 RB4 RB5 RB6 RB7 RB8 RB9
50  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
51  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
52  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
53  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
54  0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
55  1.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
56  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
57  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
58  1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
59  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
60  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
61  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
62  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
63  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0

如您所见,有些行上只有 0。名称为RA 的列是class 0 的特征,名称为RB 的列是class 1 的特征,因此与实际labels 相同的数据集如下所示:

    RA0 RA1 RA2 RA3 RA4 RA5 RA6 RA7 RA8 RA9 ... RB1 RB2 RB3 RB4 RB5 RB6 RB7 RB8 RB9 label
50  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
51  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
52  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0
53  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0
54  0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0
55  1.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
56  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
57  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0
58  1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
59  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
60  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0

我使用Keras 做了一个简单的神经网络模型,但该模型没有学习,而且在训练数据集上的准确率很少超过 52%。我尝试了同一模型的两种变体:

变体 1:

def build_nn(n_features,lr = 0.001):
    _input = Input(shape = (n_features,),name = 'input',sparse = True)
    x = Dense(12,kernel_initializer = 'he_uniform',activation = 'relu')(_input)
    x = Dropout(0.5)(x)
    x = Dense(8,kernel_initializer = 'he_uniform',activation = 'relu')(x)
    x = Dropout(0.5)(x)
    x = Dense(2,kernel_initializer = 'he_uniform',activation = 'softmax')(x)
    nn = Model(inputs = [_input],outputs = [x])
    nn.compile(loss='sparse_categorical_crossentropy',optimizer=Adam(lr = lr),metrics=['accuracy'])
    return nn

变体 2:

def build_nn(feature_layer,lr = 0.001):
    feature_inputs = {}
    for feature in feature_layer:
        feature_inputs[feature.key] = Input(shape = (1,),name = feature.key)
    feature_layer = tf.keras.layers.DenseFeatures(feature_layer)
    feature_inputs_n = feature_layer(feature_inputs)
    x = Dense(12,kernel_initializer = 'he_uniform',activation = 'relu')(feature_inputs_n)
    x = Dropout(0.5)(x)
    x = Dense(8,kernel_initializer = 'he_uniform',activation = 'relu')(x)
    x = Dropout(0.5)(x)
    x = Dense(2,kernel_initializer = 'he_uniform',activation = 'softmax')(x)
    nn = Model(inputs = [v for v in feature_inputs.values()],outputs = [x])
    nn.compile(loss='sparse_categorical_crossentropy',optimizer=Adam(lr = lr),metrics=['accuracy'])
    return nn

做变体2的动机是因为特征稀疏,我认为这可能会对模型的性能产生影响,所以我关注了this tensorflow guide

此外,使用 keras api 提供的to_categorical 函数将标签转换为分类标签:

y_train2 = to_categorical(y_train)
y_test2 = to_categorical(y_test)

我的问题是:

  1. 我的模型是否错误(尤其是变体 2)或者我对稀疏特征的表示错误以及应该如何处理这些特征?

  2. RARB 是两个不同类的特征,由于有行全为 0,我应该添加代表未知类的第三个类还是删除仅包含 0 的行?

  3. 既然RARB 映射了两个不同的类,我应该做两个单独的模型,一个用于列RA 和类0,另一个用于列RB 和类1?

我还发布了训练/测试模型准确性的图片:

如果需要,我还可以提供代码的任何其他部分。

编辑: 我没有放这部分,因为我觉得它与我所要求的没有关系,但似乎我错了。

每个特征都是 sklearn 决策树的一个单独分支。 decision tree 查找的类别是交易环境中下一根蜡烛的上涨或下跌(蜡烛是具有开盘价、最低价、最高价和收盘价的时间工具的价格聚合)。然后,想法是抓取那些在价格时间序列中被评估的分支,并评估是否满足条件,因此如果分支处于活动状态,则值为 1。

例如,索引 55 处的分支 RA0 处于活动状态,因此值为 1。标签计算为np.sign(close - open)。因此,我们的想法是,通过使用多个分支,可以改进标签的分类,通过神经网络可以查看哪个分支是否处于活动状态以及哪个分支具有更大的权重以便进行分类。

【问题讨论】:

    标签: python-3.x tensorflow keras neural-network sparse-matrix


    【解决方案1】:

    这里使用sparse_categorical_crossentropy是错误的; sparse_categorical_crossentropy 中的稀疏性指的是标签表示,而不是特征。由于您使用的是 one-hot 编码标签:

    y_train2 = to_categorical(y_train)
    y_test2 = to_categorical(y_test)
    

    最后一层有activation = 'softmax' 的 2 个节点(我认为这意味着你只有 2 个类),你应该切换到loss='categorical_crossentropy',而不管你的功能的稀疏性 .

    其他一般性说明:

    • 移除 dropout,默认情况下应该从不使用。 Dropout 用于帮助防止过度拟合 if 检测到这样的事情;不加批判地使用(更糟糕的是,具有如此高的值),众所周知的是完全阻止训练(即与您在此处报告的内容非常相似)。

    • 从所有层中删除kernel_initializer = 'he_uniform',从而留下default glorot_uniform 一个(有用的提示:默认值的存在是有原因的,不建议使用它们,除非您有一个特定的理由这样做,并且您确切地知道自己在做什么)。

    【讨论】:

    • 感谢您的回答。我会尝试你的建议。关于训练数据,我应该删除所有只有 0 个值的行吗?
    • @xerac 很难说没有问题上下文(以及这些行的 标签)。
    • 每个特征都是从决策树中提取的一个分支的结果。因此,基本上在计算特征时,它类似于data['RA0'] = eval(branch[0])(决策树的分支存储为字符串)。所有分支都与 0 类或 1 类相关(RA 与 0 类相关,RB 与 1 类相关)。问题是单独的每个分支都有些好,但我的目标是也许某些分支与其他分支结合起来比单独的分支更好。
    • @xerac 这一切在您的脑海中可能听起来很清楚,但相信我,在其他任何人的脑海中(包括我的)听起来都不是这样。另外,如果认为此类信息对问题有用,则应成为问题的一部分,而不是评论。在 SO,我们可以帮助您解决问题的 编程 方面,但关于您的具体问题上下文(如前所述,标签 呢?)和数据(其中我们没有),你或多或少靠自己,实验为王。
    • 我明白在我的脑海中它是“清晰的”。为了提供上下文,我添加了一个编辑,解释了这些功能的来源和预期用途。
    猜你喜欢
    • 2018-04-03
    • 2018-07-21
    • 2018-10-22
    • 2016-08-03
    • 1970-01-01
    • 1970-01-01
    • 2018-07-08
    • 2021-12-16
    • 2017-02-20
    相关资源
    最近更新 更多