Вычисление условных вероятностей для категориальных и непрерывных переменных в python? P (категорический | непрерывный) - PullRequest
0 голосов
/ 29 августа 2018

У меня есть набор данных, который имеет одну категориальную и несколько непрерывных переменных следующим образом:

A     B     C
2.0  1.0   foo
2.2  1.2   bar
1.0  1.5   foo

Я хочу вычислить:

Pr(C='foo'| A=2.0) # column A
Pr(C='foo'| A=1.0) # column A
Pr(C='bar'| A=2.2) # column A
Pr(C='foo'| B=1.0) # column B
Pr(C='bar'| B=1.2) # column B

Каким будет правильный подход к решению этой проблемы? Будет ли допустимым сгруппировать значения в A и B в скобки или вычислить для каждой случайной величины в A и B? Спасибо!

Ответы [ 2 ]

0 голосов
/ 29 августа 2018
  1. A, B - числовые переменные, вычисляющие условные вероятности только из таблицы (учитывая ее как совокупность)

Предположим, что A, B могут иметь значения только из приведенной таблицы, и возьмем следующую таблицу вероятностей с несколькими строками (для лучшего понимания):

import pandas as pd
df = pd.read_csv('prob.txt', sep=' ') # let the dataframe df store the probability table 
df

# the probability table 
     A   B   C
0   2.0 1.0 foo
1   2.2 1.2 bar
2   1.0 1.5 foo
3   2.0 3.0 bar
4   2.0 2.0 foo
5   3.2 1.2 foo

Теперь напомним определение условной вероятности для двух событий X, Y с P (Y)! = 0:

enter image description here

Следовательно, мы имеем

# Pr(C='foo'| A=2.0) = Pr(C='foo' & A=2.0) / Pr(A=2.0)

df[(df.C=='foo') & (df.A==2.0)] # Pr(C='foo' & A=2.0), we have 2 such rows
#    A   B   C
# 0 2.0 1.0 foo
# 4 2.0 2.0 foo

df[(df.A==2.0)]    # Pr(A=2.0), we have 3 such rows 
#    A   B   C
# 0 2.0 1.0 foo
# 3 2.0 3.0 bar
# 4 2.0 2.0 foo

# the required probability Pr(C='foo'| A=2.0)
df[(df.C=='foo') & (df.A==2.0)].shape[0] / df[(df.A==2.0)].shape[0]  # 2 / 3
# 0.6666666666666666   

Аналогично мы можем вычислить и другие условные вероятности.

  1. Подогнать классификатор, рассматривающий таблицу как образец обучающего набора данных с переменными предиктора A, B (непрерывные), для прогнозирования Pr (C | A, B)

Теперь давайте предположим, что таблица предоставляет несколько (случайных) выборочных значений непрерывных переменных A, B из совокупности, и вы хотите подобрать классификатор, чтобы предсказать вероятность класса C (столбец 'foo'or') '), учитывая данные (с видимыми / невидимыми значениями переменных A, B), в этом случае вы можете установить любой классификатор из библиотеки scikit-learn, который вам не нужно реализовывать самостоятельно. Например, самым простым в этом случае может быть Naive Bayesian, хотя он предполагает условную независимость, учитывая класс (P (A, B | C) = P (A | C) P (B | C)).

Предполагая, что у вас есть набор данных df, который выглядит следующим образом (где я сгенерировал набор данных синтетически, вы можете использовать свой собственный набор данных здесь)

import pandas as pd
# load your data in dataframe df here
df.head()
#        A         B      C
# 0.161729  0.814335    foo
# 0.862661  0.517964    foo
# 0.814303  0.337391    foo
# 1.898132  1.530963    bar
# 2.124829  0.289176    bar

from sklearn.naive_bayes import GaussianNB
clf = GaussianNB()
X, y = df[['A','B']], df['C']

# fit the classifier on the training dataset
clf.fit(X, y)

# predict the Pr(C = 'bar' | A, B) with predict_proba() 
print(clf.predict_proba([[1,1]])[:,0])   # Pr(C='bar'|A=1.0, B=1.0)
# [ 0.86871233]

