ảnh đồ án

NHÓM 7 DỮ LIỆU VỀ TIỂU ĐƯỜNG

Thăm dò tập dữ liệu Pima Indian Diabetes

date: 2023-12-13


I.Exploring the dataset

Installing module

#install.packages('reader')
#install.packages("lattice")
#install.packages("reshape2")
#install.packages('ggplot2')

Exploring data

library(reader)
## Loading required package: NCmisc
## 
## Attaching package: 'reader'
## The following objects are masked from 'package:NCmisc':
## 
##     cat.path, get.ext, rmv.ext
# Đọc file CSV trực tiếp từ đường link
diabetes <- read.csv("https://drive.google.com/uc?id=15mjrv0LV2T6GWNdAuW-QhXVdtMkQALlh")
# Hiển thị dữ liệu
head(diabetes)
##   Pregnancies Glucose BloodPressure SkinThickness Insulin  BMI
## 1           6     148            72            35       0 33.6
## 2           1      85            66            29       0 26.6
## 3           8     183            64             0       0 23.3
## 4           1      89            66            23      94 28.1
## 5           0     137            40            35     168 43.1
## 6           5     116            74             0       0 25.6
##   DiabetesPedigreeFunction Age Outcome
## 1                    0.627  50       1
## 2                    0.351  31       0
## 3                    0.672  32       1
## 4                    0.167  21       0
## 5                    2.288  33       1
## 6                    0.201  30       0

Overall of dataset: dữ liệu y tế và nhân khẩu học của phụ nữ để dự đoán bệnh tiểu đường

Bộ dữ liệu này chứa thông tin về 769 phụ nữ và bao gồm nhiều thuộc tính liên quan đến sức khỏe. Dưới đây là tổng quan ngắn gọn về các cột:

  • Mang thai: Số lần người phụ nữ đã mang thai.

  • Glucose: Nồng độ glucose trong huyết tương của người phụ nữ.

  • Huyết áp: Đo huyết áp.

  • Độ dày của da: Độ dày của nếp gấp da ở cơ tam đầu.

  • Insulin: Nồng độ insulin trong máu.

  • BMI (Chỉ số khối cơ thể): Thước đo lượng mỡ trong cơ thể dựa trên chiều cao và cân nặng.

  • Chức năng phả hệ bệnh tiểu đường: Một chức năng cho thấy khả năng mắc bệnh tiểu đường dựa trên tiền sử gia đình.

  • Tuổi: Tuổi của người phụ nữ.

  • Kết quả: Biến mục tiêu cho biết người phụ nữ có mắc bệnh tiểu đường hay không (1 đối với bệnh nhân tiểu đường, 0 đối với người không mắc bệnh tiểu đường).

Structure of dataset

str(diabetes)
## 'data.frame':    768 obs. of  9 variables:
##  $ Pregnancies             : int  6 1 8 1 0 5 3 10 2 8 ...
##  $ Glucose                 : int  148 85 183 89 137 116 78 115 197 125 ...
##  $ BloodPressure           : int  72 66 64 66 40 74 50 0 70 96 ...
##  $ SkinThickness           : int  35 29 0 23 35 0 32 0 45 0 ...
##  $ Insulin                 : int  0 0 0 94 168 0 88 0 543 0 ...
##  $ BMI                     : num  33.6 26.6 23.3 28.1 43.1 25.6 31 35.3 30.5 0 ...
##  $ DiabetesPedigreeFunction: num  0.627 0.351 0.672 0.167 2.288 ...
##  $ Age                     : int  50 31 32 21 33 30 26 29 53 54 ...
##  $ Outcome                 : int  1 0 1 0 1 0 1 0 1 1 ...

Ta có thể thấy:

  • Chỉ có 2 thuộc tính BMI và DiabetesPedigreeFunction là kiểu số thực, còn lại là int

  • Tổng có 768 dòng và 9 cột

Summary of statistic

summary(diabetes)
##   Pregnancies        Glucose      BloodPressure    SkinThickness  
##  Min.   : 0.000   Min.   :  0.0   Min.   :  0.00   Min.   : 0.00  
##  1st Qu.: 1.000   1st Qu.: 99.0   1st Qu.: 62.00   1st Qu.: 0.00  
##  Median : 3.000   Median :117.0   Median : 72.00   Median :23.00  
##  Mean   : 3.845   Mean   :120.9   Mean   : 69.11   Mean   :20.54  
##  3rd Qu.: 6.000   3rd Qu.:140.2   3rd Qu.: 80.00   3rd Qu.:32.00  
##  Max.   :17.000   Max.   :199.0   Max.   :122.00   Max.   :99.00  
##     Insulin           BMI        DiabetesPedigreeFunction      Age       
##  Min.   :  0.0   Min.   : 0.00   Min.   :0.0780           Min.   :21.00  
##  1st Qu.:  0.0   1st Qu.:27.30   1st Qu.:0.2437           1st Qu.:24.00  
##  Median : 30.5   Median :32.00   Median :0.3725           Median :29.00  
##  Mean   : 79.8   Mean   :31.99   Mean   :0.4719           Mean   :33.24  
##  3rd Qu.:127.2   3rd Qu.:36.60   3rd Qu.:0.6262           3rd Qu.:41.00  
##  Max.   :846.0   Max.   :67.10   Max.   :2.4200           Max.   :81.00  
##     Outcome     
##  Min.   :0.000  
##  1st Qu.:0.000  
##  Median :0.000  
##  Mean   :0.349  
##  3rd Qu.:1.000  
##  Max.   :1.000

Ta có thể thấy:

  • Cột SkinThickness, Insulin có 1% điểm dữ liệu bằng 0 (vì Min=0)

  • Cột Outcome có 75% điểm dữ liệu < 1, chứng tỏ tỉ lệ mắc bệnh tiểu đường thấp

Data visualization of distribution attributes

Distribution of Age, Pregnancies, Glucose and Outcome
#install.packages("cowplot")
#install.packages("gridExtra")
library(ggplot2)
library(cowplot)
library(gridExtra)
par(mfrow=c(1,4))
# Boxplot cho Age
boxplot(diabetes$Age,
        col="#ff0066",
        main="Boxplot for Age")

# Boxplot cho Pregnancies
boxplot(diabetes$Pregnancies,
        col="yellow",
        main="Boxplot for Pregnancy")

# Boxplot cho Pregnancies
barplot(table(diabetes$Outcome), main = "Barplot of Out come", xlab = "Outcome", ylab="Count")

plot(density(diabetes$Glucose),
     col="yellow",
     main="Density Plot for Glucose",
     xlab="Glucose",
     ylab="Density")
polygon(density(diabetes$Glucose),
        col="#ccff66")

box(which = "outer", lty = "solid")

Ta có thể thấy:

  • Từ boxplot về độ tuổi, cho thấy rằng phụ nữ trong tập dữ liệu tập trung chủ yếu ở khoảng 25-41 tuổi

  • Từ boxplot về số lần mang thai, cho thấy rằng phụ nữ chủ yếu có số lần mang thai từ 1-6 lần

  • Từ boxplot giữa nồng độ glucose và kết quả, những người không bệnh sẽ có nồng độ glucose thấp hơn nhóm bị bệnh; nhóm không bệnh có nồng độ glucose tập trung khoảng 99-130 mg/dl, còn nhóm bị bệnh khoảng 130-170 mg/dl

