Na podstawie pliku sport.csv, zawierającego wyniki pewnej ankiety, zamodelować sieć Bayesowską (uczenie struktury, estymacja parametrów), w której węzłami będą zmienne losowe zawarte w poniższej tabeli.

Zmienna losowa Wartość Opis
A a Badany ćwiczy regularnie.
b Badany ćwiczy nieregularnie.
c Badany nie ćwiczy.
B a Aktywny członek klubu sportowego.
b Bierny członek klubu sportowego.
c Badany nie należy do klubu sportowego.
C a Dieta przygotowana przez dietetyka.
b Badany samodzielnie dba o zdrową dietę.
c Badany nie odżywia się zdrowo.
D a Utrata wagi powyżej 5 kg.
b Utrata wagi poniżej 5 kg.
c Brak utraty wagi.
E a Wiek <= 20 lat.
b Wiek 21-39 lat.
c Wiek >= 40 lat.

Wczytujemy dane

sport <- read.csv("C:/Users/r_nal/Seafile/Moja biblioteka/Wnioskowanie w warunkach niepenwości/Pro_3/sport.csv") 

head(sport)
##   X A B C D E
## 1 1 c c c a c
## 2 2 c c b b b
## 3 3 a c a a c
## 4 4 b a a b a
## 5 5 c c a c c
## 6 6 c c a c b
colnames(sport)
## [1] "X" "A" "B" "C" "D" "E"

Pierwsza kolumna “X” zawiera numer porządkowy. Nie będzie ona nam do niczego potrzebna, dlatego usuwam ją z tabeli.

sport2 <- sport[,c(2,3,4,5,6)]
head(sport2)
##   A B C D E
## 1 c c c a c
## 2 c c b b b
## 3 a c a a c
## 4 b a a b a
## 5 c c a c c
## 6 c c a c b

Instalowanie pakietów

install.packages("bnlearn")
if (!requireNamespace("BiocManager", quietly = TRUE))
install.packages("BiocManager")
BiocManager::install(c("graph", "RBGL", "Rgraphviz"))
a

install.packages("gRain", dependencies=TRUE)

Ładowanie pakietow.

library(bnlearn)
library(gRain)
## Warning: pakiet 'gRain' został zbudowany w wersji R 4.3.3
## Ładowanie wymaganego pakietu: gRbase
## Warning: pakiet 'gRbase' został zbudowany w wersji R 4.3.3
## 
## Dołączanie pakietu: 'gRbase'
## Następujące obiekty zostały zakryte z 'package:bnlearn':
## 
##     ancestors, children, nodes, parents

Uczenie struktury oraz jej rysunek.

Wszystkie algorytmy akceptuja niepelne dane. Więcej informacji można znaleźć szukając structure-learning

Dwie główne grupy algorytmow:

Przyklad algorytmu z grafem skierowanym

Polecenie siechc <- hc(sport2) nie zadziała, ponieważ dane są tekstowe, a nie numeryczne. Musimy zamienić kolumny na czyniki (ang. factor).

Zmieniamy na czynniki każdą kolumnę

sport2$A  <- as.factor(sport2$A)
sport2$B  <- as.factor(sport2$B)
sport2$C  <- as.factor(sport2$C)
sport2$D  <- as.factor(sport2$D)
sport2$E  <- as.factor(sport2$E)

Tworzymy strukturę. Ilustrujemy ją grafem

siechc <- hc(sport2)
graphviz.plot(siechc)
## Ładowanie wymaganej przestrzeni nazw: Rgraphviz

Tzw. “wynik sieci” BIC (Bayesian Information Criterior) jest miarą dopasowania struktury sieci do danych. Im wyższy tym lepiej. Użycie tego kryterum pozwala porównywać różne sieci w celu znalezienia modelu najlepiej wspieranego przez dane.

score(siechc,data=sport2,type="bic")
## [1] -20846.79

Przyklad algorytmu z grafem czesciowo skierowanym

siec <- pc.stable(sport2)
graphviz.plot(siec)

Definiujemy brakujące kierunki. Będziemy testować różne możliwości połączenia

siec1 <- set.arc(siec, "E", "B")
siec1 <- set.arc(siec1, "B", "A")
graphviz.plot(siec1)

Wyniki dopasowania danych do sieci

