انتقل إلى المحتوى الرئيسي

مرحلة التعلم الخاضع للإشراف

قبل أن يتمكن AlphaGo من اللعب الذاتي، كان يحتاج أولاً إلى "مشاهدة" كمية كبيرة من سجلات اللعب البشرية. تسمى هذه العملية التعلم الخاضع للإشراف.

من خلال تحليل 30 مليون موقف من اللعب البشري، حققت شبكة Policy Network في AlphaGo دقة تنبؤ 57% — قادرة على تخمين الحركة التالية لخبير بشري في أكثر من نصف الحالات.

قد لا يبدو هذا مثيراً للإعجاب، لكن بالنظر إلى أن كل موقف لديه في المتوسط 250 حركة قانونية، فهذا إنجاز مذهل.


لماذا نبدأ من سجلات اللعب البشرية؟

نقطة بداية التعلم

تخيل أنك تريد تعليم شخص لا يعرف شيئاً عن الجو. ماذا ستفعل؟

الخيار أ: الاستكشاف العشوائي

دعه يلعب عشوائياً، ليكتشف تدريجياً ما هي الحركة الجيدة
← كفاءة منخفضة جداً، قد لا يتعلم أبداً

الخيار ب: مشاهدة كيف يلعب الخبراء

دعه يشاهد كمية كبيرة من مباريات اللاعبين المحترفين، ويقلد طريقة لعبهم
← بعد وضع الأساس، يستكشف بنفسه

اختار AlphaGo الخيار ب. التعلم الخاضع للإشراف هو النسخة الرياضية من "مشاهدة كيف يلعب الخبراء".

قيمة سجلات اللعب البشرية

أمضى البشر آلاف السنين في تطوير نظرية الجو. كل هذه المعرفة مشفرة في سجلات اللعب:

  • الجوسيكي (الأنماط الافتتاحية): طرق اللعب الافتتاحية التي تم التحقق منها على مدى فترة طويلة
  • تكتيكات الوسط: حكمة التحول بين الهجوم والدفاع
  • مهارات النهاية: جوهر حساب النقاط
  • الرؤية الشاملة: حدس الحكم العام

يتيح التعلم الخاضع للإشراف لـ AlphaGo "وراثة" هذه الحكمة البشرية، دون الحاجة للتجربة من الصفر.


مصدر بيانات التدريب

KGS Go Server

جاءت بيانات تدريب AlphaGo بشكل رئيسي من KGS Go Server (المعروف أيضاً بـ Kiseido Go Server)، وهي منصة جو معروفة على الإنترنت.

خصائص KGS

الخاصيةالوصف
المستخدمونلاعبون هواة بشكل رئيسي، مع بعض المحترفين
نطاق القوةمن المبتدئين إلى المحترفين دان 9
سجلات المبارياتسجلات SGF كاملة محفوظة
فترة النشاطمن 2000 حتى الآن

لماذا اختيار KGS؟

  1. كمية بيانات كبيرة: ملايين سجلات اللعب
  2. تنسيق موحد: تنسيق SGF سهل التحليل
  3. علامات القوة: كل مستخدم له تصنيف
  4. التنوع: لاعبون بأساليب مختلفة

30 مليون موقف

من سجلات KGS، استخرجت DeepMind حوالي 30 مليون موقف:

البيانات الخام:
- حوالي 160,000 سجل لعب
- كل سجل حوالي 200 حركة
- مجموع ~32 مليون موقف

فلترة البيانات:
- فلترة مباريات اللاعبين ذوي الدان المنخفض
- فلترة المواقف من المباريات المستسلمة مبكراً
- في النهاية حوالي 30 مليون موقف عالي الجودة

تنسيق البيانات

كل عينة تدريب تتضمن:

{
"board_state": [[0, 1, 2, ...], ...], # لوحة 19×19
"features": [...], # 48 مستوى ميزة
"next_move": 123, # موقع اللعب البشري (0-360)
"game_result": 1, # 1=فوز الأسود، -1=فوز الأبيض
"player_rank": "5d", # دان اللاعب الذي لعب هذه الحركة
}