The correlation of Glucose, Outcome and Insulin
par(mfrow=c(1,2))
plot(diabetes$Insulin, diabetes$Glucose, xlab="Insulin", ylab="Glucose", type='p', col=c("red"), pch=20, main="Tương quan giữa Glucose và Insulin")

# Boxplot cho Outcome và Glucose theo người mắc bệnh và không
diabetes_groups <- cut(diabetes$Outcome, c(-Inf, 0, Inf), labels = c("Không bệnh", "Bệnh"))
boxplot(diabetes$Glucose~diabetes_groups, xlab="Outcome", ylab="Glucose (mg/dl)", main="Tỉ lệ giữa Glucose và Outcome", col="pink")

box(which="outer", lty="solid")

Ta có thể thấy:

  • Lượng Insulin càng ít thì lượng đường Glucose càng cao, do Insulin có khả nào chuyển hóa đường nhưng những người mắc bệnh tiểu đường thì cơ thể họ sẽ khó khắn trong việc sản xuất Insulin

  • Lượng đường Glucose trong tập data chủ yếu trong khoảng 90 - 150

The correlation between attributes and Outcome

Cách tính đường hồi quy tuyến tính:

  • Tính tổng các bình phương khoảng cách d tới đường hồi quy sao cho là bé nhất với mọi điểm dữ liệu. Ta sẽ được đường hồi quy phù hợp nhất

\[ sum_{min} = d_1^2+d_2^2+d_3^2+... \\ \]

  • Công thức tính khoảng cách từ 1 điểm đến 1 đường thẳng

\[ d(M, \Delta) = \sqrt{\dfrac{|ax_0+by_0+c|}{a^2+b^2}} \\ \]

p1 <- ggplot(data = diabetes, aes(x = Glucose, y = Outcome)) +
  geom_point() +
  geom_smooth(method = "lm", se = FALSE) +
  labs(title = "Mối quan hệ giữa nồng độ glucose và kết quả bệnh tiểu đường",
       x = "Nồng độ glucose (mg/dL)",
       y = "Kết quả (1 = mắc bệnh, 0 = không mắc bệnh)")

p2 <- ggplot(data = diabetes, aes(x = SkinThickness, y = Outcome)) +
  geom_point() +
  geom_smooth(method = "lm", se = FALSE) +
  labs(title = "Mối quan hệ giữa độ dày của da và kết quả bệnh tiểu đường",
       x = "độ dày da (mm)",
       y = "Kết quả (1 = mắc bệnh, 0 = không mắc bệnh)")

p3 <- ggplot(data = diabetes, aes(x = Pregnancies, y = Outcome)) +
  geom_point() +
  geom_smooth(method = "lm", se = FALSE) +
  labs(title = "Mối quan hệ giữa số lần mang thai và kết quả bệnh tiểu đường",
       x = "Số lần mang thai (lần)",
       y = "Kết quả (1 = mắc bệnh, 0 = không mắc bệnh)")

grid.arrange(p1, p2, p3, ncol = 3)
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'


Ta có thể thấy

  • Theo đường hồi quy tuyến tính dương trên, số lần mang thai hoặc nồng độ glucose càng tăng thì tỉ lệ mắc bệnh tiểu đường càng cao

  • Ngược lại, độ dày của da không ảnh hưởng quá mạnh vào khả năng mắc bệnh tiểu đường

Kiểm tra giá trị rỗng

sum_of_nan <- sum(is.na(diabetes))
paste("Tổng số giá trị rỗng trong dataset:", sum_of_nan)
## [1] "Tổng số giá trị rỗng trong dataset: 0"
for (col in colnames(diabetes)) {
  nan_of_col <- sum(is.na(diabetes[, col]))
  print(paste("Số giá trị rỗng trong cột", col, ":", nan_of_col))
}
## [1] "Số giá trị rỗng trong cột Pregnancies : 0"
## [1] "Số giá trị rỗng trong cột Glucose : 0"
## [1] "Số giá trị rỗng trong cột BloodPressure : 0"
## [1] "Số giá trị rỗng trong cột SkinThickness : 0"
## [1] "Số giá trị rỗng trong cột Insulin : 0"
## [1] "Số giá trị rỗng trong cột BMI : 0"
## [1] "Số giá trị rỗng trong cột DiabetesPedigreeFunction : 0"
## [1] "Số giá trị rỗng trong cột Age : 0"
## [1] "Số giá trị rỗng trong cột Outcome : 0"

Kiểm tra giá trị ngoại lai

Tìm giá trị ngoại lai
find_outliers <- function(inp, na.rm = TRUE) {
  i.qnt <- quantile(inp, probs = c(0.25, 0.75), na.rm = na.rm)
  i.max <- 1.5 * IQR(inp, na.rm = na.rm)
  
  outliers <- inp < (i.qnt[1] - i.max) | inp > (i.qnt[2] + i.max)
  
  return(outliers)
}
Lập tỉ lệ outliers trong cột tương ứng
calculate_rate <- function(inp) {
  num_outliers <- sum(find_outliers(inp))
  num_regular <- length(inp) - num_outliers
  
  outlier_rate <- num_outliers / length(inp) * 100
  regular_rate <- num_regular / length(inp) * 100
  
  rates <- list(outlier=outlier_rate, regular=regular_rate)
  return (rates)
}
for (col in colnames(diabetes)) {
  rates <- calculate_rate(unlist(diabetes[, col]))
  # Liệt kê tỉ lệ giá trị ngoại lại trong từng cột
  print(paste(col, "-", "Total Outliers (%):", round(rates$outlier, 2), ", Regular Values (%):", round(rates$outlier, 2)))
}
## [1] "Pregnancies - Total Outliers (%): 0.52 , Regular Values (%): 0.52"
## [1] "Glucose - Total Outliers (%): 0.65 , Regular Values (%): 0.65"
## [1] "BloodPressure - Total Outliers (%): 5.86 , Regular Values (%): 5.86"
## [1] "SkinThickness - Total Outliers (%): 0.13 , Regular Values (%): 0.13"
## [1] "Insulin - Total Outliers (%): 4.43 , Regular Values (%): 4.43"
## [1] "BMI - Total Outliers (%): 2.47 , Regular Values (%): 2.47"
## [1] "DiabetesPedigreeFunction - Total Outliers (%): 3.78 , Regular Values (%): 3.78"
## [1] "Age - Total Outliers (%): 1.17 , Regular Values (%): 1.17"
## [1] "Outcome - Total Outliers (%): 0 , Regular Values (%): 0"
Vẽ trực quan tỉ lệ ngoại lai
pie_outlier <- function(outlier_col) {for (col in outlier_col) {
  rates <- calculate_rate(unlist(diabetes[, col]))
  
  pie_data <- data.frame(
    type = c("Outliers", "Regular"),
    rate = c(rates$outlier, rates$regular)
  )
  
  # Vẽ trực quan những cột có tỉ lệ ngoại lai >= 2.3%
  return(ggplot(pie_data, aes(x="", y = rate, fill=type)) +
  geom_bar(stat="identity", width=1, color="white") +
  coord_polar("y", start=0) +
  theme_void() +
  labs(title = paste(col),
     caption = paste0("Total Outliers (%):", round(rates$outlier, 2), ", Regular Values (%):", round(rates$regular, 2))))
}}
grid.arrange(pie_outlier("BloodPressure"), pie_outlier("Insulin"), pie_outlier("BMI"), pie_outlier("DiabetesPedigreeFunction"), ncol=2)

