R語言 | 二分類和多分類的邏輯迴歸實現

二分類邏輯迴歸

首先,我先展示下我邏輯迴歸的總體代碼,如果有基礎的同志需要的話,可以直接修改數據和參數拿去用呀:

library(lattice)
library(ggplot2)
library(caret)
library(e1071)
library(foreign)
library(survival)
library(MASS)
library(nnet)
library(epiDisplay)
library(pROC)

# 數據導入
data<-read.csv('E:/TestData/Number10.2.csv',header = T)

# 共線性診斷
XX<-cor(data[-1])
kappa(XX,exact = TRUE)  # 也可以計算條件數kappa(X),k<100,說明共線性程度小;如果100<k<1000,則存在較多的多重共線性;若k>1000,存在嚴重的多重共線性。

# 劃分訓練集與測試集
train_sub = sample(nrow(data),7.5/10*nrow(data))
train_data = data[train_sub,]
test_data =data[-train_sub,]

# 模型構建
model6<-glm(mort~.,data=train_data,family = binomial)
summary(model6) #展示模型的

# 模型預測
pre_logistic<-as.numeric(predict(model6,newdata = test_data,type = "response")>0.5)

# 模型檢驗
conMat4<-confusionMatrix(factor(pre_logistic),factor(test_data$mort),positive="1")
logistic.display(model6) #輸出OR值

# 繪製ORC曲線
roc1<-roc(test_data$mort,pre_logistic,plot=TRUE, print.thres=TRUE, print.auc=TRUE,levels = c(0,1),direction = "<")

# 檢驗線性假設是否成立
pre<-predict(model6,newdata = test_data,type = "response")
par(mfrow=c(2,2))
scatter.smooth(test_data[,2],log(pre/(1-pre)),cex=0.5)
scatter.smooth(test_data[,3],log(pre/(1-pre)),cex=0.5)
scatter.smooth(test_data[,4],log(pre/(1-pre)),cex=0.5)
scatter.smooth(test_data[,5],log(pre/(1-pre)),cex=0.5)

數據準備

在將數據導入R之前,根據自己的需求對數據進行清理。本例中,因變量爲二分類,代表患者的出院和死亡,實驗目的爲預測患者死亡相關因素。因此,我們將死亡設置爲1,住院設置爲0。

R語言數據的導入支持很多格式,本例中導入的是csv格式,可以使用read.csv()函數,也可以使用read.table()函數;如果想要導入.xlsx文件,可以調用library(openxlsx)包,使用read.xlsx()函數,需要的同志可以自己去查。

本例中,首先我們導入數據

data<-read.csv('E:/TestData/Number10.2.csv',header = T)

#header = T 表明直接把文件中的標題行導入

數據導入效果展示如下(因爲可能涉及到敏感信息,這裏我將標題行抹去啦,實際導入進來是有標題行的)
因爲可能涉及到敏感信息,這裏我將標題行抹去啦,實際導入進來是有標題行的
在進行數據分析之前,我們需要檢驗一下自變量之間是否存在多重共線性:

data<-read.csv('E:/TestData/Number10.2.csv',header = T)
XX<-cor(data[-1])
kappa(XX,exact = TRUE)  # 也可以計算條件數kappa(X),k<100,說明共線性程度小;如果100<k<1000,則存在較多的多重共線性;若k>1000,存在嚴重的多重共線性。

本例中,計算得出的k=2.857281,說明自變量間的共線程度較小,可以不予考慮。

然後我們按 7.5 : 2.5 的比例將數據劃分爲測試集和訓練集

train_sub = sample(nrow(data),7.5/10*nrow(data))
train_data = data[train_sub,]  # 訓練集
test_data =data[-train_sub,]  # 測試集

模型構建

R語言中二分類邏輯迴歸,可以調用glm()函數,具體實現如下:

model6<-glm(mort~.,data=train_data,family = binomial)

#實際模型建立的時候,可以採用mort~colname1+colname2+colname3的形式,mort ~代表將剩餘所有的列作爲自變量放入模型

summary(model6) #模型展示

結果如下:
在這裏插入圖片描述
上圖中,我們可以看到模型中,所有的變量P值均顯著(若此步驟中有不顯著的自變量,可以考慮將其剔除,然後重新構建模型)

模型構建成功以後,我們根據模型對測試集進行預測,將概率>0.5的歸爲死亡分類,概率<0.5的歸爲出院分類:

pre_logistic<-as.numeric(predict(model6,newdata = test_data,type = "response")>0.5)

模型檢驗

爲了檢驗模型的預測效果,我們利用library(caret)包下的confusionMatrix()函數輸出預測值和真實值的混淆矩陣,以及模型的準確率,敏感性和特異性:

conMat4<-confusionMatrix(factor(pre_logistic),factor(test_data$mort),positive="1") 
logistic.display(model6) #輸出OR值