score(siec1,data=sport2,type="bic")
## [1] -20846.79
siec2 <- set.arc(siec, "B", "E")
siec2 <- set.arc(siec2, "B", "A")
graphviz.plot(siec2)

Wyniki dopasowania danych do sieci

score(siec2,data=sport2,type="bic")
## [1] -20846.79

Sieci rownoważne (kierując się kryterium BIC)

  1. Dodanie v-struktury obniza wartosc sieci. W algorytmie wszystkie v-struktury zostaly podane w formie grafow skierowanych
siec3 <- set.arc(siec, "E", "B")
siec3 <- set.arc(siec3, "A", "B")
graphviz.plot(siec3)

Wyniki dopasowania danych do sieci

score(siec3,data=sport2,type="bic")
## [1] -21144.31

Wynik sieci pogorszy sie jesli zmienimy luk skierowany.

siechc <- hc(sport2)
graphviz.plot(siechc)

zmianakierunku <- set.arc(siechc, "D", "C")
score(zmianakierunku,data=sport2,type="bic")
## [1] -21644.15
graphviz.plot(zmianakierunku)

Mamy możliwosc wymuszenia istnienia luków w sieci

sieclista <- pc.stable(sport2, 
                       whitelist = matrix(c("D","E"), 
                       ncol = 2, byrow = TRUE))
graphviz.plot(sieclista)    

sieclista1 <- set.arc(sieclista, "A", "B")
score(sieclista1,data=sport2,type="bic")
## [1] -20890.46

Wynik gorszy niż na początkowej sieci.

Innym kryterium statystycznym używanym przez algorytmy w trakcie uczenia struktury jest warunkowy test niezależności.

Warunkowy test niezależności skupia się na obecności poszczególnych łuków. Łuk sieci reprezentuje zależność (w sensie probabilistycznym) pomiędzy węzłami. Warunkowy test niezależności może zostać wykonany w celu oceny czy zależność pomiędzy wezłami (w sensie probabilistycznym) jest wspierana przez dane.

Interpretacja testu \(\chi^2\)

Interpretacja:

Testowanie dla pojedynczych zmiennych:

ci.test(zmienna1,zmienna2,warunek,test="x2", data=dane)

Przy użyciu tego testu możemy rozważać dodanie łuku do sieci lub przeanalizować, czy łuk powinien zostać usunięty z sieci (ponieważ jego istnienie nie jest wspierane przez dane).

graphviz.plot(siechc)

ci.test("B","D",test="x2", data=sport2)
## 
##  Pearson's X^2
## 
## data:  B ~ D  
## x2 = 571.13, df = 4, p-value < 2.2e-16
## alternative hypothesis: true value is greater than 0

Nie ma podstaw do odrzucenia hipotezy, że zmienne B oraz D są niezależne. Czyli zmienne B i D uznajemy za zależne.

Rozważmy dodanie łuku pomiędzy B i D.

ci.test("B","D",c("A"),test="x2", data=sport2)
## 
##  Pearson's X^2
## 
## data:  B ~ D | A
## x2 = 12.449, df = 12, p-value = 0.4104
## alternative hypothesis: true value is greater than 0

Duża p-value oznacza zależność pomiędzy B i D nie jest istotna (w zadanej już strukurze). Oznacza to, że nie trzeba dodawać łuku pomiędzy B i D w istniejącej już sieci.

ci.test("A","D",c("C"), test="x2", data=sport2)
## 
##  Pearson's X^2
## 
## data:  A ~ D | C
## x2 = 4311.6, df = 12, p-value < 2.2e-16
## alternative hypothesis: true value is greater than 0

Mała p-value oznacza, że zmienne sa zależne(pod warunkiem rodziców), więc łuk jest dobrze wspierany przez dane.

Estymacja parametrów

Skorzystamy z gotowej funkcji. Ponieważ kolumny zostały już zmienione na czynniki, będzie ona działać.

