Python 从scikit学习随机森林的混淆概率

Python 从scikit学习随机森林的混淆概率,python,scikit-learn,random-forest,Python,Scikit Learn,Random Forest,我有一个整数值的时间序列,我正试图预测它。我通过一个滑动窗口来实现这一点,在这个窗口中,它学会关联99个值来预测下一个值。这些值介于0和128之间。X的表示是一个由99个长度的n个滑动窗口组成的立方体,每个整数编码为128个元素的一个热编码向量。这个数组的形状是(n,99128)。Y的形状是(n,128)。我认为这是一个多类问题,因为Y可以精确地得出一个结果 这对Keras/Tensorflow很有效,但当我尝试使用scikit learn中的RandomForest时,它会抱怨输入向量是3D而

我有一个整数值的时间序列,我正试图预测它。我通过一个滑动窗口来实现这一点,在这个窗口中,它学会关联99个值来预测下一个值。这些值介于0和128之间。X的表示是一个由99个长度的n个滑动窗口组成的立方体,每个整数编码为128个元素的一个热编码向量。这个数组的形状是(n,99128)。Y的形状是(n,128)。我认为这是一个多类问题,因为Y可以精确地得出一个结果

这对Keras/Tensorflow很有效,但当我尝试使用scikit learn中的RandomForest时,它会抱怨输入向量是3D而不是2D。因此,我将输入立方体X重塑为二维形状矩阵(n,99*128)。结果不是很好,为了了解发生了什么,我要求提供概率(见下面的代码)

我从
predict\u proba
得到的输出是:

[array([[0.841, 0.159]]), array([[1.]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), 
 array([[1.]]), array([[1., 0.]]), array([[1., 0.]]), array([[1., 0.]]),
 array([[1., 0.]]), array([[1., 0.]]), array([[0.995, 0.005]]), array([[0.999,
 0.001]]), array([[0.994, 0.006]]), array([[1., 0.]]), array([[0.994, 0.006]]),
 array([[0.977, 0.023]]), array([[0.999, 0.001]]), array([[0.939, 0.061]]),
 array([[0.997, 0.003]]), array([[0.969, 0.031]]), array([[0.997, 0.003]]),
 array([[0.984, 0.016]]), array([[0.949, 0.051]]), array([[1., 0.]]),
 array([[0.95, 0.05]]), array([[1., 0.]]), array([[0.918, 0.082]]), 
 array([[0.887, 0.113]]), array([[1.]]), array([[0.88, 0.12]]), array([[1.]]),
 array([[0.884, 0.116]]), array([[0.941, 0.059]]), array([[1.]]), array([[0.941,
 0.059]]), array([[1.]]), array([[0.965, 0.035]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]]),
 array([[1.]]), array([[1.]]), array([[1.]]), array([[1.]])]
输出向量的长度是128,但为什么它由一个列表组成,包含2D数组,有时包含一个元素,有时包含两个元素?据我所知,数组应该返回维度#samples*#类,在我的shape示例(1128)中也是如此

有人能帮我指出我做错了什么吗

编辑1

我按照@Vivek Kumar(谢谢Vivek)在评论中提出的思路做了实验。我输入整数序列(X)并将其与序列(y)中的下一个整数匹配。代码如下:

def rff(X_train, Y_train, X_val, Y_val, samples, cont=False):
    print('Input data:', X_train.shape, Y_train.shape, X_val.shape, Y_val.shape)
    clf = RandomForestClassifier(n_estimators=64, n_jobs=-1)
    clf.fit(X_train, Y_train)
    score = clf.score(X_val, Y_val)

    y_true = Y_val
    y_prob = clf.predict_proba(X_val)
    y_hat = clf.predict(X_val)
    print('y_true', y_true.shape, y_true)
    print('y_prob', y_prob.shape, y_prob)
    print('y_hat', y_hat.shape, y_hat)
    #sum_prob = np.sum(y_true == y_prob)
    sum_hat = np.sum(y_true == y_hat)
    print('Score of randomforest =', score)
    print('Score y_hat', sum_hat / len(X_val))
    #print('Score y_prob', sum_prob / len(X_val))

    # compute some individual samples
    for i in range(samples):
        index = random.randrange(0, len(X_val) - 1)
        y_true_i = Y_val[index]
        #y_prob_i = y_prob[index]
        y_hat_i = y_hat[index]
        print('{:4d} - {:3d}{:3d}'.format(index, y_true_i, y_hat_i))
其输出为:

Input data: (4272, 99) (4272,) (1257, 99) (1257,)
y_true (1257,) [ 0  0  0 ... 69 70 70]
y_prob (1257, 29) [[0.09375  0.       0.       ... 0.078125 0.078125 0.015625]
 [0.109375 0.       0.       ... 0.046875 0.0625   0.0625  ]
 [0.125    0.       0.       ... 0.015625 0.078125 0.015625]
 ...
 [0.078125 0.       0.       ... 0.       0.       0.      ]
 [0.046875 0.       0.       ... 0.       0.       0.      ]
 [0.078125 0.       0.       ... 0.       0.       0.      ]]