Kiểm tra độ tương quan của các thuộc tính

library(lattice)
library(reshape2)
# creating correlation matrix
corr_mat <- round(cor(diabetes),2)
 
# reduce the size of correlation matrix
melted_corr_mat <- melt(corr_mat)
# head(melted_corr_mat)
 
# plotting the correlation heatmap
library(ggplot2)
ggplot(data = melted_corr_mat, aes(x=Var1, y=Var2, fill=value)) + geom_tile() +
  geom_text(aes(Var2, Var1, label = value), color = "white", size = 4)

Ta có thể thấy:

  • Tất cả thuộc tính đều có quan hệ thuận biến với Outcome (kết quả)

  • Glucose, BMI và Age ảnh hưởng tới kết quả mắc bệnh lớn nhất với 0.47, 0.29, 0.24

  • SkinThickness, BloodPressure ảnh hưởng tới kết quả mắc bệnh yếu nhất với 0.7

II.Tiền xử lí dữ liệu

Chuẩn bị các thư viện

#install.packages("readr")
#install.packages("dplyr")
#install.packages("tidyr")
#install.packages("ggplot2")
library(readr)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:gridExtra':
## 
##     combine
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(tidyr)
## 
## Attaching package: 'tidyr'
## The following object is masked from 'package:reshape2':
## 
##     smiths
library(ggplot2)

Xử lí giá trị bị thiếu

Kiểm tra các giá trị bị thiếu

Kiểm tra các giá trị bị thiếu của từng cột

na_count<-colSums(sapply(diabetes,is.na))
na_count
##              Pregnancies                  Glucose            BloodPressure 
##                        0                        0                        0 
##            SkinThickness                  Insulin                      BMI 
##                        0                        0                        0 
## DiabetesPedigreeFunction                      Age                  Outcome 
##                        0                        0                        0

Bộ dữ liệu này không tồn tại giá trị bị thiếu

Các phương pháp xử lí giá trị bị thiếu

Giới thiệu 3 phương pháp xử lí giá trị bị thiếu :

Điền giá trị trung vị.

diabetes_median <- diabetes %>%
mutate_all(~ ifelse(is.na(.), median(., na.rm = TRUE), .))

Điền giá trị trung bình.

diabetes_mean <- diabetes %>%
mutate_all(~ ifelse(is.na(.), mean(., na.rm = TRUE), .))

Điền giá trị phổ biến nhất.

fill_mode <- function(x) {
  mode_val <- names(sort(table(x), decreasing = TRUE))[1] 
  x[is.na(x)] <- mode_val 
  return(x)
}

diabetes_mode <- diabetes %>%
mutate_all(fill_mode)

Xử lí giá trị ngoại lai

Phương pháp xử lý giá trị ngoại lai dựa trên ma trận Z-score

Bước 1:Tìm Z-score cho tất cả các điểm trong tập dữ liệu

Bước 2: Vẽ biểu đồ Scatter Plots biểu diễn ma trận Z-score

Bước 3: Quan sát biểu đồ Z-score,tìm Z-score ngưỡng

Bước 4: Dựa trên Z-score ngưỡng và loại các giá trị vượt qua Z-score ngưỡng đó

Ta có công thức như sau :

\[ Z = \frac{{X - \bar{X}}}{{\sigma}} \]

Trong đó:

  • \(X\) là giá trị của một điểm dữ liệu cụ thể trong một thuộc tính nào đó.

  • \(\bar{X}\) là giá trị trung bình của thuộc tính đó trong tập dữ liệu.

  • \(\sigma\) là độ lệch chuẩn của thuộc tính đó trong tập dữ liệu.

Áp dụng công thức trên để biến đổi bộ dữ liệu thành ma trận Z-score

diabetes_z <- (diabetes - colMeans(diabetes)) / apply(diabetes, 2, sd)
head(diabetes_z)
##   Pregnancies      Glucose BloodPressure SkinThickness     Insulin       BMI
## 1   0.6395305   7.99033370   215.8827363     9.2459493  -1.2873733 99.985707
## 2  -3.7499128   0.04512617     2.7855842    -2.8741635  -0.6924393 -0.564690
## 3  -3.1569579  19.15326626   133.4539425    -3.5702706  -4.0578295 48.120296
## 4  -1.2246861 267.19131711    18.4459142     0.1544326 282.2820762  7.198215
## 5  -0.6924393   8.82288025    -2.5301191    -0.3887359  11.4588828 -2.433161
## 6  -3.4236465 242.47973103     0.2528715    -4.0578295  -0.7316434 -2.247670
##   DiabetesPedigreeFunction           Age   Outcome
## 1               -0.9550312  1.8469872005  1.593957
## 2               -3.7702115 -0.4234448489 -2.826550
## 3               -3.5355523  0.0009413653  1.365006
## 4               -1.2769045 61.9569937727 -1.141108
## 5               -0.6725858 -0.0204830505 -3.749913
## 6               -4.0323353 62.1678499768 -3.570271

Vẽ biểu đồ Scatter Plots biểu diễn ma trận Z-score

Biểu đồ này cho phép chúng ta quan sát được các giá trị ngoại lai

melted_diabetes <- gather(diabetes_z, key = "Variable", value = "Z-score")

# Vẽ scatter plot cho tất cả các cột
ggplot(melted_diabetes, aes(x = Variable, y = `Z-score`, color = `Z-score`)) +
  geom_point() +
  labs(x = "Variable", y = "Z-score", title = "Scatter Plots of Z-scores") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))  # Điều chỉnh góc và vị trí của chú thích trên trục x

Quan sát biểu đồ ta thấy được các điểm Z-score >=700 là các giá trị ngoại lai

Ta chọn Z-score ngưỡng là 700 và loại các giá trị Z-score mà vượt qua ngưỡng đó

# Lọc các giá trị Z-score mà tất cả đều nhỏ hơn 700
diabetes_filter <- diabetes[rowSums(apply(diabetes_z, 2, function(x) abs(x) < 700)) == ncol(diabetes_z), ]

# Hiển thị kích thước của bộ dữ liệu sau khi loại bỏ
cat("Còn lại số lượng hàng và cột là:", dim(diabetes_filter))
## Còn lại số lượng hàng và cột là: 760 9

Loại bỏ các cột không cần thiết (nếu có) cho việc xây dựng mô hình

Vẽ biểu đồ hộp để xem sự phân phối dữ liệu của biến mục tiêu và biến độc lập

attach(diabetes_filter)
par(mfrow=c(2,4))
boxplot(Pregnancies~Outcome, main="No. of Pregnancies vs. Diabetes", 
        xlab="Outcome", ylab="Pregnancies",col="red")
boxplot(Glucose~Outcome, main="Glucose vs. Diabetes", 
        xlab="Outcome", ylab="Glucose",col="pink")
boxplot(BloodPressure~Outcome, main="Blood Pressure vs. Diabetes", 
        xlab="Outcome", ylab="Blood Pressure",col="green")
boxplot(SkinThickness~Outcome, main="Skin Thickness vs. Diabetes", 
        xlab="Outcome", ylab="Skin Thickness",col="orange")
boxplot(Insulin~Outcome, main="Insulin vs. Diabetes", 
        xlab="Outcome", ylab="Insulin",col="yellow")
