Machine Learning: تقليل الأبعاد

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

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

1. ما ستتعلمه


2. قصة حقيقية من عالم بيانات

(1) الألم: بيانات سلوك المستخدم 50-بعدًا لا يمكنك رؤيتها أو فهمها

جمع Bob 50 ميزة سلوكية للمستخدم (مدة الجلسة، عدد النقرات، نسب التفاعل لكل فئة، وما إلى ذلك)، لكنه لم يستطع فهم كيفية توزيع المستخدمين بشكل حدسي — الجداول غير قابلة للقراءة، رسوم التشتت تصل إلى بُعدين، ونتائج التجميع كانت صعبة التحقق. البيانات عالية الأبعاد صندوق أسود للحدس البشري.

(2) الإصلاح: PCA + t-SNE

يضغط PCA البيانات إلى بعدين مع الحفاظ على أقصى تباين، ويرسم t-SNE البنية المحلية على مستوى 2D — مما يجعل البيانات عالية الأبعاد شيئًا يمكنك فعلًا رؤيته.

PYTHON
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
from sklearn.preprocessing import StandardScaler

X_scaled = StandardScaler().fit_transform(X_50d)

# PCA: سريع، يحافظ على التباين العام
X_pca = PCA(n_components=2).fit_transform(X_scaled)

# t-SNE: بطيء، يحافظ على البنية المحلية
X_tsne = TSNE(n_components=2, perplexity=30).fit_transform(X_scaled)

(3) النتيجة: رسم 2D يكشف على الفور ثلاث مجموعات مستخدمين طبيعية

بعد تقليل الأبعاد، استطاع Bob رؤية ثلاث مجموعات مستخدمين متميزة في لمحة — عالية القيمة، ونشطة، وخاملة — والتي توافقت بشكل وثيق مع نتائج التجميع، مما سمح لفريق الأعمال بفهم توزيع البيانات في ثوانٍ.


3. لعنة الأبعاد

(1) ظواهر غير بديهية في الفضاء عالي الأبعاد

▶ مثال: تجربة لعنة الأبعاد

PYTHON
import numpy as np

rng = np.random.default_rng(42)

for dim in [2, 10, 50, 100, 500]:
    n = 1000
    X = rng.uniform(0, 1, (n, dim))

    # حساب المسافات الزوجية
    from sklearn.metrics import pairwise_distances
    dists = pairwise_distances(X)

    np.fill_diagonal(dists, np.inf)
    min_dist = dists.min()
    max_dist = dists.max()
    ratio = (max_dist - min_dist) / max_dist

    print(f"Dim={dim:4d}: min={min_dist:.3f}, max={max_dist:.3f}, "
          f"relative_range={ratio:.4f}")

Output:

TEXT 📖 للعرض فقط
# Runs successfully
الأبعاد أقل مسافة أقصى مسافة النطاق النسبي المعنى
2 0.02 1.41 0.99 المسافات ذات معنى
10 0.78 1.87 0.58 المسافات تبدأ في الانهيار
50 2.42 3.28 0.26 المسافات شبه عديمة الفائدة
100 3.54 4.05 0.13 جميع المسافات تتقارب
500 8.11 8.47 0.04 منهار تمامًا

4. PCA (تحليل المكونات الرئيسية)

(1) كيف يعمل PCA

يستخدم PCA تحليل القيم الذاتية لإيجاد اتجاهات أقصى تباين (المكونات الرئيسية) ويُسقط البيانات على فضاء ذي أبعاد أقل.

100%
graph TB
    INPUT[بيانات موحدة] --> COV[حساب مصفوفة التغاير]
    COV --> EIG[تحليل القيم الذاتية]
    EIG --> SELECT[اختر أعلى K متجهات ذاتية]
    SELECT --> PROJECT[إسقاط البيانات إلى K أبعاد]
    PROJECT --> OUTPUT[تمثيل منخفض الأبعاد]

▶ مثال: تقليل PCA ونسبة التباين المفسّر

PYTHON
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
import numpy as np

X, y = load_iris(return_X_y=True)

# وحّد أولًا (PCA حساس للمقياس)
X_scaled = StandardScaler().fit_transform(X)