معالجة البيانات المسبقة

تحليل SGF

SGF (Smart Game Format) هو التنسيق القياسي لسجلات الجو:

(;GM[1]FF[4]CA[UTF-8]AP[CGoban:3]ST[2]
RU[Japanese]SZ[19]KM[6.50]
PW[White]PB[Black]
;B[pd];W[dd];B[pq];W[dp];B[qk];W[nc]...
)

يجب تحليل:

  • حجم اللوحة (SZ[19])
  • كل حركة (B[pd], W[dd]...)
  • نتيجة المباراة (RE[B+2.5])
def parse_sgf(sgf_string):
"""تحليل سجل SGF"""
moves = []
# استخراج جميع الحركات
pattern = r';([BW])\[([a-s]{2})\]'
for match in re.finditer(pattern, sgf_string):
color = match.group(1) # 'B' or 'W'
coord = match.group(2) # 'pd', 'dd', etc.

# تحويل الإحداثيات
x = ord(coord[0]) - ord('a')
y = ord(coord[1]) - ord('a')

moves.append((color, x, y))

return moves

استخراج الميزات

لكل موقف، استخراج 48 مستوى ميزة (انظر تصميم ميزات المدخلات):

def extract_features(board, history, current_player):
"""استخراج 48 مستوى ميزة"""
features = np.zeros((48, 19, 19))

# مواقع الأحجار
features[0] = (board == 1) # الأحجار السوداء
features[1] = (board == 2) # الأحجار البيضاء
features[2] = (board == 0) # النقاط الفارغة

# السجل التاريخي
for i, hist in enumerate(history[:8]):
features[3+i] = (hist == 1)
features[11+i] = (hist == 2)

# الحريات، الأتاري، اللادر، إلخ...
# (التنفيذ المفصل محذوف)

return features

تعزيز البيانات

لوحة الجو لها 8 تماثلات (4 دورانات × 2 انعكاس). كل عينة أصلية يمكن أن تصبح 8:

الأصلي:

دوران 90°:

دوران 180°:

دوران 270°:

كل منها يُقلب أفقياً، للحصول على 8 عينات تدريب متكافئة

هذا يزيد بيانات التدريب الفعالة 8 مرات، مع ضمان أن الأنماط التي يتعلمها النموذج لا تعتمد على اتجاه معين.

def augment(state, action):
"""تعزيز التماثل الثماني"""
augmented = []

for rotation in [0, 1, 2, 3]: # 0, 90, 180, 270 درجة
rotated_state = np.rot90(state, rotation, axes=(1, 2))
rotated_action = rotate_action(action, rotation)
augmented.append((rotated_state, rotated_action))

# القلب الأفقي
flipped_state = np.flip(rotated_state, axis=2)
flipped_action = flip_action(rotated_action)
augmented.append((flipped_state, flipped_action))

return augmented

دالة الخسارة

خسارة الإنتروبيا المتقاطعة

يستخدم التعلم الخاضع للإشراف خسارة الإنتروبيا المتقاطعة (Cross-Entropy Loss) لتدريب شبكة Policy Network:

L(θ) = -Σ log p_θ(a | s)

حيث:

  • s: حالة اللوحة
  • a: الموقع الذي لعب فيه الإنسان فعلياً (العلامة)
  • p_θ(a | s): احتمال النموذج للتنبؤ بهذا الموقع

الفهم البديهي

خسارة الإنتروبيا المتقاطعة تقيس "الفجوة بين تنبؤ النموذج والعلامة":

السيناريوتنبؤ النموذجالخسارةالشرح
تنبؤ مثالياحتمال a = 1.00الأفضل
واثق وصحيحاحتمال a = 0.90.1جيد جداً
غير متأكد لكن صحيحاحتمال a = 0.50.7مقبول
تنبؤ خاطئاحتمال a = 0.12.3سيء جداً
خاطئ تماماًاحتمال a = 0.014.6الأسوأ

دالة الخسارة تدفع النموذج لزيادة احتمال الموقع الصحيح.

المقارنة مع MSE

لماذا لا نستخدم متوسط مربع الخطأ (MSE)؟

