在 Dataframe 中查找 BernoulliNB 概率

Posted

技术标签:

【中文标题】在 Dataframe 中查找 BernoulliNB 概率【英文标题】:Look up BernoulliNB Probability in Dataframe 【发布时间】:2019-08-06 19:45:39 【问题描述】:

我有一些训练数据 (TRAIN) 和一些测试数据 (TEST)。 每个数据帧的每一行都包含一个观察到的类 (X) 和一些二进制 (Y) 列。 BernoulliNB 根据训练数据预测测试数据中 X 给定 Y 的概率。我正在尝试查找测试数据(Pr)中每行观察到的类的概率。

编辑:我使用 Antoine Zambelli 的建议来修复代码:

from sklearn.naive_bayes import BernoulliNB
BNB = BernoulliNB()

# Training Data
TRAIN = pd.DataFrame('X' : [1,2,3,9],
                      'Y1': [1,1,0,0],
                      'Y4': [1,0,0,0])

# Test Data
TEST  = pd.DataFrame('X' : [5,0,1,1,1,2,2,2,2],
                      'Y1': [1,1,0,1,0,1,0,0,0],
                      'Y2': [1,0,1,0,1,0,1,0,1],
                      'Y3': [1,1,0,1,1,0,0,0,0],
                      'Y4': [1,1,0,1,1,0,0,0,0])

# Add the information that TRAIN has none of the missing items
diff_cols = set(TEST.columns)-set(TRAIN.columns)
for i in diff_cols:
    TRAIN[i] = 0

# Split the data
Se_Tr_X = TRAIN['X']
Se_Te_X = TEST ['X']
df_Tr_Y = TRAIN .drop('X', axis=1)
df_Te_Y = TEST  .drop('X', axis=1)

# Train: Bernoulli Naive Bayes Classifier
A_F = BNB.fit(df_Tr_Y, Se_Tr_X)

# Test: Predict Probability
Ar_R = BNB.predict_proba(df_Te_Y)
df_R = pd.DataFrame(Ar_R)

# Rename the columns after the classes of X
df_R.columns = BNB.classes_

df_S = df_R .join(TEST)

# Look up the predicted probability of the observed X
# Skip X's that are not in the training data
def get_lu(df):
  def lu(i, j):
    return df.get(j, ).get(i, np.nan)
  return lu
df_S['Pr'] = [*map(get_lu(df_R), df_S .T, df_S .X)]

这似乎有效,给了我结果(df_S):

这正确地给出了前 2 行的“NaN”,因为训练数据不包含关于 X=5 或 X=0 类的信息。

【问题讨论】:

你能添加predict_proba()的输出吗?至少在第一种情况和其中一个问题情况下?我想排除df_S 的构造中发生了一些事情。请打印Ar_Rpd.DataFrame(Ar_R) :) 没关系,我得到了它的工作 - 我会发布一个答案,只是试图以一种有意义的方式框架它。 【参考方案1】:

好的,这里有几个问题。我在下面有一个完整的工作示例,但首先是这些问题。主要是断言“这正确地给出了前 2 行的“NaN””。

这与分类算法的使用方式和它们的功能有关。训练数据包含您希望算法知道并能够采取行动的所有信息。测试数据只会在考虑该信息的情况下进行处理。即使您(此人)知道测试标签是 5 并且未包含在训练数据中,算法也不知道这一点。它只会查看特征数据,然后尝试从中预测标签。所以它不能返回nan(或5,或任何不在训练集中的东西)——nan来自你的工作,从df_Rdf_S

这导致了第二个问题,即df_Te_Y = TEST .iloc[ : , 1 : ] 行,该行应该是df_Te_Y = TEST .iloc[ : , 2 : ],因此它不包含标签数据。标签数据只出现在训练集中。预测的标签只会从出现在训练数据中的标签集中提取。

注意:我已将类标签更改为 Y,将特征数据更改为 X,因为这是文献中的标准。

from sklearn.naive_bayes import BernoulliNB
from sklearn.metrics import accuracy_score
import pandas as pd

BNB = BernoulliNB()

# Training Data
train_df = pd.DataFrame('Y' : [1,2,3,9], 'X1': [1,1,0,0], 'X2': [0,0,0,0], 'X3': [0,0,0,0], 'X4': [1,0,0,0])

# Test Data
test_df  = pd.DataFrame('Y' : [5,0,1,1,1,2,2,2,2],
                      'X1': [1,1,0,1,0,1,0,0,0],
                      'X2': [1,0,1,0,1,0,1,0,1],
                      'X3': [1,1,0,1,1,0,0,0,0],
                      'X4': [1,1,0,1,1,0,0,0,0])


X = train_df.drop('Y', axis=1)  # Known training data - all but 'Y' column.
Y = train_df['Y']  # Known training labels - just the 'Y' column.

X_te = test_df.drop('Y', axis=1)  # Test data.
Y_te = test_df['Y']  # Only used to measure accuracy of prediction - if desired.

Ar_R = BNB.fit(X, Y).predict_proba(X_te)  # Can be combined to a single line.
df_R = pd.DataFrame(Ar_R)
df_R.columns = BNB.classes_  # Rename as per class labels.

# Columns are class labels and Rows are observations.
# Each entry is a probability of that observation being assigned to that class label.
print(df_R)

predicted_labels = df_R.idxmax(axis=1).values  # For each row, take the column with the highest prob in that row.
print(predicted_labels)  # [1 1 3 1 3 2 3 3 3]

print(accuracy_score(Y_te, predicted_labels))  # Percent accuracy of prediction.

print(BNB.fit(X, Y).predict(X_te))  # [1 1 3 1 3 2 3 3 3], can be used in one line if predicted_label is all we want.
# NOTE: change train_df to have 'Y': [1,2,1,9] and we get predicted_labels = [1 1 9 1 1 1 9 1 9].
# So probabilities have changed.

如果在阅读代码后没有意义,我建议查看一些关于聚类算法的教程或其他材料。

【讨论】:

它错误地将5 归类为训练数据(在本例中为1)这一事实实际上触及了机器学习中一个非常深刻的概念。测试数据以及稍后要预测的真实数据应该与您的训练数据具有相同的结构。即,如果您希望获得准确性,训练数据必须能够代表传入的真实数据。

以上是关于在 Dataframe 中查找 BernoulliNB 概率的主要内容,如果未能解决你的问题,请参考以下文章

text [在DataFrame中查找范围] Dataframe中的范围。

伯努利分布 Bernoulli distribution

在 Spark 的 Dataframe 行中查找最小值

在 PySpark 中,如何根据另一个 DataFrame 中的查找来填充新列?

在 Dataframe 中查找 BernoulliNB 概率

如何在 Spark 中使用 Python 查找 DataFrame 中的分区数以及如何在 Spark 中使用 Python 在 DataFrame 中创建分区