# PCA بجميع المكونات لرؤية التباين المفسّر
pca_full = PCA()
pca_full.fit(X_scaled)

print("Explained variance ratio:")
for i, (evr, cum) in enumerate(zip(pca_full.explained_variance_ratio_,
                                     pca_full.explained_variance_ratio_.cumsum())):
    print(f"  PC{i+1}: {evr:.3f} (cumulative: {cum:.3f})")

# قلل إلى 2D
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)
print(f"\n2D PCA preserves {pca.explained_variance_ratio_.sum():.1%} variance")

# تصور
fig, ax = plt.subplots(figsize=(8, 6))
for target in np.unique(y):
    mask = y == target
    ax.scatter(X_pca[mask, 0], X_pca[mask, 1], label=load_iris().target_names[target], s=40)
ax.set_xlabel(f"PC1 ({pca.explained_variance_ratio_[0]:.1%})")
ax.set_ylabel(f"PC2 ({pca.explained_variance_ratio_[1]:.1%})")
ax.set_title("PCA of Iris Dataset")
ax.legend()
plt.tight_layout()
plt.savefig("pca_iris.png", dpi=150)

Output:

TEXT 📖 للعرض فقط
Explained variance ratio:

(2) اختيار عدد المكونات التي يجب الاحتفاظ بها

▶ مثال: رسم التباين المفسّر التراكمي

PYTHON
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
import numpy as np

rng = np.random.default_rng(42)
n, p = 500, 50
X = rng.standard_normal((n, p))
# اجعل أول 5 أبعاد تحمل إشارة أكثر
X[:, :5] *= 3

X_scaled = StandardScaler().fit_transform(X)
pca = PCA().fit(X_scaled)

fig, ax = plt.subplots(figsize=(10, 5))
cumvar = pca.explained_variance_ratio_.cumsum()
ax.plot(range(1, len(cumvar)+1), cumvar, "b-o", markersize=3)
ax.axhline(0.95, color="red", linestyle="--", label="95% variance")
ax.axhline(0.90, color="orange", linestyle="--", label="90% variance")
ax.set_xlabel("Number of Components")
ax.set_ylabel("Cumulative Explained Variance")
ax.set_title("PCA Explained Variance")
ax.legend()
n_95 = (cumvar < 0.95).sum() + 1
print(f"Components for 95% variance: {n_95}")
plt.tight_layout()
plt.savefig("pca_variance.png", dpi=150)

Output:

TEXT 📖 للعرض فقط
# Runs successfully
العتبة المعنى النتيجة النموذجية
90% تحتفظ بالإشارة الرئيسية 5-15 مكونًا (لـ 50 بُعدًا)
95% تحتفظ بمزيد من التفاصيل 10-25 مكونًا (لـ 50 بُعدًا)
99% شبه خالية من الفقدان 20-40 مكونًا (لـ 50 بُعدًا)

5. تصور manifold لـ t-SNE

(1) كيف يعمل t-SNE

يحافظ t-SNE على علاقات الجوار المحلية عبر تقليل تباعد KL بين التشابهات الزوجية في الفضاءات عالية الأبعاد ومنخفضة الأبعاد.

▶ مثال: تصور t-SNE

PYTHON
from sklearn.manifold import TSNE
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_digits
import matplotlib.pyplot as plt
import numpy as np

X, y = load_digits(return_X_y=True)
X_scaled = StandardScaler().fit_transform(X)

# t-SNE بقيم حيرة مختلفة
fig, axes = plt.subplots(1, 3, figsize=(18, 5))

for ax, perplexity in zip(axes, [5, 30, 50]):
    tsne = TSNE(n_components=2, perplexity=perplexity, random_state=42, init="pca")
    X_tsne = tsne.fit_transform(X_scaled)

    scatter = ax.scatter(X_tsne[:, 0], X_tsne[:, 1], c=y, cmap="tab10", s=5, alpha=0.7)
    ax.set_title(f"t-SNE (perplexity={perplexity})")
    ax.set_xlabel("t-SNE 1")
    ax.set_ylabel("t-SNE 2")