# MSE:
loss_mse = (prediction - target)^2

# Cross-Entropy:
loss_ce = -log(prediction[target])
الخاصيةMSEالإنتروبيا المتقاطعة
نوع الهدفانحدار (قيم مستمرة)تصنيف (توزيع احتمالي)
سلوك التدرجكلما زاد الخطأ، زاد التدرجعند الخطأ الواثق، التدرج أكبر
السيناريو المناسبشبكة Valueشبكة Policy

مخرجات شبكة Policy Network هي توزيع احتمالي لـ 361 فئة، والإنتروبيا المتقاطعة هي الاختيار الطبيعي.


عملية التدريب

تكوين الأجهزة

استخدمت DeepMind موارد حوسبة كبيرة:

الموردالعدد
GPU50
وقت التدريبحوالي 3 أسابيع
حجم الدفعة16
إجمالي خطوات التدريب~340M

المحسّن

استخدام النزول التدرجي العشوائي (SGD) + الزخم:

optimizer = torch.optim.SGD(
model.parameters(),
lr=0.003, # معدل التعلم الأولي
momentum=0.9, # معامل الزخم
weight_decay=1e-4 # تنظيم L2
)

لماذا SGD بدلاً من Adam؟

في عام 2016، كان SGD + momentum لا يزال الخيار السائد لمهام الصور. في الواقع، وجدت الأبحاث اللاحقة (بما في ذلك KataGo) أن محسّنات نوع Adam قد تكون أفضل.

جدولة معدل التعلم

معدل التعلم يتناقص تدريجياً أثناء التدريب:

scheduler = torch.optim.lr_scheduler.StepLR(
optimizer,
step_size=80_000_000, # كل 80M خطوة
gamma=0.1 # معدل التعلم × 0.1
)
معدل التعلم:
0.003 ────────┐
└─────── 0.0003 ────────┐
└─────── 0.00003
80M خطوة 160M خطوة 240M خطوة

حلقة التدريب

def train_epoch(model, dataloader, optimizer):
model.train()
total_loss = 0
correct = 0
total = 0

for batch in dataloader:
states, actions = batch

# التمرير الأمامي
policy = model(states) # (batch, 361)

# حساب الخسارة
loss = F.cross_entropy(policy, actions)

# التمرير الخلفي
optimizer.zero_grad()
loss.backward()
optimizer.step()

# الإحصائيات
total_loss += loss.item()
predictions = policy.argmax(dim=1)
correct += (predictions == actions).sum().item()
total += actions.size(0)

accuracy = correct / total
avg_loss = total_loss / len(dataloader)

return avg_loss, accuracy

منحنى التدريب

عملية التدريب النموذجية:

الدقة
60% | ......**********
| ......*
50% | ......*
| ....*
40% | ..*
|..*
30% |*
+───────────────────────────────────── خطوات التدريب
0 100M 200M 300M 340M

الخسارة والدقة سترتفعان بسرعة، ثم تستقران.


تحليل النتائج

دقة 57%

بعد التدريب الكامل، حققت شبكة Policy Network دقة top-1 بنسبة 57.0%.

ما هي دقة top-1؟

التنبؤ: النموذج يخرج 361 احتمال
Top-1: الموقع ذو أعلى احتمال
الدقة: نسبة هذا الموقع يساوي الموقع الذي لعبه الإنسان فعلياً

57% تعني: النموذج لديه أكثر من نصف الفرصة لتخمين الحركة التالية للخبير البشري.

المقارنة مع برامج أخرى

البرنامجدقة Top-1الملاحظات
الاختيار العشوائي0.4%خط الأساس
ميزات تقليدية + نموذج خطي~24%مستوى 2008
CNN ضحلة~44%مستوى 2014
شبكة Policy Network لـ AlphaGo57%اختراق 2016
AlphaGo Zero~60%2017

CNN العميقة من DeepMind تحسنت بـ 13 نقطة مئوية عن أفضل طريقة سابقة.

تقييم قوة اللعب

قوة اللعب باستخدام شبكة Policy Network وحدها (بدون بحث):