boxplot(BMI~Outcome, main="BMI vs. Diabetes", 
        xlab="Outcome", ylab="BMI",col="purple")
boxplot(DiabetesPedigreeFunction~Outcome, main="Diabetes Pedigree Function vs. Diabetes", xlab="Outcome", ylab="DiabetesPedigreeFunction",col="lightgreen")
boxplot(Age~Outcome, main="Age vs. Diabetes", 
        xlab="Outcome", ylab="Age",col="lightblue")
box(which = "outer", lty = "solid")

diabetes_f<-diabetes_filter

Huyết áp và độ dày của da ít thay đổi với bệnh tiểu đường, chúng sẽ bị loại khỏi mô hình. Các biến khác ít nhiều cho thấy mối tương quan với bệnh tiểu đường nên sẽ được giữ nguyên

diabetes_f $BloodPressure <- NULL
diabetes_f $SkinThickness <- NULL

dim(diabetes_f)
## [1] 760   7

Chuẩn hoá dữ liệu

Phương pháp chuẩn hoá dữ liệu bằng MinMax-Scaler

Mục đích

  • Đảm bảo rằng các biến có thang đo đồng nhất.

  • Miền giá trị nằm trong Khoảng (0-1).

  • Giúp mô hình học tốt hơn.

  • Giảm ảnh hưởng của biên độ lớn giữa các biến.

Công thức :

\[ \text{Scaled Value} = \frac{{X - \text{min}(X)}}{{\text{max}(X) - \text{min}(X)}} \]

min_max_scaler <- function(x) {
  return ((x - min(x)) / (max(x) - min(x)))
}

diabetes_scale <- as.data.frame(lapply(diabetes_f, min_max_scaler))
head(diabetes_scale)
##   Pregnancies   Glucose   Insulin       BMI DiabetesPedigreeFunction       Age
## 1  0.35294118 0.7437186 0.0000000 0.5007452               0.23441503 0.4833333
## 2  0.05882353 0.4271357 0.0000000 0.3964232               0.11656704 0.1666667
## 3  0.47058824 0.9195980 0.0000000 0.3472429               0.25362938 0.1833333
## 4  0.05882353 0.4472362 0.1111111 0.4187779               0.03800171 0.0000000
## 5  0.00000000 0.6884422 0.1985816 0.6423249               0.94363792 0.2000000
## 6  0.29411765 0.5829146 0.0000000 0.3815201               0.05251921 0.1500000
##   Outcome
## 1       1
## 2       0
## 3       1
## 4       0
## 5       1
## 6       0

III.Xây dựng các mô hình

PREDICTING DIABETES using Logarithmic Regression model

Chia tập dữ liệu thành 2 phần , 70% tập dữ liệu để train, 30 tập dữ liệu để test

train <- diabetes_scale [1:530,]
test <- diabetes_scale [531:760,]
model <-glm(Outcome ~.,family=binomial(link='logit'),data=train)
summary(model)
## 
## Call:
## glm(formula = Outcome ~ ., family = binomial(link = "logit"), 
##     data = train)
## 
## Coefficients:
##                          Estimate Std. Error z value Pr(>|z|)    
## (Intercept)              -8.31656    0.79380 -10.477  < 2e-16 ***
## Pregnancies               2.17795    0.64605   3.371 0.000748 ***
## Glucose                   6.28234    0.85292   7.366 1.76e-13 ***
## Insulin                  -0.77826    0.83942  -0.927 0.353857    
## BMI                       5.84760    1.10552   5.289 1.23e-07 ***
## DiabetesPedigreeFunction  2.68500    0.82830   3.242 0.001189 ** 
## Age                       0.08529    0.65216   0.131 0.895952    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 686.91  on 529  degrees of freedom
## Residual deviance: 512.27  on 523  degrees of freedom
## AIC: 526.27
## 
## Number of Fisher Scoring iterations: 5

Với mức ý nghĩa là 0.05 ta thấy rằng ba thuộc tính phù hợp nhất, ‘Glucose’, ‘BMI’ và ‘Pregnancies’ có giá trị p thấp.Điều này cho thấy rằng các biến độc lập này ảnh hưởng đáng kể đến hiệu suất của mô hình hồi quy logistic trong dự đoán ‘Kết quả.’

“Insulin” và “Age” không có ý nghĩa thống kê vì giá trị p cao .

anova(model, test="Chisq")
## Analysis of Deviance Table
## 
## Model: binomial, link: logit
## 
## Response: Outcome
## 
## Terms added sequentially (first to last)
## 
## 
##                          Df Deviance Resid. Df Resid. Dev  Pr(>Chi)    
## NULL                                       529     686.91              
## Pregnancies               1   25.416       528     661.49 4.621e-07 ***
## Glucose                   1  102.956       527     558.54 < 2.2e-16 ***
## Insulin                   1    0.089       526     558.45 0.7656248    
## BMI                       1   34.931       525     523.52 3.416e-09 ***
## DiabetesPedigreeFunction  1   11.233       524     512.29 0.0008037 ***
## Age                       1    0.017       523     512.27 0.8960336    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Bảng “Analysis of Deviance Table” cung cấp thông tin về sự biến động của deviance (độ lệch) khi thêm vào từng biến độc lập vào mô hình

Chúng ta có thể thấy rằng việc bổ sung insulin và tuổi tác ít ảnh hưởng đến độ lệch

Với mức ý nghĩa 0,05 cho thấy rằng Pregnacies, Glucose, BMI là những yếu tố dự báo quan trọng của biến Kết quả.

Cross Validation

Bắt đầu nhận dạng và chuyển đổi xác suất thành nhãn dự đoán 1: mắc bệnh,0: không mắc bệnh

Tìm ma trận nhầm lẫn

fitted.results <- predict(model,newdata=test,type='response')
fitted.results <- ifelse(fitted.results > 0.5,1,0)
(conf_matrix_logi<-table(fitted.results, test$Outcome))
##               
## fitted.results   0   1
##              0 136  33
##              1  16  45

Tính toán độ chính xác toàn thể,độ nhạy,độ đặc hiệu

TP <- conf_matrix_logi[2, 2]  # True Positive
TN <- conf_matrix_logi[1, 1]  # True Negative
FP <- conf_matrix_logi[1, 2]  # False Positive
FN <- conf_matrix_logi[2, 1]  # False Negative

Accuracy<-(TP+TN)/(TP+TN+FP+FN)
cat("Độ chính xác:",Accuracy,"\n")
## Độ chính xác: 0.7869565
#trong số bệnh nhân thực tế bị bệnh tiểu đường,bao nhiêu phần trăm được dự báo bị bệnh
Sensitivity<-TP/(TP+FN)
cat("Độ nhạy:",Sensitivity,"\n")
## Độ nhạy: 0.7377049
#trong số bệnh nhân thực tế không bị bệnh, bao nhiêu phần trăm được dự báo không bị bệnh

Specificity<-TN/(TN+FP)
cat("Độ đặc hiệu",Specificity)
## Độ đặc hiệu 0.8047337

Dựa trên các con số này. Ta thể kết luận rằng mô hình có độ chính xác khá cao. Đối với việc dự đoán bệnh nhân bị bệnh tiểu đường, mô hình có độ nhạy là 73.77%, và đối với việc dự đoán bệnh nhân không bị bệnh tiểu đường, độ đặc hiệu là 80.47%. Điều này cung cấp cái nhìn chi tiết hơn về hiệu suất của mô hình trong từng khía cạnh cụ thể

