在探究變量之間的相關性時,由于并不是每次分析數據時所用的樣本集都能囊括所有的情況,所以單純從樣本集去下判斷會有武斷的嫌疑;同樣的,我們有時候也想要在數據樣本不夠全面時就能對結果有個大概的了解。
例如醫生在給患者做診斷時,有些檢查需要耗費的時間很久,但僅僅憑借一些其他的癥狀,他就可以對病人患某種病有個大概的猜想,從而先做出一些措施來降低風險,畢竟等到疾病真正發生時可能會來不及。概率圖模型便是能夠同時進行多變量的概率分析的模型,既能提高效率,又能顧及沒有注意到的細節。
以下是一個例子:
library(bnlearn)# 1. 生成更簡單的模擬數據集(確保變量間有明確因果關系)
set.seed(123)
n <- 1000# 明確因果關系:Smoking -> LungCancer -> Cough
smoking <- rbinom(n, 1, 0.3)
lung_cancer <- ifelse(smoking, rbinom(n, 1, 0.15), rbinom(n, 1, 0.05))
cough <- ifelse(lung_cancer, rbinom(n, 1, 0.5), rbinom(n, 1, 0.1))health_data <- data.frame(Smoking = factor(smoking, labels = c("No", "Yes")),LungCancer = factor(lung_cancer, labels = c("No", "Yes")),Cough = factor(cough, labels = c("No", "Yes"))
)# 2. 構建網絡結構(改用明確指定結構的方式)
bn_struct <- empty.graph(names(health_data))# 手動指定因果關系(避免方向不確定問題)
arcs(bn_struct) <- matrix(c("Smoking", "LungCancer","LungCancer", "Cough"),ncol = 2, byrow = TRUE
)# 3. 參數學習(現在應該可以正常運行)
bn_model <- bn.fit(bn_struct, health_data)# 查看條件概率表
cat("吸煙對肺癌的影響:\n")
print(bn_model$LungCancer)cat("\n肺癌對咳嗽的影響:\n")
print(bn_model$Cough)# 4. 簡單推理示例
# 已知某人吸煙,預測患肺癌概率
smoking_yes_probs <- cpquery(bn_model, event = (LungCancer == "Yes"),evidence = (Smoking == "Yes"))cat("\n吸煙者患肺癌概率:", round(smoking_yes_probs, 3))# 已知某人咳嗽,反推吸煙概率
cough_yes_smoking <- cpquery(bn_model,event = (Smoking == "Yes"),evidence = (Cough == "Yes"))cat("\n咳嗽患者中吸煙比例:", round(cough_yes_smoking, 3))
輸出:
Parameters of node Cough (multinomial distribution)Conditional probability table:LungCancer
Cough No YesNo 0.91738197 0.54411765Yes 0.08261803 0.45588235
吸煙者患肺癌概率: 0.137
咳嗽患者中吸煙比例: 0.364
從結果可以看到,患者中有無肺癌,咳嗽的概率有明顯的不同,這說明咳嗽確實是肺癌的一個重要表現,但反過來,咳嗽的也有可能是其他原因導致的。如果反過來去看因果發生的概率,即咳嗽的人群中患有肺癌的概率,便會發現概率沒有想象中那么大,這能輔助我們考慮多種情況。