載入中...
التكوينتصنيف Eloالمستوى التقريبي
أقوى تقليدي (Pachi)~2500هاوي دان 4-5
شبكة SL Policy~2800هاوي دان 6-7

التعلم الخاضع للإشراف وحده وصل بالفعل إلى مستوى الهاوي المتقدم، وهذا كان اختراقاً كبيراً في 2016.

الدقة مقابل قوة اللعب

المثير للاهتمام أن الدقة وقوة اللعب ليست علاقة خطية:

الدقة:  44% → 57% (تحسن 13%)
Elo: ~2500 → ~2800 (تحسن ~300)

نسبة تحسن الدقة: 13% / 44% ≈ 30%
نسبة تحسن Elo: 300 / 2500 ≈ 12%

تحسن بسيط في الدقة قد يجلب تحسناً كبيراً في قوة اللعب، لأن:

  • الاختيارات الصحيحة في المواقف الحرجة أكثر أهمية
  • تجنب الأخطاء الواضحة أهم من لعب حركات جيدة إضافية

حدود التعلم الخاضع للإشراف

المشكلة 1: تأثير السقف

التعلم الخاضع للإشراف يمكنه فقط الوصول إلى "المستوى البشري"، لا يمكنه التجاوز:

هدف شبكة SL Policy: تقليد البشر

إذا كان لدى البشر عادات خاطئة

شبكة SL Policy ستتعلم أيضاً هذه الأخطاء

على سبيل المثال، إذا لم يلعب اللاعبون في بيانات التدريب "الحركة 37" غير التقليدية كثيراً، فإن شبكة SL Policy لن تتعلمها أيضاً.

المشكلة 2: عدم القدرة على التمييز بين الحركة الجيدة والسيئة

التعلم الخاضع للإشراف ينظر فقط إلى "ما لعبه الإنسان"، بغض النظر عما إذا كانت الحركة جيدة أم سيئة:

الموقف A: الإنسان لعب K10 (في الواقع حركة سيئة)
الموقف B: الإنسان لعب Q4 (حركة جيدة)

شبكة SL Policy تعاملهما بالتساوي، كلاهما يجب تعلمه

بيانات التدريب تتضمن مباريات لاعبين هواة، فيها الكثير من الأخطاء. شبكة SL Policy ستتعلم هذه الأخطاء.

المشكلة 3: نقص الاستكشاف

شبكة SL Policy تتعلم فقط الحركات المعروفة للبشر:

مجموعة الحركات البشرية: {A, B, C, D, E}

شبكة SL Policy ستختار فقط من هذه الحركات

قد توجد حركة أفضل F، لكنها لم تُكتشف أبداً

هذا هو الحد الأساسي للتعلم الخاضع للإشراف: يمكنه فقط تعلم ما هو موجود في بيانات التدريب.

الحل: التعلم المعزز

للتجاوز على البشر، قام AlphaGo بـ التعلم المعزز بعد التعلم الخاضع للإشراف:

شبكة SL Policy (مستوى بشري)
↓ اللعب الذاتي
شبكة RL Policy (تجاوز البشر)

انظر مقدمة في التعلم المعزز واللعب الذاتي للتفاصيل.


نقاط التنفيذ

كود التدريب الكامل

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, Dataset

class GoDataset(Dataset):
def __init__(self, data_path):
# تحميل البيانات المعالجة مسبقاً
self.states = np.load(f"{data_path}/states.npy")
self.actions = np.load(f"{data_path}/actions.npy")

def __len__(self):
return len(self.states)

def __getitem__(self, idx):
state = torch.FloatTensor(self.states[idx])
action = torch.LongTensor([self.actions[idx]])[0]
return state, action

def train_policy_network():
# النموذج
model = PolicyNetwork(input_channels=48, num_filters=192, num_layers=12)
model = model.cuda()

# البيانات
dataset = GoDataset("data/kgs")
dataloader = DataLoader(
dataset, batch_size=16, shuffle=True, num_workers=4
)

# المحسّن
optimizer = optim.SGD(
model.parameters(),
lr=0.003,
momentum=0.9,
weight_decay=1e-4
)
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=80_000_000, gamma=0.1)