PREDICTING DIABETES using Decision Tree model

Ma trận tương quan

#install.packages("corrgram")
library(corrgram)
## 
## Attaching package: 'corrgram'
## The following object is masked from 'package:lattice':
## 
##     panel.fill
corrgram(diabetes_filter)

Xét biểu đồ tương quan, ta thấy:
- Pregnancies và Age tương quan cao
- SkinThickness và Insulin tương quan cao

Do đó: Khi xây dựng mô hình dự đoán, với mỗi cặp thuộc tính, chỉ sử dụng 1 trong 2 để hạn chế tình trạng đa cộng tuyến (multicollinearity)

MÔ HÌNH CÂY QUYẾT ĐỊNH

Chia tập dữ liệu thành 2 tập train và test

library(caret)
## Warning: package 'caret' was built under R version 4.3.2

Chi tập dữ liệu thành 2 phần, tập train để xây dựng mô hình và tập test để kiểm tra mô hình

set.seed(1)
split <- createDataPartition(diabetes_filter$Outcome,p = 0.75,list = FALSE)
dfTrain <- diabetes_filter[split,]
dfTest <- diabetes_filter[-split,]
head(dfTrain)
##   Pregnancies Glucose BloodPressure SkinThickness Insulin  BMI
## 1           6     148            72            35       0 33.6
## 2           1      85            66            29       0 26.6
## 3           8     183            64             0       0 23.3
## 4           1      89            66            23      94 28.1
## 5           0     137            40            35     168 43.1
## 6           5     116            74             0       0 25.6
##   DiabetesPedigreeFunction Age Outcome
## 1                    0.627  50       1
## 2                    0.351  31       0
## 3                    0.672  32       1
## 4                    0.167  21       0
## 5                    2.288  33       1
## 6                    0.201  30       0
head(dfTest)
##    Pregnancies Glucose BloodPressure SkinThickness Insulin  BMI
## 9            2     197            70            45     543 30.5
## 10           8     125            96             0       0  0.0
## 12          10     168            74             0       0 38.0
## 13          10     139            80             0       0 27.1
## 14           1     189            60            23     846 30.1
## 23           7     196            90             0       0 39.8
##    DiabetesPedigreeFunction Age Outcome
## 9                     0.158  53       1
## 10                    0.232  54       1
## 12                    0.537  34       1
## 13                    1.441  57       0
## 14                    0.398  59       1
## 23                    0.451  41       1

Hàm kiểm tra mô hình

Xây dựng các hàm kiểm tra kết quả của mô hình

Hàm xây dựng ma trận nhầm lẫn để xem kết quả dự đoán và tính độ chính xác bằng ma trận nhầm lẫn

# Dùng ma trận nhầm lẫn
accuracy <- function() {
  predictions <- predict(model, newdata = dfTest, type = "class")
  
  # So sánh giữa giá trị dự đoán và giá trị thực tế
  confusion_matrix <- table(predictions, dfTest$Outcome)
  print(confusion_matrix)
  
  # Tính toán độ chính xác từ ma trận nhầm lẫn
  accuracy <- sum(diag(confusion_matrix)) / sum(confusion_matrix)
  return (accuracy)
}

Hàm tính độ chính xác, độ nhạy và độ đặc hiệu của mô hình

thongso <- function() {
  predictions <- predict(model, newdata = dfTest, type = "class")
  confusion_matrix <- table(predictions, dfTest$Outcome)
  TP <- confusion_matrix[2, 2]  # True Positive
  TN <- confusion_matrix[1, 1]  # True Negative
  FP <- confusion_matrix[1, 2]  # False Positive
  FN <- confusion_matrix[2, 1]  # False Negative
  
  Accuracy<-(TP+TN)/(TP+TN+FP+FN)
  cat("Độ chính xác:",Accuracy,"\n")
  
  #trong số bệnh nhân thực tế bị bệnh tiểu đường,bao nhiêu phần trăm được dự báo bị bệnh
  Sensitivity<-TP/(TP+FN)
  cat("Độ nhạy:",Sensitivity,"\n")
  #trong số bệnh nhân thực tế không bị bệnh, bao nhiêu phần trăm được dự báo không bị bệnh
  
  Specificity<-TN/(TN+FP)
  cat("Độ đặc hiệu",Specificity)
}

Xây dựng mô hình cây quyết định

Mô hình cây quyết định

Xây dựng mô hình cây quyết định ban đầu. Với thuộc tính mục tiêu là Outcome, và biến thành phần và các thuộc tính còn lại của tập dữ liệu

# Huấn luyện mô hình cây quyết định
library(rpart)
model <- rpart(Outcome ~ Pregnancies + Glucose + BloodPressure + SkinThickness + Insulin + BMI + DiabetesPedigreeFunction + Age, data = dfTrain, method = "class")

# In cây quyết định
print(model)
## n= 570 
## 
## node), split, n, loss, yval, (yprob)
##       * denotes terminal node
## 
##   1) root 570 202 0 (0.64561404 0.35438596)  
##     2) Glucose< 127.5 369  75 0 (0.79674797 0.20325203)  
##       4) Age< 29.5 216  23 0 (0.89351852 0.10648148) *
##       5) Age>=29.5 153  52 0 (0.66013072 0.33986928)  
##        10) BMI< 26.95 33   1 0 (0.96969697 0.03030303) *
##        11) BMI>=26.95 120  51 0 (0.57500000 0.42500000)  
##          22) Glucose< 106.5 62  17 0 (0.72580645 0.27419355) *
##          23) Glucose>=106.5 58  24 1 (0.41379310 0.58620690)  
##            46) BloodPressure>=85 12   3 0 (0.75000000 0.25000000) *
##            47) BloodPressure< 85 46  15 1 (0.32608696 0.67391304)  
##              94) SkinThickness>=13.5 27  12 1 (0.44444444 0.55555556)  
##               188) DiabetesPedigreeFunction< 0.5485 15   4 0 (0.73333333 0.26666667) *
##               189) DiabetesPedigreeFunction>=0.5485 12   1 1 (0.08333333 0.91666667) *
##              95) SkinThickness< 13.5 19   3 1 (0.15789474 0.84210526) *
##     3) Glucose>=127.5 201  74 1 (0.36815920 0.63184080)  
##       6) BMI< 30.2 54  20 0 (0.62962963 0.37037037)  
##        12) Age>=56 10   0 0 (1.00000000 0.00000000) *
##        13) Age< 56 44  20 0 (0.54545455 0.45454545)  
##          26) Age< 26.5 14   2 0 (0.85714286 0.14285714) *
##          27) Age>=26.5 30  12 1 (0.40000000 0.60000000) *
##       7) BMI>=30.2 147  40 1 (0.27210884 0.72789116)  
##        14) Glucose< 157.5 88  33 1 (0.37500000 0.62500000)  
##          28) BMI< 41.65 69  32 1 (0.46376812 0.53623188)  
##            56) Age< 31 26   7 0 (0.73076923 0.26923077) *
##            57) Age>=31 43  13 1 (0.30232558 0.69767442) *
##          29) BMI>=41.65 19   1 1 (0.05263158 0.94736842) *
##        15) Glucose>=157.5 59   7 1 (0.11864407 0.88135593) *
# Biểu đồ cây quyết định
library(rpart.plot)
rpart.plot(model)


