【问题标题】:Create (efficiently) fake truth/predicted values from a confusion matrix从混淆矩阵中创建(有效)假真值/预测值
【发布时间】:2015-04-26 19:55:06
【问题描述】:

出于测试目的,我需要从混淆矩阵中创建虚假的真实值/预测值。

我的混淆矩阵使用以下方法存储在 Pandas DataFrame 中:

labels = ['N', 'L', 'R', 'A', 'P', 'V']
df = pd.DataFrame([
    [1971, 19, 1, 8, 0, 1],
    [16, 1940, 2, 23, 9, 10],
    [8, 3, 181, 87, 0, 11],
    [2, 25, 159, 1786, 16, 12],
    [0, 24, 4, 8, 1958, 6],
    [11, 12, 29, 11, 11, 1926] ], columns=labels, index=labels)
df.index.name = 'Actual'
df.columns.name = 'Predicted'

我假设索引是实际值,列是预测值。

这个混淆矩阵看起来像:

Predicted     N     L    R     A     P     V
Actual
N          1971    19    1     8     0     1
L            16  1940    2    23     9    10
R             8     3  181    87     0    11
A             2    25  159  1786    16    12
P             0    24    4     8  1958     6
V            11    12   29    11    11  1926

我正在寻找一种创建 2 个 Numpy 数组的有效方法:y_truey_predict,它们将产生这样一个混淆矩阵。

我的第一个想法是首先创建大小合适的 Numpy 数组。

所以我做到了:

N_all = df.sum().sum()

y_true = np.empty(N_all)
y_pred = np.empty(N_all)

但我不知道如何有效地填充这 2 个 Numpy 数组

同样的代码也应该适用于二进制混淆矩阵,例如:

labels = [False, True]
df = pd.DataFrame([
    [5, 3],
    [2, 7]], columns=labels, index=labels)
df.index.name = 'Actual'
df.columns.name = 'Predicted'

这个二进制混淆矩阵看起来像:

Predicted  False  True
Actual
False          5      3
True           2      7

【问题讨论】:

  • 那么,您有矩阵作为输入,需要同时生成向量 y_true 和 y_predicted?具有相同标签的值在两个向量中应该具有相同的值。具有不同标签的值应作为其预测/真实值推送到每个向量。我想我错过了这个问题。

标签: python numpy pandas confusion-matrix


【解决方案1】:

如果您想精确地重新创建,可以使用以下函数:

def create_arrays(df):
    # Unstack to make tuples of actual,pred,count
    df = df.unstack().reset_index()

    # Pull the value labels and counts
    actual = df['Actual'].values
    predicted = df['Predicted'].values
    totals = df.iloc[:,2].values

    # Use list comprehension to create original arrays
    y_true = [[curr_val]*n for (curr_val, n) in zip(actual, totals)]
    y_predicted = [[curr_val]*n for (curr_val, n) in zip(predicted, totals)]

    # They come nested so flatten them
    y_true = [item for sublist in y_true for item in sublist]
    y_predicted = [item for sublist in y_predicted for item in sublist]

    return y_true, y_predicted

我们可以检查这是否产生了预期的结果:

import pandas as pd
import numpy as np
from sklearn.metrics import confusion_matrix

labels = ['N', 'L', 'R', 'A', 'P', 'V']
df = pd.DataFrame([
    [1971, 19, 1, 8, 0, 1],
    [16, 1940, 2, 23, 9, 10],
    [8, 3, 181, 87, 0, 11],
    [2, 25, 159, 1786, 16, 12],
    [0, 24, 4, 8, 1958, 6],
    [11, 12, 29, 11, 11, 1926] ], columns=labels, index=labels)
df.index.name = 'Actual'
df.columns.name = 'Predicted'

# Recreate the original confusion matrix and check for equality
y_t, y_p = create_arrays(df)
conf_mat = confusion_matrix(y_t,y_p)
check_labels = np.unique(y_t)

df_new = pd.DataFrame(conf_mat, columns=check_labels, index=check_labels).loc[labels, labels]
df_new.index.name = 'Actual'
df_new.columns.name = 'Predicted'

df == df_new

输出:

Predicted     N     L     R     A     P     V
Actual                                       
N          True  True  True  True  True  True
L          True  True  True  True  True  True
R          True  True  True  True  True  True
A          True  True  True  True  True  True
P          True  True  True  True  True  True
V          True  True  True  True  True  True

对于二进制:

# And for the binary
labels = ['False', 'True']
df = pd.DataFrame([
    [5, 3],
    [2, 7]], columns=labels, index=labels)
df.index.name = 'Actual'
df.columns.name = 'Predicted'

# Recreate the original confusion matrix and check for equality
y_t, y_p = create_arrays(df)
conf_mat = confusion_matrix(y_t,y_p)
check_labels = np.unique(y_t)

df_new = pd.DataFrame(conf_mat, columns=check_labels, index=check_labels).loc[labels, labels]
df_new.index.name = 'Actual'
df_new.columns.name = 'Predicted'

df == df_new

Predicted False  True
Actual               
False      True  True
True       True  True

【讨论】:

  • 您可以添加 df_comp = df != df_newassert df_comp.sum().sum()==0 但它不适用于二进制 Predicted False True Actual False 5 3 True 2 7 Predicted True Actual True 7
  • y_true 数组可以使用sum_true = df.sum(axis=1).shift(1).fillna(0) sum_predicted = df.sum(axis=0).shift(1).fillna(0) index = np.arange(N_all) s_true = pd.Series(index=index) s_true[sum_true] = sum_true.index s_true = s_true.fillna(method='ffill') y_true = s_true.values 创建,但我仍然看不到如何有效地创建 y_predicted。我正在使用 Pandas 系列,但纯 Numpy 可能会更有效。
  • @scls 从上面它可以工作吗?您是否将 True 和 False 作为布尔值而不是字符串传递?如果是这样,那将导致它失败。
  • @scls 我很困惑......我编写了上面的函数来创建两个数组,几乎只使用速度很快的 stdlib?
  • 抱歉,它不适用于引发ValueError: Can only compare identically-labeled DataFrame objects 的二进制文件。 df.columns Index([False, True], dtype='object')df_new.columns Index([True], dtype='object')。 For 循环比 Numpy 调用慢 (C)
猜你喜欢
  • 2020-09-17
  • 2021-03-02
  • 2020-07-31
  • 2013-02-16
  • 2016-06-15
  • 1970-01-01
  • 2015-12-14
  • 2020-02-04
相关资源
最近更新 更多