rozkladprawdopodobienstw<- bn.fit(siechc, sport2)
rozkladprawdopodobienstw
## 
##   Bayesian network parameters
## 
##   Parameters of node A (multinomial distribution)
## 
## Conditional probability table:
##       a      b      c 
## 0.3266 0.3330 0.3404 
## 
##   Parameters of node B (multinomial distribution)
## 
## Conditional probability table:
##  
##    A
## B            a          b          c
##   a 0.84507042 0.43903904 0.09518214
##   b 0.03306797 0.21141141 0.09753231
##   c 0.12186160 0.34954955 0.80728555
## 
##   Parameters of node C (multinomial distribution)
## 
## Conditional probability table:
##       a      b      c 
## 0.7638 0.1916 0.0446 
## 
##   Parameters of node D (multinomial distribution)
## 
## Conditional probability table:
##  
## , , C = a
## 
##    A
## D            a          b          c
##   a 0.79635499 0.09565217 0.07585139
##   b 0.10855784 0.79130435 0.11996904
##   c 0.09508716 0.11304348 0.80417957
## 
## , , C = b
## 
##    A
## D            a          b          c
##   a 0.18791946 0.88000000 0.27164179
##   b 0.10738255 0.04000000 0.49253731
##   c 0.70469799 0.08000000 0.23582090
## 
## , , C = c
## 
##    A
## D            a          b          c
##   a 0.45205479 0.29333333 0.14666667
##   b 0.17808219 0.44000000 0.34666667
##   c 0.36986301 0.26666667 0.50666667
## 
## 
##   Parameters of node E (multinomial distribution)
## 
## Conditional probability table:
##  
##    B
## E            a          b          c
##   a 0.60272767 0.27447552 0.18004640
##   b 0.29960405 0.27447552 0.31090487
##   c 0.09766828 0.45104895 0.50904872

Rysowanie rozkładow

  1. Prawdopodobieństwa całkowite w sieci
graphviz.chart(rozkladprawdopodobienstw)

  1. Rozklady warunkowe dla każdego węzła
library(lattice)
## Warning: pakiet 'lattice' został zbudowany w wersji R 4.3.3
bn.fit.barchart(rozkladprawdopodobienstw$A, main="Zmienna A - cwiczenia")

bn.fit.barchart(rozkladprawdopodobienstw$B, main="Zmienna B - czlonek klubu sportowego")

bn.fit.barchart(rozkladprawdopodobienstw$C, main="Zmienna C - dieta")

bn.fit.barchart(rozkladprawdopodobienstw$D, main="Zmienna D - utrata wagi")

bn.fit.barchart(rozkladprawdopodobienstw$E, main="Zmienna E - wiek")

Wnioskowanie na podstawie sieci

Ze struktury sieci możemy odczytać bezpośrednie i pośrednie związki pomiędzy węzłami. Jeżeli zmienne są zależne bezpośrednio, jest pomiędzy nimi łuk. Jeżeli zależność jest pośrednia, jest pomiędzy nimi kilka łuków przechodzących przez węzły, które „pośredniczą” w relacji. Graficzna niezależność implikuje niezależność probabilistyczną (tzn. jeżeli nie ma ścieżki „zablokowanej” pomiędzy węzłami to zmienne są (warunkowo) niezależne –czyli istotne są kierunki łuków). Implikacja w drugą stronę nie zawsze jest prawdziwa (tzn. nie każda warunkowa niezależność jest widoczna w grafie). Przeanalizujemy kilka relacji pomiędzy zmiennymi (analiza d-separacji).

Przykłady

  1. Sprawdzamy czy zmienne A i B są niezależne. Test ten działa na podstawie struktyry. Test \(\chi^2\) działa na podstawie danych.
dsep(siechc,x="A",y="B")
## [1] FALSE

Jeżeli istnieje bezpośredni łuk to zmienne są zależne.

dsep(siechc,x="A",y="E")
## [1] FALSE
dsep(siechc,x="A",y="E",z="B")
## [1] TRUE

Zmienne A i E są połączone łukiem, więc sa zależne. Trzeci argument jest warunkiem. Jeżeli sprawdzimy niezależność pomiędzy zmiennymi A i E pod warunkiem B, to okazuje się, że są niezależne.

dsep(siechc,x="B",y="D")
## [1] FALSE
dsep(siechc,x="B",y="D",z="A")
## [1] TRUE

Zmienne B i D są zależne, ale B i D są niezależne pod warunkiem A.

dsep(siechc,x="A",y="C")
## [1] TRUE
dsep(siechc,x="A",y="C",z="D")
## [1] FALSE