y_hat (1257,) [81 81 79 ... 67 67 65]
Score of randomforest = 0.20047732696897375
Score y_hat 0.20047732696897375
 228 -  76 77
  51 -  76  0
 563 -  81  0
 501 -   0 77
 457 -  79 79
 285 -  76 77
 209 -  81  0
1116 -  79  0
 178 -  72 77
1209 -  67 65
概率数组具有一致的大小,但其形状完全奇怪(128,29)。这29是从哪里来的。。。?然而,报告也有一些改进:准确性大大提高。过去是0.0015左右,现在是0.20左右

关于概率数组代表什么有什么想法吗

编辑2

我的错误是,通过从128个热编码值返回到整数,我没有考虑到我只有29个唯一值
predict_proba
巧妙地预测了这29个值,因为这是它学到的

剩下的唯一问题是概率预测了哪些值?让我们假设要预测的类是0,101-128,
predict\u proba
返回索引0..28的值。概率到类的映射是什么:0-->0,1-->101,2-->102,29-128? 我在手册中找不到任何关于这方面的提示

首先,让我们谈谈您的目标
y
  • 二维
    y
    被视为标签指示器矩阵,用于scikit学习中的多标签或多输出多类任务。从您的数据来看,情况似乎并非如此,因此我认为您不会希望对
    y
    进行热编码

  • 关于问题中的目标的第二件事是,您首先需要决定是要分类还是要回归任务。您说您有一个
    “整数值时间序列”
    。所以问题是,这些整数可以在数值上相互比较吗

<强>例1 < /强>:考虑到你有一个问题,你想把数据分为三个国家:“日本”、“俄罗斯”、“美国”。

  • 现在,这些字符串可以编码为1(“日本”)、2(“俄罗斯”)和3(“美国”),以便在机器学习模型中使用。但是我们不能比较这些编码,因为2中的数字大于1或小于3。这里的1,2,3只是分类数据的数值表示,实际上没有任何数值意义。在这种情况下,分类任务适合将数据放入这三个类中

  • 但在任何其他情况下,如预测股票价格或预测温度等,数字可以而且应该相互比较,因此应该使用回归(预测实际价值目标)

示例2:为了更好地理解,您还可以考虑模型的正确性(损失函数)。让我们假设一个模型预测的目标为1到10,并且特定样本的正确目标为9

  • 在分类任务中,只有正确的预测才重要。无论模型预测的目标是8还是1,这都无关紧要

  • 但是在回归模型中,如果一个模型预测输出为8,那么你可以说它比一个模型预测相同样本的输出为1要好

希望你明白我的意思。因此,对于您的问题,即使您有有限数量的整数(128)作为目标,您也需要确定它们在分类或回归中是否有意义

注意:我现在将分类作为您最初的问题进一步讨论

现在进入功能
X
如果类别中不存在排序,或者无法正确确定排序,则使用热编码。我在上面对类别之间的数字比较所作的解释也适用于这里

  • 考虑三个类别的另一个例子:“高”、“中”、“低”。在这里,它们有一个固有的顺序,如果编码为0(低)、1(中)和2(高),那么它们可以进行数字比较。因此,您可以决定将它们保留为0、1、2或一个热编码

  • 正如我在评论中所说的那样,随机林对于这些事情来说非常健壮,如果对类别进行战略性编码,则不会对性能产生太大影响。例如,如果编码0(高)、1(低)、2(中)等,性能可能会下降

现在再次回到您的案例和我的问题,从第1点开始:这些整数可以在数字上相互比较吗?如果是,则无需对功能进行热编码。如果没有,就去做。

首先让我们谈谈你的目标
Input data: (4272, 99) (4272,) (1257, 99) (1257,)
y_true (1257,) [ 0  0  0 ... 69 70 70]
y_prob (1257, 29) [[0.09375  0.       0.       ... 0.078125 0.078125 0.015625]
 [0.109375 0.       0.       ... 0.046875 0.0625   0.0625  ]
 [0.125    0.       0.       ... 0.015625 0.078125 0.015625]
 ...
 [0.078125 0.       0.       ... 0.       0.       0.      ]
 [0.046875 0.       0.       ... 0.       0.       0.      ]
 [0.078125 0.       0.       ... 0.       0.       0.      ]]
y_hat (1257,) [81 81 79 ... 67 67 65]
Score of randomforest = 0.20047732696897375
Score y_hat 0.20047732696897375
 228 -  76 77
  51 -  76  0
 563 -  81  0
 501 -   0 77
 457 -  79 79
 285 -  76 77
 209 -  81  0
1116 -  79  0
 178 -  72 77
1209 -  67 65