Machine Learning: تقليل الأبعاد
آخر تحديث: 2026-08-26
في الفضاء عالي الأبعاد، كل نقطة بعيدة عن كل نقطة أخرى — تقليل الأبعاد ليس مجرد ضغط، إنه طريقة لكشف البنية الحقيقية لبياناتك.
1. ما ستتعلمه
- لعنة الأبعاد: انهيار المسافة وندرة البيانات في الفضاءات عالية الأبعاد
- PCA (تحليل المكونات الرئيسية): مصفوفات التغاير، تحليل القيم الذاتية، نسبة التباين المفسّر
- التصور manifold لـ t-SNE: معامل الحيرة، تباعد KL، رسم الخرائط من أبعاد عالية إلى 2D/3D
- نظرة سريعة على UMAP: بديل أسرع لـ t-SNE يحافظ على البنية العامة
- دراسة حالة لسلوك مستخدمي التجارة الإلكترونية: ميزات سلوك 50-بعدًا → تصور 2D يكشف شرائح مستخدمين طبيعية
2. قصة حقيقية من عالم بيانات
(1) الألم: بيانات سلوك المستخدم 50-بعدًا لا يمكنك رؤيتها أو فهمها
جمع Bob 50 ميزة سلوكية للمستخدم (مدة الجلسة، عدد النقرات، نسب التفاعل لكل فئة، وما إلى ذلك)، لكنه لم يستطع فهم كيفية توزيع المستخدمين بشكل حدسي — الجداول غير قابلة للقراءة، رسوم التشتت تصل إلى بُعدين، ونتائج التجميع كانت صعبة التحقق. البيانات عالية الأبعاد صندوق أسود للحدس البشري.
(2) الإصلاح: PCA + t-SNE
يضغط PCA البيانات إلى بعدين مع الحفاظ على أقصى تباين، ويرسم t-SNE البنية المحلية على مستوى 2D — مما يجعل البيانات عالية الأبعاد شيئًا يمكنك فعلًا رؤيته.
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) ظواهر غير بديهية في الفضاء عالي الأبعاد
- انهيار المسافة: في الفضاء عالي الأبعاد، تتقارب المسافة إلى أقرب نقطة والمسافة إلى أبعد نقطة نحو نفس القيمة
- ندرة البيانات: ينمو الحجم أسيًا مع البُعد، لذلك يصبح عدد ثابت من العينات أكثر ندرة
- مخاطرة فرط التجهيز: عندما تكون الميزات >> العينات، تميل النماذج إلى "حفظ الضوضاء"
▶ مثال: تجربة لعنة الأبعاد
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:
# 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 تحليل القيم الذاتية لإيجاد اتجاهات أقصى تباين (المكونات الرئيسية) ويُسقط البيانات على فضاء ذي أبعاد أقل.
graph TB
INPUT[بيانات موحدة] --> COV[حساب مصفوفة التغاير]
COV --> EIG[تحليل القيم الذاتية]
EIG --> SELECT[اختر أعلى K متجهات ذاتية]
SELECT --> PROJECT[إسقاط البيانات إلى K أبعاد]
PROJECT --> OUTPUT[تمثيل منخفض الأبعاد]
▶ مثال: تقليل PCA ونسبة التباين المفسّر
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:
Explained variance ratio:
(2) اختيار عدد المكونات التي يجب الاحتفاظ بها
▶ مثال: رسم التباين المفسّر التراكمي
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:
# 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
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:
# Runs successfully
(2) ما يجب الانتباه إليه في t-SNE
| الاعتبار | ملاحظات |
|---|---|
| perplexity | عادة 5-50. أصغر → يركز على الجيران القريبين؛ أكبر → يركز على البنية العامة |
| البذرة العشوائية | بذور مختلفة يمكن أن تعطي نتائج مختلفة — اضبط random_state |
| ليس للاستخدام اللاحق | t-SNE لا يحافظ على المسافات، لذلك غير مناسب كمدخلات للنموذج |
| بطيء في الحساب | لمجموعات البيانات الكبيرة (>10k)، قلل الأبعاد بـ PCA أولًا، ثم شغّل t-SNE |
| حجم المجموعات لا معنى له | يمكن لـ t-SNE تضخيم أو تقليص الأحجام النسبية للمجموعات |
▶ مثال: تسريع t-SNE بالمعالجة المسبقة بـ PCA
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:
# Runs successfully
6. عملي: تقليل الأبعاد لسلوك مستخدمي التجارة الإلكترونية
▶ مثال: ميزات المستخدم 50-بعدًا → تصور 2D
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:
# Runs successfully
(1) PCA مقابل t-SNE مقابل UMAP
| الجانب | PCA | t-SNE | UMAP |
|---|---|---|---|
| ما يحافظ عليه | التباين العام | الجوار المحلية | العامة + المحلية |
| السرعة | سريع (<1 ثانية) | بطيء (دقائق) | متوسط (ثوانٍ) |
| قابلية التكرار | حتمية | تعتمد على البذرة | تعتمد على البذرة |
| قابلية التفسير | عالية (التباين المفسّر) | منخفضة | متوسطة |
| الاستخدام اللاحق | ✅ قابل للاستخدام كميزات | ❌ تصور فقط | ⚠️ يحتاج تحققًا |
| رسم خرائط بيانات جديدة | ✅ transform | ❌ يجب إعادة التشغيل | ✅ transform |
❓ أسئلة شائعة
pip install umap-learn.cumsum(explained_variance_ratio_) لاتخاذ القرار.📖 ملخص
- لعنة الأبعاد: تنهار المسافات، وتصبح البيانات متفرقة، وترتفع مخاطرة فرط التجهيز — تقليل الأبعاد ضروري
- PCA: يحافظ على اتجاهات أقصى تباين؛ رائع للتقليل السريع ومدخلات النموذج، لكن يجب التوحيد أولًا
- t-SNE: يحافظ على علاقات الجوار المحلية؛ مثالي للتصور، لكن غير قابل للاستخدام كميزات نموذج وبطيء في الحساب
- UMAP: بديل t-SNE أسرع، يحافظ على البنية العامة، ويدعم رسم خرائط البيانات الجديدة
- خط أنابيب نموذجي: StandardScaler → PCA (تسريع + إزالة الضوضاء) → t-SNE/UMAP (تصور)
- اختيار عدد مكونات PCA: انظر إلى نسبة التباين المفسّر التراكمية؛ 90-95% عتبة شائعة
📝 تمارين
- أساسي (الصعوبة ⭐): شغّل PCA على مجموعة بيانات Iris لتقليلها إلى بعدين، وارسم رسم تشتت، وعلّق على نسبة التباين المفسّر. تلميح:
PCA(n_components=2)+ scatter. - متوسط (الصعوبة ⭐⭐): على بيانات
load_digits(64 بُعدًا)، قلل أولًا إلى 30 بُعدًا بـ PCA، ثم إلى بُعدين بـ t-SNE. قارن وقت التشغيل وجودة التصور بين t-SNE المباشر مقابل PCA + t-SNE. تلميح: قِس الوقت بـtime.time(). - تحدي (الصعوبة ⭐⭐⭐): ولّد بيانات 50-بعدًا مع 3 مجموعات مستخدمين، وقللها إلى 2D باستخدام PCA و t-SNE و UMAP على التوالي، وقيم باستخدام تجميع K-Means (ARI/NMI) لتحديد الطريقة التي تحافظ بشكل أفضل على بنية المجموعة الأصلية. تلميح:
sklearn.metrics.adjusted_rand_score.
← الدرس السابق: التعلم الجماعي | الدرس التالي: أساسيات NLP →