Zmienne A i C są niezależne (zwróćmy uwagę, że droga między nimi jest „zablokowana”). Jeżeli znamy wartość jaką przyjmuje zmienna D, ulega zmianie rozkład obu zmiennych A i C i w ten sposób zmienne stają się zależne.

Innym rodzajem wnioskowania jest wnioskowanie na podstawie wyznaczonych rozkładów prawdopodobieństw. Wczytujemy pakiet i tworzymy drzewo węzłowe

library(gRain)
junction <-compile(as.grain(rozkladprawdopodobienstw))
  1. Jakie jest prawdopodobieństwo, że losowo wybrana osoba korzysta z porad dietetyka?
querygrain(junction, nodes = "C")$C
## C
##      a      b      c 
## 0.7638 0.1916 0.0446

W ten sposób obliczyliśmy prawdopodobieństwo całkowite zmiennej losowej C. Możemy > z niej odczytać, że prawdopodobieństwo, że losowo wybrana osoba:

  • korzysta z diety przygotowanej przez dietetyka wynosi 0.7638
  • samodzielnie dba o zdrową dietę wynosi 0.1916
  • nie odżywia się zdrowo 0.0446

Podkreślam, że nic więcej o tej losowej osobie nie wiemy.

  1. Wyznaczymy rozkład łączny dla wszystkich zmiennych w przypadku, gdy mamy informację o każdym węźle.
