R: الانحدار اللوجستي R

آخر تحديث: 2026-08-26

في الدرس السابق، تعرفنا على الانحدار الخطي — وهو التنبؤ بـالقيم المستمرة (المبيعات، درجة الحرارة). لكن 80% من المشكلات الواقعية تنطوي على أسئلة من نوع «هل» — هل سيقوم المستخدم بإجراء عملية شراء؟ هل سيتم النقر على رابط في رسالة بريد إلكتروني؟ هل سيتخلف المقترض عن سداد القرض؟ في هذا الدرس، سنتعرف على الانحدار اللوجستي — وهو التنبؤ بـالاحتمالات والفئات.

بعد الانتهاء من هذا الدرس، ستتمكن من استخدام لغة R للقيام بما يلي: التنبؤ بفقدان العملاء، والتنبؤ بمعدل النقر على رسائل البريد الإلكتروني، وتقييم الجدارة الائتمانية، ونمذجة اختبارات A/B — مما يغطي 60% من مشكلات التصنيف في علم البيانات.

1. ما ستتعلمه



2. قصة حول التنبؤ بفقدان العملاء

(1) المشكلة: أي العملاء من المرجح أن يتركوا الخدمة؟

شياو تشاو هو محلل بيانات في إحدى شركات SaaS. سأله مديره: "أي العملاء من المرجح أن ينسحبوا الشهر المقبل؟ كيف يمكننا الاحتفاظ بهم قبل أن يحدث ذلك؟"

البيانات: 1,000 عميل؛ المتغيرات = العمر، ومدة الاستخدام، وعدد مرات التواصل مع خدمة العملاء؛ التصنيف = ما إذا كان العميل قد انسحب أم لا.

(2) الحل باستخدام لغة R

R
# 1. Model Building in One Line
model <- glm(churn ~ age + usage + support_calls,
             data = df, family = binomial)

# 2. Probability per row
df$prob <- predict(model, type = "response")

# 3. One-Line Evaluation
library(pROC)
roc_obj <- roc(df$churn, df$prob)
auc(roc_obj)  # [1] 0.85  ← Model Quality

3 أسطر من التعليمات البرمجية → توقع معدل توقف العملاء + جودة النموذج.



3. مبادئ الانحدار اللوجستي

(1) لماذا نحتاج إلى الانحدار اللوجستي؟

100%
graph TB
    A[Y Category 0/1] --> B[Linear regression is not applicable]
    B --> C[We need to map continuous values to 0-1]
    C --> D[Logit Transformation + Sigmoid]
    D --> E[Logistic Regression]
    
    style A fill:#fff3cd
    style B fill:#f8d7da
    style C fill:#d4edda
    style D fill:#cce5ff
    style E fill:#e1d4ff

الانحدار الخطي يتنبأ بالقيم المستمرة، بينما الانحدار اللوجستي يتنبأ بالاحتمالات (0–1).

(2) الصيغ الرياضية

TEXT 📖 للعرض فقط
P(Y=1) = 1 / (1 + e^(-z))
       │      │      │
       │      │      └─ z = β₀ + β₁X₁ + β₂X₂ + ...
       │      └─ e Index
       └─ Sigmoid Function (Range 0-1)

الصيغة المكافئة (تحويل اللوجيت):

TEXT 📖 للعرض فقط
log(P/(1-P)) = β₀ + β₁X₁ + β₂X₂ + ...

الاحتمالات = P / (1-P) = احتمال النجاح / احتمال الفشل.

(3) الدالة السينيّة

R
sigmoid <- function(x) 1 / (1 + exp(-x))

# Examples
sigmoid(0)     # 0.5
sigmoid(2)     # 0.881
sigmoid(-2)    # 0.119
sigmoid(10)    # 0.99995


4. الاستخدام الأساسي لدالة glm()

(1) قواعد النحو

R
glm(formula, data, family = binomial)
المعلمة المعنى
formula y ~ x1 + x2 (مثل lm)
data إطار البيانات
family binomial (التصنيف الثنائي) / gaussian (الخطي) / poisson (العد)