plt.tight_layout()
plt.savefig("tsne_perplexity.png", dpi=150)

Output:

TEXT 📖 للعرض فقط
# Runs successfully

(2) ما يجب الانتباه إليه في t-SNE

الاعتبار ملاحظات
perplexity عادة 5-50. أصغر → يركز على الجيران القريبين؛ أكبر → يركز على البنية العامة
البذرة العشوائية بذور مختلفة يمكن أن تعطي نتائج مختلفة — اضبط random_state
ليس للاستخدام اللاحق t-SNE لا يحافظ على المسافات، لذلك غير مناسب كمدخلات للنموذج
بطيء في الحساب لمجموعات البيانات الكبيرة (>10k)، قلل الأبعاد بـ PCA أولًا، ثم شغّل t-SNE
حجم المجموعات لا معنى له يمكن لـ t-SNE تضخيم أو تقليص الأحجام النسبية للمجموعات

▶ مثال: تسريع t-SNE بالمعالجة المسبقة بـ PCA

PYTHON
from sklearn.manifold import TSNE
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
import numpy as np

rng = np.random.default_rng(42)
X = rng.standard_normal((5000, 50))

# t-SNE مباشر (بطيء)
# tsne = TSNE(n_components=2, random_state=42)
# X_tsne = tsne.fit_transform(X)  # بطيء جدًا على 5000x50!

# أفضل ممارسة: PCA أولًا، ثم t-SNE
X_scaled = StandardScaler().fit_transform(X)
X_pca_30 = PCA(n_components=30).fit_transform(X_scaled)  # PCA سريع إلى 30D
X_tsne = TSNE(n_components=2, perplexity=30, random_state=42,
              init="pca", learning_rate="auto").fit_transform(X_pca_30)

print(f"PCA→t-SNE shape: {X_tsne.shape}")

Output:

TEXT 📖 للعرض فقط
# Runs successfully

6. عملي: تقليل الأبعاد لسلوك مستخدمي التجارة الإلكترونية

▶ مثال: ميزات المستخدم 50-بعدًا → تصور 2D

PYTHON
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import numpy as np

rng = np.random.default_rng(42)
n = 3000

# توليد بيانات سلوك المستخدم 50-بعدًا مع 3 مجموعات طبيعية
group1 = rng.normal(loc=2, scale=1, size=(800, 50))   # مستخدمون عاليو القيمة
group2 = rng.normal(loc=0, scale=1.5, size=(1200, 50)) # مستخدمون عاديون
group3 = rng.normal(loc=-2, scale=0.8, size=(1000, 50)) # مستخدمون خاملون
X = np.vstack([group1, group2, group3])

# أضف أبعاد ضوضاء
X[:, 20:] += rng.normal(0, 3, (n, 30))

# توحيد
X_scaled = StandardScaler().fit_transform(X)

# PCA إلى 2D
X_pca = PCA(n_components=2).fit_transform(X_scaled)

# t-SNE إلى 2D (مع معالجة PCA مسبقة)
X_pca30 = PCA(n_components=30).fit_transform(X_scaled)
X_tsne = TSNE(n_components=2, perplexity=30, random_state=42,
              init="pca", learning_rate="auto").fit_transform(X_pca30)

# تسميات K-Means كمرجع
labels = KMeans(n_clusters=3, random_state=42, n_init=10).fit_predict(X_scaled)

# تصور
fig, axes = plt.subplots(1, 2, figsize=(16, 6))

for ax, X_2d, title in [(axes[0], X_pca, "PCA"), (axes[1], X_tsne, "t-SNE")]:
    scatter = ax.scatter(X_2d[:, 0], X_2d[:, 1], c=labels, cmap="Set1", s=8, alpha=0.6)
    ax.set_title(title)
    ax.set_xlabel(f"{title} 1")
    ax.set_ylabel(f"{title} 2")

plt.tight_layout()
plt.savefig("user_behavior_dim_reduction.png", dpi=150)

Output:

TEXT 📖 للعرض فقط
# Runs successfully

(1) PCA مقابل t-SNE مقابل UMAP