querygrain(junction, nodes = c("A","B","C","D","E"), type="joint")
## , , D = a, C = a, E = a
## 
##    B
## A             a            b           c
##   a 0.101185102 0.0018030748 0.004358669
##   b 0.006437882 0.0014117272 0.001531130
##   c 0.001131382 0.0005279404 0.002866450
## 
## , , D = b, C = a, E = a
## 
##    B
## A             a            b            c
##   a 0.013793392 0.0002457923 0.0005941668
##   b 0.053258841 0.0116788341 0.0126666170
##   c 0.001789431 0.0008350078 0.0045336712
## 
## , , D = c, C = a, E = a
## 
##    B
## A             a            b            c
##   a 0.012081803 0.0002152925 0.0005204381
##   b 0.007608406 0.0016684049 0.0018095167
##   c 0.011994961 0.0055972460 0.0303902216
## 
## , , D = a, C = b, E = a
## 
##    B
## A             a            b           c
##   a 0.005989595 0.0001067320 0.000258009
##   b 0.014857532 0.0032580254 0.003533586
##   c 0.001016385 0.0004742789 0.002575095
## 
## , , D = b, C = b, E = a
## 
##    B
## A              a            b            c
##   a 0.0034226259 6.098971e-05 0.0001474337
##   b 0.0006753424 1.480921e-04 0.0001606175
##   c 0.0018428958 8.599562e-04 0.0046691284
## 
## , , D = c, C = b, E = a
## 
##    B
## A              a            b            c
##   a 0.0224609825 0.0004002450 0.0009675336
##   b 0.0013506847 0.0002961841 0.0003212350
##   c 0.0008823562 0.0004117366 0.0022355221
## 
## , , D = a, C = c, E = a
## 
##    B
## A              a            b            c
##   a 0.0033539467 5.976588e-05 0.0001444753
##   b 0.0011528287 2.527974e-04 0.0002741787
##   c 0.0001277416 5.960847e-05 0.0003236439
## 
## , , D = b, C = c, E = a
## 
##    B
## A              a            b            c
##   a 0.0013212517 2.354413e-05 5.691449e-05
##   b 0.0017292431 3.791961e-04 4.112680e-04
##   c 0.0003019347 1.408928e-04 7.649766e-04
## 
## , , D = c, C = c, E = a
## 
##    B
## A              a            b            c
##   a 0.0027441382 4.889936e-05 0.0001182070
##   b 0.0010480261 2.298158e-04 0.0002492534
##   c 0.0004412892 2.059202e-04 0.0011180427
## 
## , , D = a, C = a, E = b
## 
##    B
## A              a            b           c
##   a 0.0502971201 0.0018030748 0.007526568
##   b 0.0032001442 0.0014117272 0.002643961
##   c 0.0005623878 0.0005279404 0.004949798
## 
## , , D = b, C = a, E = b
## 
##    B
## A              a            b           c
##   a 0.0068564233 0.0002457923 0.001026010
##   b 0.0264739202 0.0116788341 0.021872766
##   c 0.0008894909 0.0008350078 0.007828762
## 
## , , D = c, C = a, E = b
## 
##    B
## A             a            b            c
##   a 0.006005626 0.0002152925 0.0008986946
##   b 0.003781989 0.0016684049 0.0031246809
##   c 0.005962459 0.0055972460 0.0524779600
## 
## , , D = a, C = b, E = b
## 
##    B
## A              a            b            c
##   a 0.0029773098 0.0001067320 0.0004455309
##   b 0.0073853865 0.0032580254 0.0061018101
##   c 0.0005052249 0.0004742789 0.0044466848
## 
## , , D = b, C = b, E = b
## 
##    B
## A              a            b            c
##   a 0.0017013199 6.098971e-05 0.0002545891
##   b 0.0003356994 1.480921e-04 0.0002773550
##   c 0.0009160672 8.599562e-04 0.0080626703
## 
## , , D = c, C = b, E = b
## 
##    B
## A              a            b           c
##   a 0.0111649117 0.0004002450 0.001670741
##   b 0.0006713988 0.0002961841 0.000554710
##   c 0.0004386019 0.0004117366 0.003860309
## 
## , , D = a, C = c, E = b
## 
##    B
## A              a            b            c
##   a 1.667181e-03 5.976588e-05 0.0002494805
##   b 5.730484e-04 2.527974e-04 0.0004734529
##   c 6.349784e-05 5.960847e-05 0.0005588697
## 
## , , D = b, C = c, E = b
## 
##    B
## A              a            b            c
##   a 0.0006567682 2.354413e-05 9.828018e-05
##   b 0.0008595726 3.791961e-04 7.101794e-04
##   c 0.0001500858 1.408928e-04 1.320965e-03
## 
## , , D = c, C = c, E = b
## 
##    B
## A              a            b            c
##   a 0.0013640570 4.889936e-05 0.0002041204
##   b 0.0005209531 2.298158e-04 0.0004304117
##   c 0.0002193562 2.059202e-04 0.0019306407
## 
## , , D = a, C = a, E = c
## 
##    B
## A              a            b           c
##   a 0.0163964180 0.0029630146 0.012323350
##   b 0.0010432188 0.0023199084 0.004328992
##   c 0.0001833335 0.0008675709 0.008104371
## 
## , , D = b, C = a, E = c
## 
##    B
## A              a            b           c
##   a 0.0022351336 0.0004039134 0.001679899
##   b 0.0086302647 0.0191919694 0.035812574
##   c 0.0002899662 0.0013721785 0.012818137
## 
## , , D = c, C = a, E = c
## 
##    B
## A             a            b           c
##   a 0.001957781 0.0003537928 0.001471445
##   b 0.001232895 0.0027417099 0.005116082
##   c 0.001943709 0.0091980221 0.085922869
## 
## , , D = a, C = b, E = c
## 
##    B
## A              a            b            c
##   a 0.0009705768 0.0001753940 0.0007294738
##   b 0.0024075709 0.0053539525 0.0099905756
##   c 0.0001646989 0.0007793882 0.0072806168
## 
## , , D = b, C = b, E = c
## 
##    B
## A              a            b            c
##   a 0.0005546153 0.0001002251 0.0004168422
##   b 0.0001094350 0.0002433615 0.0004541171
##   c 0.0002986298 0.0014131765 0.0132011183
## 
## , , D = c, C = b, E = c
## 
##    B
## A              a            b            c
##   a 0.0036396629 0.0006577275 0.0027355267
##   b 0.0002188701 0.0004867230 0.0009082341
##   c 0.0001429803 0.0006766118 0.0063205354
## 
## , , D = a, C = c, E = c
## 
##    B
## A              a            b            c
##   a 5.434862e-04 9.821399e-05 0.0004084777
##   b 1.868087e-04 4.154250e-04 0.0007751908
##   c 2.069974e-05 9.795532e-05 0.0009150448
## 
## , , D = b, C = c, E = c
## 
##    B
## A              a            b            c
##   a 2.141006e-04 3.869036e-05 0.0001609155
##   b 2.802131e-04 6.231375e-04 0.0011627862
##   c 4.892665e-05 2.315308e-04 0.0021628332
## 
## , , D = c, C = c, E = c
## 
##    B
## A              a            b            c
##   a 4.446706e-04 0.0000803569 0.0003342090
##   b 1.698261e-04 0.0003776591 0.0007047189
##   c 7.150818e-05 0.0003383911 0.0031610639