(2) الانحدار اللوجستي الأول

R
# Data
df <- data.frame(
  churn = c(0, 0, 0, 1, 1, 1, 0, 1, 0, 1),
  age = c(25, 30, 35, 50, 55, 60, 28, 58, 32, 65),
  usage = c(80, 70, 60, 30, 20, 10, 75, 15, 65, 5)
)

# Modeling
model <- glm(churn ~ age + usage, data = df, family = binomial)
summary(model)

الناتج:

TEXT 📖 للعرض فقط
Coefficients:
             Estimate Std. Error z value Pr(>|z|)    
(Intercept)   8.452      4.123   2.050   0.0403 *  
age           0.087      0.043   2.023   0.0431 *  
usage        -0.156      0.058  -2.690   0.0072 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(3) تحليل النتائج الست الرئيسية

الحقل المعنى التوضيح
التقدير المعامل (في الفضاء اللوجيتي) معامل موجب → تؤدي الزيادة في هذا المتغير إلى زيادة احتمال انقطاع الخدمة
الخطأ المعياري الخطأ المعياري دقة تقدير المعامل
قيمة z إحصائية z التقدير / الخطأ المعياري
Pr(>|z|) قيمة p احتمال أن يكون المعامل مختلفًا بشكل ذي دلالة إحصائية عن 0
الانحراف الصفر انحراف النموذج الصفر النموذج القائم على المعامل فقط
الانحراف المتبقي الانحراف المتبقي كلما انخفضت القيمة، كان التوافق أفضل
💡 ملاحظة: z value يحل محل قيمة t (تقريب توزيع عادي للعينات الكبيرة)؛ ويشير p < 0.05 إلى أن المعامل ذو دلالة إحصائية.



5. تفسير المعاملات: نسبة الاحتمالات

(1) لماذا نستخدم نسبة الاحتمالات؟

تكون معاملات الانحدار اللوجستي في فضاء اللوجيت، وهو أمر غير بديهي. لذا، يجب تحويلها إلى نسب الاحتمالات (OR) لتسهيل تفسيرها:

R
# odds ratio = exp(Coefficient)
exp(coef(model))
# (Intercept)         age         usage
#   4670.123      1.091      0.856

(2) التفسير باستخدام «أو»

قيمة OR المعنى
OR = 1 المتغير ليس له تأثير
OR > 1 تؤدي الزيادة في المتغير إلى زيادة الاحتمالات (يزداد احتمال وقوع الحدث)
أو < 1 تؤدي الزيادة في المتغير إلى تقليل الاحتمالات (يقل احتمال وقوع الحدث)
R
# age's OR = 1.09
# Analysis: For each 1 year increase in age, churn odds increase by 9%

# usage's OR = 0.86
# Analysis: For each 1 unit increase in usage, churn odds decrease by 14%

(3) فترة الثقة بنسبة 95%

R
exp(confint(model))
#                  2.5 %    97.5 %
# (Intercept)  12.345  12345.678
# age           1.002      1.198
# usage         0.745      0.978

معامل CI لا يشمل 1 → المعامل ذو دلالة إحصائية.



6. التوقعات

(1) المعلمة type

R
# type = "response"  <- Probability (0-1) * Most Commonly Used
predict(model, type = "response")

# type = "link"  <- logit space (Default)
predict(model, type = "link")

(2) التنبؤ في العالم الواقعي

R
# Training Set Predictions
df$prob <- predict(model, type = "response")

# Threshold 0.5 to convert to category
df$pred <- ifelse(df$prob > 0.5, 1, 0)

# New Data Forecasts
new_customers <- data.frame(
  age = c(40, 55, 30),
  usage = c(50, 15, 80)
)
predict(model, new_customers, type = "response")
# [1] 0.123 0.876 0.045
# Analysis: Age 55, Usage 15, probability of customer churn 87.6%

(3) اختيار العتبة