import matplotlib.pylab as plt
X1, X2 = np.meshgrid(np.linspace(X[['A']].min(), X[['A']].max(),10), np.linspace(X[['B']].min(), X[['B']].max(),10))
plt.figure(figsize=(10,6))
# plot the probability surface
plt.contourf(X1, X2, clf.predict_proba(np.c_[X1.ravel(), X2.ravel()])[:,0].reshape(X1.shape), cmap='jet', alpha=.8)
plt.colorbar()
cols = {'foo':'green', 'bar':'red'}
plt.scatter(X[['A']], X[['B']], c=[cols[c] for c in y.tolist()], s=50)
plt.show()

Цветная полоса показывает, как изменяется вероятность того, что C = 'bar' с учетом значений A и B (ось x, y на графике). Исходные точки данных также обозначены точками зеленого и красного цветов (соответственно с классами 'foo' и 'bar').

enter image description here

Если условная независимость слишком сильна для вас, вы можете попытаться соответствовать

  • Байесовский классификатор: классификатор линейного / квадратичного дискриминантного анализа (предположим, что два гауссиана один для Pr (A, B | C = 'foo'), другой для Pr (A, B | C = 'bar') с одинаковой / разной ковариационной матрицей и изучите гауссовские параметры для условных вероятностей класса из данных с MLE / MAP, а затем вычислите апостериорную вероятность P (C | A, B) с помощью теоремы Байеса для вычисления MLE 1D гауссовского параметра это видео может быть полезно). На следующем рисунке показаны гауссианы, подогнанные по условному распределению класса с MLE, и поверхность решения с классификатором LDA.

enter image description here

enter image description here

clf.predict_proba([[1,1]])[:,0]  # Pr(C='bar'|A=1.0, B=1.0)
# [ 0.67028318]
  • SVM, RandomForest, NeuralNet для более сложных классификаторов и прогнозирования вероятности с помощью подогнанного классификатора. На следующем рисунке показана поверхность принятия решения с RandomForest classifier.

enter image description here

clf.predict_proba([[1,1]])[:,0]  # Pr(C='bar'|A=1.0, B=1.0)
# [ 1.0]

Надеюсь, теперь это правильно ответит на ваш вопрос.

0 голосов
/ 29 августа 2018

Я думаю, что это легче решить, если применить базовую концепцию вероятности так:

import numpy as np
import pandas as pd

a=np.random.choice([1.1,1.2,1.3,1.4],10)
b=np.random.choice([1.1,1.2,1.3,1.4],10)
c=np.random.choice(['bar','foo'],10)

df=pd.DataFrame({'A':a,'B':b,'C':c})

probs={}
for col in ['A','B']:
    for num in df[col].unique():
        for cat in df['C'].unique():
            tdf=df[df[col]==num]
            N=len(tdf) #total 
            n=len(tdf[tdf['C']==cat]) #occurences
            probs['C:{2}//{0}:{1}'.format(col,num,cat)]=(n/N)

возвращение

{'C:bar//A:1.4': 0.6666666666666666,
 'C:foo//A:1.4': 0.3333333333333333,
 'C:bar//A:1.3': 0.6666666666666666,
 'C:foo//A:1.3': 0.3333333333333333,
 'C:bar//A:1.1': 0.0,
 'C:foo//A:1.1': 1.0,
 'C:bar//A:1.2': 0.6666666666666666,
 'C:foo//A:1.2': 0.3333333333333333,
 'C:bar//B:1.3': 0.6666666666666666,
 'C:foo//B:1.3': 0.3333333333333333,
 'C:bar//B:1.4': 0.5,
 'C:foo//B:1.4': 0.5,
 'C:bar//B:1.2': 0.6666666666666666,
 'C:foo//B:1.2': 0.3333333333333333}

с этим сгенерированным фреймом данных

     A   B   C
0   1.4 1.3 bar
1   1.3 1.4 bar
2   1.1 1.2 foo
3   1.4 1.4 foo
4   1.2 1.3 bar
5   1.2 1.4 foo
6   1.3 1.3 foo
7   1.4 1.2 bar
8   1.3 1.4 bar
9   1.2 1.2 bar
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...