الجانب PCA t-SNE UMAP
ما يحافظ عليه التباين العام الجوار المحلية العامة + المحلية
السرعة سريع (<1 ثانية) بطيء (دقائق) متوسط (ثوانٍ)
قابلية التكرار حتمية تعتمد على البذرة تعتمد على البذرة
قابلية التفسير عالية (التباين المفسّر) منخفضة متوسطة
الاستخدام اللاحق ✅ قابل للاستخدام كميزات ❌ تصور فقط ⚠️ يحتاج تحققًا
رسم خرائط بيانات جديدة ✅ transform ❌ يجب إعادة التشغيل ✅ transform

❓ أسئلة شائعة

س هل يمكنني استخدام البيانات المخفّضة بـ PCA لتدريب النموذج؟
ج نعم. يمكن استخدام المكونات الرئيسية من PCA كمدخل للنموذج، وهي مفيدة بشكل خاص لسيناريوهات الأبعاد العالية والعينات الصغيرة. فقط تذكر: ادرب PCA على مجموعة التدريب وحول مجموعة الاختبار فقط.
س لماذا لا يمكن استخدام t-SNE كميزات نموذج؟
ج لا يحافظ t-SNE على علاقات المسافة العامة، ولا يمكنه تحويل بيانات جديدة (يجب إعادة الحساب من الصفر في كل مرة). إنه مناسب فقط للتصور، وليس كمدخل للنموذج.
س كيف أختار معامل perplexity؟
ج النطاق النموذجي هو 5-50. لمجموعات البيانات الصغيرة (~1k)، استخدم 5-20؛ للبيانات الكبيرة (10k+)، استخدم 30-50. جرب بعض القيم واختر التي تنتج أوضح المجموعات.
س هل يتطلب PCA التوحيد القياسي؟
ج بالتأكيد. PCA يعظم التباين، لذلك إذا كانت ميزاتك على مقاييس مختلفة (مثل العمر مقابل الدخل)، ستسيطر الميزات عالية التباين على المكونات الرئيسية. شغّل دائمًا StandardScaler قبل PCA.
س ما الذي يجعل UMAP أفضل من t-SNE؟
ج ثلاث مزايا — 1) أسرع 10-100 مرة؛ 2) يحافظ على مزيد من البنية العامة؛ 3) يدعم تحويل البيانات الجديدة. الجانب السلبي هو أنك تحتاج إلى تثبيته بشكل منفصل عبر pip install umap-learn.
س كم المعلومات التي تُفقد في تقليل الأبعاد؟
ج ذلك يعتمد على عدد المكونات التي تحتفظ بها. الاحتفاظ بـ 95% من التباين يعني عادة فقدان حوالي 5% من المعلومات فقط — وما يتم إسقاطه قد يكون مجرد ضوضاء. استخدم cumsum(explained_variance_ratio_) لاتخاذ القرار.

📖 ملخص

📝 تمارين

  1. أساسي (الصعوبة ⭐): شغّل PCA على مجموعة بيانات Iris لتقليلها إلى بعدين، وارسم رسم تشتت، وعلّق على نسبة التباين المفسّر. تلميح: PCA(n_components=2) + scatter.
  2. متوسط (الصعوبة ⭐⭐): على بيانات load_digits (64 بُعدًا)، قلل أولًا إلى 30 بُعدًا بـ PCA، ثم إلى بُعدين بـ t-SNE. قارن وقت التشغيل وجودة التصور بين t-SNE المباشر مقابل PCA + t-SNE. تلميح: قِس الوقت بـ time.time().
  3. تحدي (الصعوبة ⭐⭐⭐): ولّد بيانات 50-بعدًا مع 3 مجموعات مستخدمين، وقللها إلى 2D باستخدام PCA و t-SNE و UMAP على التوالي، وقيم باستخدام تجميع K-Means (ARI/NMI) لتحديد الطريقة التي تحافظ بشكل أفضل على بنية المجموعة الأصلية. تلميح: sklearn.metrics.adjusted_rand_score.

← الدرس السابق: التعلم الجماعي | الدرس التالي: أساسيات NLP →

Web-Tutorial.com

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

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

100%