العتبة السيناريوهات التي تنطبق عليها
0.5 الإعداد الافتراضي، تحقيق التوازن بين الدقة والاسترجاع
0.3 تقليل النتائج السلبية الخاطئة (التشخيصات الطبية، الاحتيال)
0.7 تقليل النتائج الإيجابية الخاطئة (البريد العشوائي)
R
# Custom Thresholds
df$pred <- ifelse(df$prob > 0.3, 1, 0)


7. تقييم النموذج: منحنى ROC + مساحة AUC

(1) مصفوفة الارتباك

R
library(caret)

# True vs Forecast
confusionMatrix(
  factor(df$pred),
  factor(df$churn),
  positive = "1"
)

#           Reference
# Prediction  0  1
#         0  50  5
#         1  10 35
# Accuracy: 0.85
# Sensitivity (Recall): 0.875
# Specificity: 0.833

(2) 4 مؤشرات رئيسية

وحدة القياس الصيغة المعنى
الدقة (TP + TN) / الإجمالي الدقة الإجمالية
الدقة TP / (TP+FP) نسبة الحالات التي تم توقع أنها إيجابية والتي تبين أنها إيجابية بالفعل
التذكر (الحساسية) TP / (TP+FN) نسبة الحالات الإيجابية الفعلية التي تم التنبؤ بها بشكل صحيح
F1 2×P×R/(P+R) المتوسط التوافقي لـ P و R

(3) منحنى ROC + مساحة تحت المنحنى (AUC)

R
library(pROC)

# Calculate ROC
roc_obj <- roc(df$churn, df$prob)
auc(roc_obj)
# [1] 0.92  ← The closer we get to 1 The better

# Draw ROC
plot(roc_obj, main = "ROC Curve", col = "blue", lwd = 2)
abline(a = 0, b = 1, lty = 2, col = "gray")  # Random Classification Baseline

# AUC Analysis
# 0.5-0.7: Poor
# 0.7-0.8: Fair
# 0.8-0.9: Good
# 0.9-1.0: Excellent


8. تقسيم مجموعة التدريب/الاختبار

R
library(caret)

# Division 70% Training / 30% Test
set.seed(42)
train_index <- createDataPartition(df$churn, p = 0.7, list = FALSE)
train_data <- df[train_index, ]
test_data <- df[-train_index, ]

# Train a Model
model <- glm(churn ~ age + usage, data = train_data, family = binomial)

# Test Set Predictions
test_data$prob <- predict(model, test_data, type = "response")
test_data$pred <- ifelse(test_data$prob > 0.5, 1, 0)

# Evaluation
confusionMatrix(factor(test_data$pred), factor(test_data$churn), positive = "1")

# True AUC
roc_obj <- roc(test_data$churn, test_data$prob)
auc(roc_obj)


9. متعدد الفئات (متعدد الحدود)

R
# For multi-class classification multinom (requires nnet package)
install.packages("nnet")
library(nnet)

# 3 Categories
df <- data.frame(
  y = c("A", "A", "B", "B", "C", "C"),
  x = c(1, 2, 3, 4, 5, 6)
)

model <- multinom(y ~ x, data = df)
summary(model)

# Forecast
predict(model, type = "class")      # Category
predict(model, type = "probs")      # Probability


10. تجربة عملية: العملية الكاملة للتنبؤ بفقدان العملاء

فيما يلي مثال على مسار عمل كامل يربط بين جميع مفاهيم الانحدار اللوجستي التي تم تناولها في هذا الدرس.

▶ مثال: توقع خسارة 1,000 عميل

R 📖 للعرض فقط
# ============================================
# 1000 Customer Churn Prediction
# Features: The Complete Logistic Regression Workflow
# ============================================

library(ggplot2)
library(dplyr)
library(caret)
library(pROC)