# حلقة التدريب
best_accuracy = 0

for epoch in range(100):
model.train()
total_loss = 0
correct = 0
total = 0

for states, actions in dataloader:
states = states.cuda()
actions = actions.cuda()

# التمرير الأمامي
policy = model(states)
loss = nn.functional.cross_entropy(policy, actions)

# التمرير الخلفي
optimizer.zero_grad()
loss.backward()
optimizer.step()
scheduler.step()

# الإحصائيات
total_loss += loss.item()
predictions = policy.argmax(dim=1)
correct += (predictions == actions).sum().item()
total += actions.size(0)

accuracy = correct / total
print(f"Epoch {epoch}: Loss={total_loss/len(dataloader):.4f}, Acc={accuracy:.4f}")

# حفظ أفضل نموذج
if accuracy > best_accuracy:
best_accuracy = accuracy
torch.save(model.state_dict(), "best_policy.pth")

print(f"Best accuracy: {best_accuracy:.4f}")

كود التقييم

def evaluate_policy(model, test_dataloader):
model.eval()

correct_top1 = 0
correct_top5 = 0
total = 0

with torch.no_grad():
for states, actions in test_dataloader:
states = states.cuda()
actions = actions.cuda()

policy = model(states)

# دقة Top-1
top1_pred = policy.argmax(dim=1)
correct_top1 += (top1_pred == actions).sum().item()

# دقة Top-5
top5_pred = policy.topk(5, dim=1)[1]
for i, action in enumerate(actions):
if action in top5_pred[i]:
correct_top5 += 1

total += actions.size(0)

print(f"Top-1 Accuracy: {correct_top1/total:.4f}")
print(f"Top-5 Accuracy: {correct_top5/total:.4f}")

المشاكل الشائعة والحلول

المشكلةالأعراضالحل
الإفراط في التعلمدقة التدريب عالية، دقة الاختبار منخفضةزيادة تعزيز البيانات، Dropout
تدريب غير مستقرتقلب حاد في الخسارةخفض معدل التعلم، زيادة حجم الدفعة
تقارب بطيءالدقة تتوقف عن التحسنضبط معدل التعلم، فحص البيانات
نقص الذاكرةخطأ OOMتقليل حجم الدفعة، استخدام الدقة المختلطة

مطابقة الرسوم المتحركة

المفاهيم الأساسية المذكورة في هذا المقال ومطابقتها لأرقام الرسوم المتحركة:

الرقمالمفهومالمقابلة الفيزيائية/الرياضية
D3التعلم الخاضع للإشرافتقدير الإمكانية القصوى
D5خسارة الإنتروبيا المتقاطعةتباعد KL
D6النزول التدرجيالتحسين
A6معالجة البيانات المسبقةالتطبيع

قراءة موسعة


النقاط الرئيسية

  1. سجلات KGS هي مصدر بيانات التدريب: حوالي 30 مليون موقف عالي الجودة
  2. خسارة الإنتروبيا المتقاطعة تقود التعلم: تجعل النموذج يزيد احتمال الموقع الصحيح
  3. دقة 57% اختراق كبير: تفوق على أفضل طريقة سابقة بـ 13 نقطة مئوية
  4. تعزيز التماثل الثماني: زيادة فعالة لبيانات التدريب
  5. للتعلم الخاضع للإشراف سقف: لا يمكن تجاوز مستوى بيانات التدريب

التعلم الخاضع للإشراف هو "نقطة البداية" لـ AlphaGo — ورث حكمة الجو البشرية لآلاف السنين، مما وضع الأساس للتعلم المعزز اللاحق.


المراجع

  1. Silver, D., et al. (2016). "Mastering the game of Go with deep neural networks and tree search." Nature, 529, 484-489.
  2. Maddison, C. J., et al. (2014). "Move Evaluation in Go Using Deep Convolutional Neural Networks." arXiv:1412.6564.
  3. Clark, C., & Storkey, A. (2015). "Training Deep Convolutional Neural Networks to Play Go." ICML.
  4. KGS Game Archives: https://www.gokgs.com/archives.jsp