#需要注意的是,confusionMatrix()函數要求輸入變量是factor類型,在此,我們可以利用library(e1071)包下的factor()函數,或者as.factor()函數將數據強制轉換爲factor類型,如上述代碼所示。

混淆矩陣輸出結果展示如下:
在這裏插入圖片描述
由上圖可知,模型的準確率AUC爲0.9681,敏感性Sensitivity爲0.80882,特異性Specificity爲0.98861。總體上來看,模型的敏感性較低,特異性高,可能存在的原因是數據不平衡,導致模型對數據量偏少的那個分類不夠敏感。建議可以採用過採樣,SMOTE平衡等方法對數據進行處理,具體實現方法,需要的同志可以自行百度。

除了輸出混淆矩陣,也可以通過繪製ROC曲線,得到模型的準確率AUC,敏感性Sensitivity和特異性Specificity:

roc1<-roc(test_data$mort,pre_logistic,plot=TRUE, print.thres=TRUE, print.auc=TRUE,levels = c(0,1),direction = "<")

ROC曲線展示如下:
在這裏插入圖片描述
其實從上圖我們可以看到,我這裏ROC曲線中的AUC值和通過混淆矩陣輸出的AUC是有偏差的(我自己還沒有明白爲什麼,如有大神看到了這裏且有想法,懇請能夠指點一二)。

到此爲止,二分類的邏輯迴歸模型就建立好啦。模型建立過程中做了很多工作,經常會出現模型擬合不好的情況,本來想記錄的詳細點,但文筆邏輯有限,發現過程中有些感想不是很容易寫出來,最終還是隻寫了大概的過程。其實模型構建過程中,經常會因爲數據問題或者操作不當出現各種各樣的,難以言喻的錯誤,比如超過2個level的無序多分類自變量最好設置爲啞變量(R語言邏輯迴歸中,將原始數據設置爲A B C等用字母表示的數據,代入glm()模型中就會自動以第一個分類爲參考將其設置爲啞變量,有需求的同志可以自行百度);再有,如果有非線性關係,而且關係不明,可能需要generalized additive models,對應着gam()函數。如果非線性關係明確,就轉化成線性的,用glm()函數:比如通過線性診斷髮現某自變量的函數關係呈現二次型的,可以將該自變量轉化爲平方,再將新的變量代入模型重新構建(線性假設的檢驗我的總體代碼中又給,有興趣的同志可以自己嘗試一下)。

線性檢驗出來的結果大概如下:
在這裏插入圖片描述
如上圖中,圖3很明顯的大概是二次型的關係,因此可以將圖3中的自變量化爲其自身的二次型,然後再構建新的模型。

多分類邏輯迴歸

介紹完二分類迴歸,我們來看一下多分類的邏輯迴歸,其R語言實現過程與二分類迴歸大同小異。同樣,我先展示下總體代碼:

library(lattice)
library(ggplot2)
library(caret)
library(e1071)
library(nnet)
library(pROC)

# 數據準備
data<-read.csv('D:/多分類邏輯迴歸/iris.csv',header = T)
train_sub = sample(nrow(data),7.5/10*nrow(data))
train_data = data[train_sub,]
test_data =data[-train_sub,]

# 多元分類模型構建
train_data$class2<-relevel(as.factor(train_data$class),ref = "Iris-setosa") # 選擇參考分類
mult.model<-multinom(class~A+B+C+D,data=train_data)
summary(mult.model)

# 係數顯著性檢驗
z <- summary(mult.model)$coefficients/summary(mult.model)$standard.errors
p <- (1 - pnorm(abs(z), 0, 1))*2
p

# 相對危險度(相對危險風險比,或者也叫odds),與OR等價
exp(coef(mult.model))

# 利用head()函數得到模型的擬合值
# head(pp<-fitted(mult.model))

# 測試集結果預測
pre_logistic<-predict(mult.model,newdata = test_data) 

# 預測正確百分比
# table(test_data$class,pre_logistic)
# 多分類混淆矩陣
conMat4<-confusionMatrix(factor(pre_logistic),factor(test_data$class))

本例中,多分類的邏輯迴歸利用的是library(nnet)包中的multinom()函數。該函數有兩個特點:一是需要選擇參考分類;二是不能計算係數的顯著性(需要自己計算)。多元邏輯迴歸中,假設有3個分類,會以參考分類作爲參考,構建兩個分類模型。模型計算的是該條數據屬於3個分類的概率,取概率最大的分類爲最終分類。(詳細的教程可以參考:多元分類詳細教程

在此不再對多元迴歸的代碼做詳細的解釋。示例代碼採用的數據是經典鳶尾花案例數據,需要的可以自行下載:鳶尾花數據集

總結:感覺就是,像算法啊,數據分析啊這種東西還是要自己動手寫,只看或者只聽,到自己動手的時候還是一團糟。所以,如果有機會,就多加練習吧!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章