# 1. Prepare data
set.seed(42)
n <- 1000
df <- tibble(
  age = round(rnorm(n, 40, 12)),
  usage = round(rnorm(n, 50, 20)),
  support_calls = sample(0:10, n, replace = TRUE),
  plan = sample(c("Basics", "Advanced", "Company"), n, replace = TRUE,
                prob = c(0.5, 0.3, 0.2))
) |>
  mutate(
    # Probability of attrition: Older, Use less, Many customer service calls -> Prone to churn
    logit_p = -3 + 0.03 * age - 0.05 * usage + 0.3 * support_calls,
    p = 1 / (1 + exp(-logit_p)),
    churn = rbinom(n, 1, p)
  ) |>
  select(-logit_p, -p)

cat("=== Data Preview ===\n")
print(head(df, 3))
cat("\nChurn rate:", round(mean(df$churn) * 100, 2), "%\n")

# 2. Training/Test Set Partitioning
set.seed(42)
train_index <- createDataPartition(df$churn, p = 0.7, list = FALSE)
train_data <- df[train_index, ]
test_data <- df[-train_index, ]

cat("\nTraining Set:", nrow(train_data), "rows\n")
cat("Test Set:", nrow(test_data), "rows\n\n")

# 3. Train a Model
model <- glm(churn ~ age + usage + support_calls + plan,
             data = train_data, family = binomial)
cat("=== Model Summary ===\n")
summary(model)

# 4. Explanation of Coefficients
cat("\n=== Coefficient odds ratio ===\n")
or_df <- tidy(model, conf.int = TRUE, exponentiate = TRUE)
print(or_df |> select(term, estimate, std.error, p.value, conf.low, conf.high))

# 5. Training Set Predictions
train_data$prob <- predict(model, type = "response")
train_data$pred <- ifelse(train_data$prob > 0.5, 1, 0)

# 6. Test Set Predictions
test_data$prob <- predict(model, test_data, type = "response")
test_data$pred <- ifelse(test_data$prob > 0.5, 1, 0)

# 7. Training Set Evaluation
cat("\n=== Training Set Evaluation ===\n")
train_cm <- confusionMatrix(factor(train_data$pred), factor(train_data$churn),
                             positive = "1")
print(train_cm)

# 8. Test Set Evaluation
cat("\n=== Test Set Evaluation ===\n")
test_cm <- confusionMatrix(factor(test_data$pred), factor(test_data$churn),
                            positive = "1")
print(test_cm)

# 9. ROC + AUC
cat("\n=== AUC ===\n")
roc_train <- roc(train_data$churn, train_data$prob)
roc_test <- roc(test_data$churn, test_data$prob)
cat("Training Set AUC:", round(auc(roc_train), 3), "\n")
cat("Test Set AUC:", round(auc(roc_test), 3), "\n")

# 10. Draw ROC
plot(roc_test, main = "ROC Curve", col = "blue", lwd = 2)
abline(a = 0, b = 1, lty = 2, col = "gray")
legend("bottomright",
       legend = paste0("AUC = ", round(auc(roc_test), 3)),
       col = "blue", lwd = 2)

# 11. Threshold Analysis
cat("\n=== Threshold Analysis ===\n")
thresholds <- seq(0.1, 0.9, by = 0.1)
threshold_results <- lapply(thresholds, function(t) {
  pred <- ifelse(test_data$prob > t, 1, 0)
  cm <- confusionMatrix(factor(pred), factor(test_data$churn), positive = "1")
  data.frame(
    threshold = t,
    precision = cm$byClass["Precision"],
    recall = cm$byClass["Sensitivity"],
    f1 = cm$byClass["F1"]
  )
}) |> bind_rows()
print(threshold_results)

# 12. Identify high-risk customers
cat("\n=== High-Risk Clients Top 5 (Probability of attrition > 70%) ===\n")
high_risk <- test_data |>
  filter(prob > 0.7) |>
  arrange(desc(prob)) |>
  head(5) |>
  select(age, usage, support_calls, plan, prob, pred)
print(high_risk)