Xem kết quả dự đoán từ mô hình cây quyết định

thongso()
## Độ chính xác: 0.7473684 
## Độ nhạy: 0.6206897 
## Độ đặc hiệu 0.8030303
Xem độ quan trọng của các thuộc tính trong mô hình

Quan sát biểu đồ mức độ quan trọng của các thuộc tính trong mô hình để thay đổi thuộc tính thành phần

library(vip)
## 
## Attaching package: 'vip'
## The following object is masked from 'package:utils':
## 
##     vi
var_importance <- vip::vip(model, num_features = 10)
print(var_importance)

Quan sát tác động của của các thuộc tính riêng lẻ lên quyết định của mô hình

library(pdp)
library(ggplot2)

# Lặp qua từng cột trong dfTrain (loại bỏ cột mục tiêu)
for (col in names(dfTrain)[-ncol(dfTrain)]) {
  # Tạo Partial Dependence Plot cho từng cột và lưu vào biến pdp_plot
  pdp_plot <- partial(model, pred.var = col)
  
  # Tạo biểu đồ Partial Dependence Plot và hiển thị
  plot(pdp_plot, main = paste("Partial Dependence Plot for", col))
}


Dựa vào biểu đồ mức độ quan trọng của các thuộc tính trong mô hình ta thấy rằng:
- Các thuộc tính Pregnancies, BloodPressure, SkinThickness, Insulin có trọng số thấp nhất.
Dựa vào Partial Dependence Plot (PDP) - Biểu đồ phụ thuộc một phần thấy rằng:
- Các thuộc tính Pregnancies, BloodPressure, SkinThickness, Insulin tăng lên nhưng không ảnh hưởng đến kết quả dự đoán của mô hình.

Loại bỏ các thuộc tính trên (Pregnancies, SkinThickness, Insulin)

Loại bỏ thuộc tính Insulin, SkinThickness và Pregnancies thấy mô hình tăng độ chính xác, độ nhạy và độ đặc hiệu. Quyết định chấp nhận mô hình với độ chính xác ~76% và độ nhạy ~0.64, độ đặc hiệu ~0.82

model <- rpart(Outcome ~ Glucose + BloodPressure + BMI + DiabetesPedigreeFunction + Age, data = dfTrain, method = "class")
rpart.plot(model)


Thông số của mô hình sau khi loại bỏ các thuộc tính có độ quan trọng thấp

accuracy()
##            
## predictions   0   1
##           0 106  23
##           1  22  39
## [1] 0.7631579
thongso()
## Độ chính xác: 0.7631579 
## Độ nhạy: 0.6393443 
## Độ đặc hiệu 0.8217054
Trích xuất các luật từ cây quyết định

Xem quy luật của mô hình cây quyết định

rules <- rpart.rules(model)
print(rules)
##  Outcome                                                                                     
##     0.00 when Glucose >=        128 & BMI <  30       & Age >=       56                      
##     0.03 when Glucose <  128        & BMI <  27       & Age >=       30                      
##     0.11 when Glucose <  128                          & Age <  30                            
##     0.14 when Glucose >=        128 & BMI <  30       & Age <  27                            
##     0.25 when Glucose is 107 to 128 & BMI >=       27 & Age >=       30 & BloodPressure >= 85
##     0.27 when Glucose is 128 to 158 & BMI is 30 to 42 & Age <  31                            
##     0.27 when Glucose <  107        & BMI >=       27 & Age >=       30                      
##     0.60 when Glucose >=        128 & BMI <  30       & Age is 27 to 56                      
##     0.67 when Glucose is 107 to 128 & BMI >=       27 & Age >=       30 & BloodPressure <  85
##     0.70 when Glucose is 128 to 158 & BMI is 30 to 42 & Age >=       31                      
##     0.88 when Glucose >=        158 & BMI >=       30                                        
##     0.95 when Glucose is 128 to 158 & BMI >=       42

So sánh hiệu suất của mô hình hồi quy logistic với mô hình cây quyết định ta thấy :

-> Hai mô hình cho thấy độ chính xác và độ đặc hiệu khá giống nhau -> Nhưng độ nhạy lại khác nhau.Mô hình hồi quy logistic có độ nhạy lớn hơn cho thấy mô hình nhận dạng các trường hợp bị bệnh chính xác hơn

-> Đối với các bài toán dự báo bệnh thì độ nhạy lớn sẽ tốt hơn. Điều này là do độ nhạy là thước đo về mức độ tốt của mô hình trong việc dự đoán các trường hợp dương tính. Trong các bài toán dự báo bệnh, việc xác định chính xác các trường hợp mắc bệnh là rất quan trọng. Nếu mô hình có độ nhạy thấp, thì mô hình sẽ có xu hướng bỏ sót các trường hợp mắc bệnh, điều này có thể dẫn đến việc điều trị sai hoặc không điều trị.

Classifying the categories of Mass (BMI) using Random Forest model

The World Health Organization (WHO) classifies adults based on the following BMI ranges:

  • Underweight: < 18.5 kg/m^2

  • Normal weight: 18.5 - 24.9 kg/m^2

  • Overweight: 25.0 - 29.9 kg/m^2

  • Obese: ≥ 30.0 kg/m^2

library(ggplot2)
diabetes_filter$BMI_Category <- cut(diabetes_filter$BMI, 
                             breaks = c(-Inf, 18.5, 24.9, 29.9, Inf), 
                             labels = c("Underweight", "Normal", "Overweight", "Obese"))

Trực quan phân bố của từng loại cân nặng

ggplot(diabetes_filter, aes(x = BMI_Category)) + 
  geom_bar(stat = "count") +
  labs(title = "Distribution of BMI Categories", x = "BMI Category", y = "Count") +
  theme_bw()

Tạo một dataframe bản sao với BMI_Category đã được số hóa

num_diabetes <- diabetes_filter
num_diabetes$BMI_Category <- as.integer(num_diabetes$BMI_Category)
str(num_diabetes)
## 'data.frame':    760 obs. of  10 variables:
##  $ Pregnancies             : int  6 1 8 1 0 5 3 10 2 8 ...
##  $ Glucose                 : int  148 85 183 89 137 116 78 115 197 125 ...
##  $ BloodPressure           : int  72 66 64 66 40 74 50 0 70 96 ...
##  $ SkinThickness           : int  35 29 0 23 35 0 32 0 45 0 ...
##  $ Insulin                 : int  0 0 0 94 168 0 88 0 543 0 ...
##  $ BMI                     : num  33.6 26.6 23.3 28.1 43.1 25.6 31 35.3 30.5 0 ...
##  $ DiabetesPedigreeFunction: num  0.627 0.351 0.672 0.167 2.288 ...
##  $ Age                     : int  50 31 32 21 33 30 26 29 53 54 ...
##  $ Outcome                 : int  1 0 1 0 1 0 1 0 1 1 ...
##  $ BMI_Category            : int  4 3 2 3 4 3 4 4 4 1 ...

Tìm các biến độc lập so với biến phụ thuộc BMI_Category

library(lattice)
library(reshape2)

# creating correlation matrix
corr_mat <- round(cor(num_diabetes),2)

# reduce the size of correlation matrix
melted_corr_mat <- melt(corr_mat)
# head(melted_corr_mat)