Przykładowo \(P(A = a, B = a, C = a, D = a, E = a) = 0.101185102\) (trzeba odnaleźć odpowiednią tabelkę). Oznacza to, że prawdopodobieństwo, że losowo wybrana osoba:

  • ćwiczy regularnie,
  • jest aktywnym członkiem klubu sportowego,
  • korzysta z diety przygotowanej przez dietetyka,
  • utraciła powyżej 5 kg wagi,
  • ma co najwyżej 20 lat,

wynosi 10.12%. W prostych słowach, co 10-ta osoba z grupy badanych spełnia te warunki.

  1. Mamy informację o niektórych węzłach. Przykładowo jestem osobą korzystającą z porad dietetyka. Na podstawie naszej sieci obliczyć prawdopodobieństwo, że jestem aktywnym członkiem klubu sportowego.
warunek <- setEvidence(junction,nodes=c("C"),states=c("a")) 
querygrain(warunek, nodes = "B")$B
## B
##      a      b      c 
## 0.4546 0.1144 0.4310

Otrzymany wynik interpretuję następująco:

  • w 45.46% jestem aktywnym członkiem klubu,
  • w 11.44% jestem biernym członkiem klubu,
  • w 43.10% nie należę do klubu.
  1. Jakie jest prawdopodobieństwo, że losowo wybrana osoba nie utraciła wagi, gdy wiadomo, że:
  • ćwiczy nieregularnie
  • jest biernym członkiem klubu
  • samodzielnie dba o zdrowe żywienie
warunek1 <- setEvidence(junction,nodes=c("A","B","C"), states=c("b","b","b"))
querygrain(warunek1, nodes = "D")$D
## D
##    a    b    c 
## 0.88 0.04 0.08

Zatem prawdopodobieństwo, że osoba spełniające powyższe warunki nie utraciła wagi wynosi 8%.

  1. Robię założenie że osoba ćwiczy regularnie
cwiczy <- setEvidence(junction,nodes=c("A"), states=c("a"))

I wśród tych osób rozważam różne rodzaje prawdopodobieństw:

  • Obliczam prawdopodobieństwo, że osoba utraciła wagę >5kg i korzysta z diety przygotowanej przez dietetyka (wiem o tej osobie tylko tyle, że ćwiczy regularnie), tj.
    \(P((C = a \land D = a) | A = a) = 0.60825594\)
querygrain(cwiczy, nodes = c("C","D"),type="joint")
##    C
## D            a          b           c
##   a 0.60825594 0.03600537 0.020161644
##   b 0.08291648 0.02057450 0.007942466
##   c 0.07262758 0.13502013 0.016495890
  • Obliczam prawdopodobieństwo, że osoba utraciła wagę >5kg (wiem o tej osobie tylko tyle, że ćwiczy regularnie), tj.
    \(P(D = a | A = a) = 0.6644230\)
    lub korzysta z diety przygotowanej przez dietetyka (wiem o tej osobie tylko tyle, że ćwiczy regularnie), tj.
    \(P(C = a | A = a) = 0.7638\)
querygrain(cwiczy, nodes = c("C","D"),type="marginal")
## $D
## D
##         a         b         c 
## 0.6644230 0.1114334 0.2241436 
## 
## $C
## C
##      a      b      c 
## 0.7638 0.1916 0.0446
  • Obliczam prawdopodobieństwo, korzysta z diety przygotowanej przez dietetyka, jeśli utraciła wagę >5kg (wiem o tej osobie tylko tyle, że ćwiczy regularnie i utraciła wagę >5kg), tj.
    \(P(C = a | (A = a \land D = a)) = 0.91546497\)
querygrain(cwiczy, nodes = c("C","D"),type="conditional")
##    D
## C            a          b          c
##   a 0.91546497 0.74408973 0.32402253
##   b 0.05419044 0.18463484 0.60238229
##   c 0.03034459 0.07127542 0.07359519