# 13. Probability Distribution Chart
ggplot(test_data, aes(x = prob, fill = factor(churn))) +
  geom_histogram(bins = 30, alpha = 0.7, position = "identity") +
  labs(title = "Probability Distribution of Attrition (Sorted by True label)",
       x = "Predict the Probability of Churn", y = "Frequency", fill = "True label") +
  scale_fill_brewer(palette = "Set1", labels = c("Not churned", "Churned")) +
  theme_minimal()

# 14. Save Model
saveRDS(model, "churn_model.rds")
cat("\n=== The model has been saved: churn_model.rds ===\n")
85 سطر من الكود المنطقي (تجاوز الحد 40, للعرض فقط)

النتائج المتوقعة (مقتطف):

TEXT 📖 للعرض فقط
=== Training Set Evaluation ===
Confusion Matrix:
          Reference
Prediction   0   1
         0 525  42
         1  18 115
Accuracy: 0.91
Sensitivity: 0.733
Specificity: 0.967

=== Test Set Evaluation ===
Accuracy: 0.89
AUC = 0.92


❓ أسئلة شائعة

س ما الفرق بين الانحدار اللوجستي والانحدار الخطي؟
ج إذا كانت المتغير المستهدف Y متغيرًا مستمرًا، فاستخدم lm()؛ وإذا كانت Y متغيرًا ثنائي القيمة (0/1)، فاستخدم glm(family = binomial).
س ما هي القيمة الجيدة لمؤشر AUC؟
ج 0.5 = عشوائي؛ 0.7–0.8 = متوسط؛ 0.8–0.9 = جيد؛ 0.9+ = ممتاز.
س ما الذي يجب أن أستخدمه للتصنيف متعدد الفئات؟
ج استخدم nnet::multinom() (الانحدار اللوجستي متعدد الفئات) أو caret (الاختيار التلقائي للنموذج). وفي حالة وجود ثلاث فئات أو أكثر، فكر في استخدام نموذج «الغابة العشوائية» (Random Forest).

📖 ملخص


📝 تمارين

  1. تمرين أساسي: أنشئ إطار بيانات (200 صفًا، 4 أعمدة: معدل ترك الخدمة + العمر + الاستخدام + مكالمات الدعم)، وقم ببناء نموذج باستخدام glm، وفسر جميع النتائج باستخدام summary، واحسب نسبة الاحتمالات باستخدام exp(coef(model)).

  2. تمرين أساسي: باستخدام النموذج الوارد في السؤال السابق، قم بالتنبؤ بمجموعة التدريب باستخدام predict(type = "response")، وارسم رسمًا بيانيًّا توزيعيًّا يوضح التسميات الفعلية مقابل الاحتمالات المتوقعة، وتأكد من أن الانحدار اللوجستي يُنتج احتمالات (0–1).

  3. تمرين أساسي: باستخدام النموذج الوارد في السؤال السابق، ارسم منحنى ROC باستخدام pROC::roc() واحسب مساحة تحت المنحنى (AUC). تحقق من أن قيمة AUC تتراوح بين 0.7 و0.9 تشير إلى أن النموذج جيد.

  4. مشكلة متقدمة: استخدم مجموعة البيانات mtcars لإنشاء مشكلة تصنيف ثنائي (vs تمثل نوع المحرك 0/1)، وقم ببناء نموذج باستخدام glm(vs ~ mpg + wt, family = binomial)، وقم بتقسيم البيانات بنسبة 70/30، واحسب قيمة AUC ومصفوفة الارتباك لمجموعة الاختبار.

  5. التحدي: التنبؤ الشامل بانسحاب العملاء — محاكاة 1,000 عميل (4 سمات + 1 تصنيف). سير العمل الكامل: ① الاستكشاف ② التقسيم ③ النمذجة ④ التقييم (مصفوفة الارتباك + منحنى ROC + مساحة AUC) ⑤ تحليل عتبة ⑥ تحديد العملاء ذوي المخاطر العالية ⑦ رسم توزيع الاحتمالات ⑧ حفظ النموذج. احفظ لقطات شاشة للعملية.

Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%