# plotting the correlation heatmap
library(ggplot2)
ggplot(data = melted_corr_mat, aes(x=Var1, y=Var2, fill=value)) + geom_tile() +
  geom_text(aes(Var2, Var1, label = value), color = "white", size = 4)

Ta có thể thấy:

  • So với BMI_Category, các thuộc tính BMI, Insulin, SkinThickness, BloodPressure và Glucose đều tương quan mạnh (5 thuộc tính)

  • Vậy thuộc tính BMI_Category sẽ phụ thuộc nhiều vào chúng, ta có thể xem chúng là các biến độc lập

Xây mô hình Random Forest để phân loại cân nặng

Chia dữ liệu thành huấn luyện và kiểm tra. 70% dành cho huấn luyện, 30% dành cho kiểm tra.

set.seed(456)

samp <- sample(nrow(diabetes_filter), 0.7 * nrow(diabetes_filter))

train <- diabetes_filter[samp, ]

test <- diabetes_filter[-samp, ]
#Kiểm tra kích thước của tập dữ liệu huấn luyện và kiểm tra
str(train)
## 'data.frame':    532 obs. of  10 variables:
##  $ Pregnancies             : int  7 8 1 0 12 7 7 8 0 5 ...
##  $ Glucose                 : int  137 194 84 119 92 136 161 196 93 115 ...
##  $ BloodPressure           : int  90 80 64 66 62 74 86 76 60 76 ...
##  $ SkinThickness           : int  41 0 23 27 7 26 0 29 0 0 ...
##  $ Insulin                 : int  0 0 115 0 258 135 0 280 0 0 ...
##  $ BMI                     : num  32 26.1 36.9 38.8 27.6 26 30.4 37.5 35.3 31.2 ...
##  $ DiabetesPedigreeFunction: num  0.391 0.551 0.471 0.259 0.926 0.647 0.165 0.605 0.263 0.343 ...
##  $ Age                     : int  39 67 28 22 44 51 47 57 25 44 ...
##  $ Outcome                 : int  0 0 0 0 1 0 1 1 0 1 ...
##  $ BMI_Category            : Factor w/ 4 levels "Underweight",..: 4 3 4 4 3 3 4 4 4 4 ...
library(randomForest) 
## randomForest 4.7-1.1
## Type rfNews() to see new features/changes/bug fixes.
## 
## Attaching package: 'randomForest'
## The following object is masked from 'package:dplyr':
## 
##     combine
## The following object is masked from 'package:gridExtra':
## 
##     combine
## The following object is masked from 'package:ggplot2':
## 
##     margin

Tìm giá trị tốt nhất cho tham số mtry bằng tuneRF

rf_fit <- tuneRF(
  x = train[, 1:8],
  y = train[, 10],
  metric = "OOBAcc",
  ntreeTry = 100,
  mtryStart = 3,
  stepFactor = 1.5,
  improve = 0.01,
  trace = T,
  plot = T
)
## mtry = 3  OOB error = 1.13% 
## Searching left ...
## mtry = 2     OOB error = 2.07% 
## -0.8333333 0.01 
## Searching right ...
## mtry = 4     OOB error = 0.56% 
## 0.5 0.01 
## mtry = 6     OOB error = 0.38% 
## 0.3333333 0.01 
## mtry = 8     OOB error = 0% 
## 1 0.01

Tìm số cây trong rừng để mô hình cho kết quả tốt nhất với mtry = 3

# Lặp lại quá trình huấn luyện và đánh giá trên các giá trị khác nhau của ntree
error_out_of_bag <- c()

for (ntree in 1:100) {
    # Huấn luyện mô hình
    model <- randomForest(BMI_Category ~ . -Age -Pregnancies, data = train, ntree = ntree, mtry=3)
    
    # Tạo tập oob
    oob <- sample(nrow(train), 0.3 * nrow(train))
    
    # Tính lỗi out_of_bag
    error_out_of_bag[ntree] <- mean(predict(model, train[oob,]) != train[oob,]$BMI_Category)
}

# Vẽ đường cong lỗi
plot(error_out_of_bag, type = "l", col = "red", ylab = "OOB error", xlab="Số cây trong rừng")

Huấn luyện mô hình

model <- randomForest(BMI_Category ~ . -Age -Pregnancies, data = train, ntree = 100, mtry=3)
model
## 
## Call:
##  randomForest(formula = BMI_Category ~ . - Age - Pregnancies,      data = train, ntree = 100, mtry = 3) 
##                Type of random forest: classification
##                      Number of trees: 100
## No. of variables tried at each split: 3
## 
##         OOB estimate of  error rate: 0.75%
## Confusion matrix:
##             Underweight Normal Overweight Obese class.error
## Underweight           7      3          0     0  0.30000000
## Normal                0     70          1     0  0.01408451
## Overweight            0      0        128     0  0.00000000
## Obese                 0      0          0   323  0.00000000

Ta có thể thấy:

  • OOB error tỉ lệ số lần phân loại sai trên tập OOB ở các cây trong rừng, OOB error càng thấp thì độ chính xác càng cao

  • class error là tỉ lệ phân loại sai ở các nhãn trên tập train đã tách OOB

  • Các chỉ số trên có thể khác nhau ở mỗi lần train, vì tập OOB sẽ lấy ngẫu nhiên

Xác thực mô hình của chúng tôi bằng cách sử dụng dữ liệu thử nghiệm

prediction_test <- predict(model, newdata = test)
prediction_train <- predict(model, newdata = train)

table(prediction_train, train$BMI_Category)
##                 
## prediction_train Underweight Normal Overweight Obese
##      Underweight          10      0          0     0
##      Normal                0     71          0     0
##      Overweight            0      0        128     0
##      Obese                 0      0          0   323
table(prediction_test, test$BMI_Category)
##                
## prediction_test Underweight Normal Overweight Obese
##     Underweight           3      0          0     0
##     Normal                2     30          0     0
##     Overweight            0      0         51     0
##     Obese                 0      0          0   142

Hiển thị giá trị dự đoán so với giá trị thực tế

results<-cbind(prediction_test, test$BMI_Category)

head(results)
##    prediction_test  
## 2                3 3
## 5                4 4
## 6                3 3
## 7                4 4
## 11               4 4
## 14               4 4
colnames(results)<-c('pred','real')

results<-as.data.frame(results)

View(results)

Tính độ chính xác của mô hình

accuracy_test <- mean(prediction_test == test$BMI_Category)
accuracy_train <- mean(prediction_train == train$BMI_Category)

paste("độ chính xác trên tập train: ", accuracy_train)
## [1] "độ chính xác trên tập train:  1"
paste("độ chính xác trên tập test: ", accuracy_test)
## [1] "độ chính xác trên tập test:  0.991228070175439"

Bạn có thể thấy rằng độ chính xác của mô hình này là khoảng 99-100 (%), điều này thật tuyệt vời. Bây giờ chúng tôi đã tự động hóa quá trình dự đoán loại cân nặng. Điều này đưa chúng ta đến khả năng theo dõi tình trạng sức khỏa của bệnh nhân và đưa ra chuẩn đoán sớm

kiểm định giả thuyết thống kế

để chứng minh phần trăm mỡ trong cơ thẻ cũng ảnh hướng đến việc có mắc bệnh hay không

Cách 1: One-Sample T-test

giả thuyết BMI (Chỉ số khối cơ thể) trung bình 34 dễ mắc bệnh tiểu đường

library(knitr)
# Vẽ biểu đồ histogram
ggplot(diabetes_filter, aes(x = BMI)) +
  geom_histogram(binwidth = 2, fill = "lightblue", color = "black") + 
  labs(x = "BMI", title = "Histogram of BMI") + theme_minimal() 

# summary statistics
kable(summary(select(diabetes_filter, BMI)), format = "markdown")
BMI
Min. : 0.00
1st Qu.:27.30
Median :32.00
Mean :31.96
3rd Qu.:36.52
Max. :67.10

Giả thuyết BMI trung bình mắc bệnh tiểu đường là 34

\[ H_0: bmi = 34 \]

\[ H_a: bmi \neq 34 \]

\[ t = \frac{\bar{x} - \mu_0}{s/\sqrt{n}} \\ \bar{x} \text{: là giá trị trung bình của mẫu.} \\ \mu_0 \text{: là giá trị trung bình đã biết đến hoặc giả định.} \\ s \text{: là độ lệch chuẩn của mẫu.} \\ n \text{: là kích thước mẫu.} \\ \]

# Tính độ lệch chuẩn của mẫu dữ liệu
standard_deviation <- sd(diabetes_filter$BMI)
print(standard_deviation)
## [1] 7.902608
t.test(num_diabetes[num_diabetes$Outcome==1,6], mu=34)
## 
##  One Sample t-test
## 
## data:  num_diabetes[num_diabetes$Outcome == 1, 6]
## t = 2.4563, df = 263, p-value = 0.01469
## alternative hypothesis: true mean is not equal to 34
## 95 percent confidence interval:
##  34.21895 35.98862
## sample estimates:
## mean of x 
##  35.10379

Kết luận và giải thích

  • Từ đầu ra và từ p.value chúng ta thấy rằng
  • p-value nhỏ mức ý nghĩa 5%.
  • Giống như bất kỳ bài kiểm tra thống kê nào khác , nếu p-value nhỏ hơn mức ý nghĩa thì có thể bác bỏ giả thuyết. –> Dựa vào kết quả kiểm định t-test, có thể kết luận rằng giá trị trung bình thực sự của cột “BMI” không bằng 34, và Ước lượng trung bình của mẫu có thể nằm trong khoảng từ 34.21895 đến 35.98862 với mức tin cậy 95%.

——————————————-

Cách 2: Independent Samples T-test

để chứng minh phần trăm mỡ trong cơ thẻ cũng ảnh hướng đến việc có mắc bệnh hay không

giả thuyết lượng mỡ trong cơ thể (BMI) không ảnh hưởng đến việc có bệnh hay không**

# Vẽ biểu đồ histogram
ggplot(diabetes_filter, aes(x = BMI_Category)) + 
  geom_bar(stat = "count") + 
  labs(title = "Distribution of BMI Categories", x = "BMI Category", y = "Count") + 
  theme_bw()

Giả thuyết tỳ lệ BMI của người bệnh và không bệnh là như nhau

\[ H_0: bmi_0 = bmi_1 \]

\[ H_a: bmi_0 \neq bmi_1 \]

\[ t = \frac{\bar{x}_A - \bar{x}_B}{\sqrt{\frac{s_A^2}{n_A} + \frac{s_B^2}{n_B}}} \\ (\bar{x}_A) \text{: là giá trị trung bình của nhóm A.} \\ (\bar{x}_B) \text{: là giá trị trung bình của nhóm B.} \\ (s_A) \text{: là độ lệch chuẩn của nhóm A.} \\ (s_B) \text{: là độ lệch chuẩn của nhóm B.} \\ (n_A) \text{: là kích thước của nhóm A.} \\ (n_B) \text{: là kích thước của nhóm B.} \\ \]

#lấy ra những người bệnh và không bệnh có chỉ số BMI_Category >= 3
sick <- num_diabetes[num_diabetes$Outcome==1 & num_diabetes$BMI_Category >= 3,6]
normal <- num_diabetes[num_diabetes$Outcome==0 & num_diabetes$BMI_Category >= 3,6]
length(sick)
## [1] 255
length(normal)
## [1] 389
# Tính độ lệch chuẩn của mỗi mẫu dữ liệu
sa <- sd(sick)
print(sa)
## [1] 6.447191
sb <- sd(normal)
print(sb)
## [1] 5.58764
# Kiểm tra đồng nhất về phương sai
result <- var.test(sick, normal)
print(result)
## 
##  F test to compare two variances
## 
## data:  sick and normal
## F = 1.3313, num df = 254, denom df = 388, p-value = 0.01127
## alternative hypothesis: true ratio of variances is not equal to 1
## 95 percent confidence interval:
##  1.066823 1.670255
## sample estimates:
## ratio of variances 
##           1.331325
t.test(normal,sick,var.equal=FALSE)
## 
##  Welch Two Sample t-test
## 
## data:  normal and sick
## t = -5.5659, df = 488.23, p-value = 4.307e-08
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -3.714332 -1.776138
## sample estimates:
## mean of x mean of y 
##  32.94653  35.69176

Kết luận và giải thích

  • Từ đầu ra và từ p.value chúng ta thấy rằng
  • p-value nhỏ hơn mức ý nghĩa 5%.
  • Giống như bất kỳ bài kiểm tra thống kê nào khác , nếu p-value nhỏ hơn mức ý nghĩa thì có thể bác bỏ giả thuyết. –> Dựa vào kết quả kiểm định t-test, có thể kết luận rằng lượng mỡ trong cơ thể có ảnh hưởng đến việc người đó có bệnh tiểu đường .

để chứng minh độ tuổi cũng ảnh hưởng đến việc người đó có bị bệnh tiểu đường hay không.

giả thuyết độ tuổi trung bình mắc bệnh tiểu đường là 35

# Vẽ biểu đồ histogram
ggplot(num_diabetes, aes(x = Age)) +
  geom_histogram(binwidth = 2, fill = "lightblue", color = "black") +
  labs(x = "Age", title = "Histogram of Age") +
  theme_minimal()

# summary statistics
kable(summary(select(diabetes, Age)), format = "markdown")
Age
Min. :21.00
1st Qu.:24.00
Median :29.00
Mean :33.24
3rd Qu.:41.00
Max. :81.00

###giả thuyết độ tuổi trung bình mắc bệnh tiểu đường là 35

\[ H_0: age = 35 \]

\[ H_a: age \neq 35 \]

t.test(num_diabetes[num_diabetes$Outcome==1,8], mu=35)
## 
##  One Sample t-test
## 
## data:  num_diabetes[num_diabetes$Outcome == 1, 8]
## t = 3.1548, df = 263, p-value = 0.001793
## alternative hypothesis: true mean is not equal to 35
## 95 percent confidence interval:
##  35.80157 38.46359
## sample estimates:
## mean of x 
##  37.13258

Kết luận và giải thích

  • Từ đầu ra và từ p.value chúng ta thấy rằng
  • p-value nhỏ mức ý nghĩa 5%.
  • Giống như bất kỳ bài kiểm tra thống kê nào khác , nếu p-value nhỏ hơn mức ý nghĩa thì có thể bác bỏ giả thuyết không. –> Dựa vào kết quả kiểm định t-test, có thể kết luận rằng giá trị trung bình thực sự của cột “Age” không bằng 35, và Ước lượng trung bình của mẫu có thể nằm trong khoảng từ 35.80157 đến 38.46359 với mức tin cậy 95%.