← العودة إلى قائمة المقالات
August 15, 2026
5 دقائق للقراءة

Multi-Task Learning for Simultaneous Price, Volume, and Volatility Prediction

Multi-Task Learning for Simultaneous Price, Volume, and Volatility Prediction
#deep-learning
#multi-task
#shared-representation
#prediction
#auxiliary

عادةً ما يُسوَّق التعلم متعدد المهام (MTL) بادعاء واحد: مشاركة مشفّر بين أهداف مترابطة تحسن المهمة الأساسية. في التداول، الأهداف المترابطة واضحة — العوائد والحجم والتقلب المحقق كلها تنشأ من تدفق الأوامر نفسه — ومع ذلك نادراً ما يُختبر هذا الادعاء. السؤال المهم ليس ما إذا كانت المهام مترابطة، بل ما إذا كانت التدرجات المشتركة متوافقة، وماذا يحدث في الطيات التي لا تكون فيها كذلك.

تضع هذه المقالة أمرين في المركز، بينما تتعامل معظم كتابات MTL معهما كحواشٍ:

  1. موازنة الخسارة هي التجربة وليست تفصيلاً. الأوزان الثابتة، وموازنة عدم اليقين لدى Kendall، وGradNorm هي ثلاثة نماذج مختلفة. شغّل النماذج الثلاثة على الطيات نفسها، وأبلغ عن الأوزان المتعلمة إلى جانب مقياس المهمة الأساسية لكل نموذج.
  2. يمكن قياس النقل السلبي قبل ظهور المقياس. يخبرك تشابه جيب التمام بين تدرجات المهام على المشفّر المشترك، أثناء التدريب، بما إذا كانت المهام المساعدة تسحب التمثيل إلى مكان تريده المهمة الأساسية أم لا. سجّل إشارات قيم جيوب التمام، ثم تحقق مما إذا كانت الإشارة قد تنبأت بالنتيجة في تلك الطية.

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

الإعداد

ثلاثة أهداف سوقية تنبثق من تمثيل كامن مشترك

مع إعطاء سمات الإدخال xRd\mathbf{x} \in \mathbb{R}^d (OHLCV والمؤشرات التقنية وتدفق الأوامر)، توجد ثلاثة أهداف:

  • المهمة 1 (أساسية): عائد الفترة التالية y(1)=rt+1y^{(1)} = r_{t+1}
  • المهمة 2 (مساعدة): لوغاريتم حجم الفترة التالية y(2)=logVt+1y^{(2)} = \log V_{t+1}
  • المهمة 3 (مساعدة): التقلب المحقق للفترة التالية y(3)=σt+1y^{(3)} = \sigma_{t+1}

ينتج نموذج متعدد المهام الأهداف الثلاثة معاً، y^=fθ(x)\hat{\mathbf{y}} = f_\theta(\mathbf{x})، وتكون مخاطرة المهام المتعددة مجموعاً موزوناً لمخاطر كل مهمة:

RMTL(θ)=k=1KwkE[(k)(fθ(k)(x),y(k))]\mathcal{R}_{\text{MTL}}(\theta) = \sum_{k=1}^{K} w_k \cdot \mathbb{E}\bigl[\ell^{(k)}(f_\theta^{(k)}(\mathbf{x}), y^{(k)})\bigr]

تدور المقالة كلها حول wkw_k وحول ما تفعله تدرجات المهام بعضها ببعض.

لماذا قد يفيد التدريب المشترك، في فقرة واحدة. تجبر المهام المساعدة التمثيل المشترك على تفسير أكثر من ظاهرة سوقية، وهذا تحكم في السعة وانحياز استقرائي في الوقت نفسه؛ وبما أن الحجم والتقلب ملحوظان مباشرة بينما "العائد المتوقع" غير ملحوظ، توفر الرؤوس المساعدة إشارة تدرج أنظف من الرأس الأساسي. وقد نوقشت حجة نموذج واحد يصدر مخرجات متعددة بالتفصيل — مع آليات قابلية التفسير — في المحوّلات الاندماجية الزمنية للتنبؤ متعدد الآفاق، التي تقدم الحجة نفسها لمشفّر مشترك ورؤوس متعددة لكمّيات متعددة الآفاق.

البنية باختصار

المشاركة الصلبة للمعلمات: يغذي مشفّر مشترك gϕg_\phi رؤوساً خاصة بـ KK مهام hψkh_{\psi_k}، بحيث تكون y^(k)=hψk(gϕ(x))\hat{y}^{(k)} = h_{\psi_k}(g_\phi(\mathbf{x})). هذه هي النسخة المقاسة هنا، لأنها النسخة التي يكون فيها تعارض التدرجات على ϕ\phi محدداً جيداً.

المشاركة اللينة للمعلمات تمنح كل مهمة مشفّرها الخاص مع عقوبة اقتران λkjϕkϕj2\lambda \sum_{k \neq j} \|\phi_k - \phi_j\|^2 — معلمات أكثر ومرونة أكبر، ومن دون متجه معلمات مشترك واحد يمكن قياس التعارض عليه. وتقع شبكات Cross-stitch بين النهجين، إذ تخلط سمات كل مهمة عبر مصفوفة متعلمة αkj\alpha_{kj} في كل مستوى. يجدر تجربة النهجين إذا أظهرت المشاركة الصلبة تعارضاً، لكن كليهما خارج نطاق القياس أدناه.

التجربة المهمة: ثلاث طرائق لموازنة الخسارة

تدرجات مهام متنافسة موزونة حول نواة عصبية مشتركة

الخسارة الساذجة L=kwkL(k)\mathcal{L} = \sum_k w_k \mathcal{L}^{(k)} حساسة للمقياس. إذا كانت خسارة العائد حول 0.010.01 وخسارة الحجم حول 1.01.0، استحوذ الحجم على التدرج وتجمد رأس العائد. هناك ثلاث استجابات:

الأوزان الثابتة. اضبط wk=1w_k = 1 بعد توحيد كل هدف. هذا هو خط الأساس الصادق — إذا فاز، فالمخططات التكيفية مجرد مراسم.

موازنة عدم اليقين (Kendall وآخرون، 2018). تعلّم مقياس ضوضاء متجانس التباين σk\sigma_k لكل مهمة:

LMTL=k=1K12σk2L(k)+logσk\mathcal{L}_{\text{MTL}} = \sum_{k=1}^{K} \frac{1}{2\sigma_k^2} \mathcal{L}^{(k)} + \log \sigma_k

تحصل المهام ذات عدم اليقين العالي على وزن أقل تلقائياً؛ ويمنع حد logσk\log \sigma_k الحل التافه σk\sigma_k \to \infty. لاحظ أن σk\sigma_k هنا أداة لموازنة وزن الخسارة وقت التدريب، وليست فاصلاً تنبؤياً — ولعدم يقين يمكنك فعلاً استخدامه لتحديد حجم مركز، راجع التنبؤ المطابق.

GradNorm (Chen وآخرون، 2018). وازن مقادير التدرجات بدلاً من مقاييس الخسارة. في كل خطوة: احسب Gk=ϕwkL(k)2G_k = \|\nabla_\phi w_k \mathcal{L}^{(k)}\|_2 والمتوسط Gˉ\bar{G}، واحسب معدل التدريب النسبي r~k=L(k)(t)/L(k)(0)rˉ\tilde{r}_k = \frac{\mathcal{L}^{(k)}(t)/\mathcal{L}^{(k)}(0)}{\bar{r}}، ثم حدّث wkwkηwwkkGkGˉr~kαw_k \leftarrow w_k - \eta_w \nabla_{w_k} \sum_k |G_k - \bar{G} \cdot \tilde{r}_k^\alpha|. عندها تتدرب جميع المهام بمعدلات متقاربة بغض النظر عن مقياس الخسارة.

كود MTL الخاص هو الرؤوس، وforward الذي يعيد قائمة، وتجميع الخسارة. أما مكدس Linear/BatchNorm/ReLU/Dropout، وقوالب Adam/cosine/clip، وحلقة العصور، فهي النمط القياسي الموضح في DeepLOB وقد حُذفت هنا.

import torch
import torch.nn as nn


class MultiTaskTradingModel(nn.Module):
    """Hard parameter sharing: one encoder, K heads."""

    def __init__(self, encoder: nn.Module, repr_dim: int, n_tasks: int = 3):
        super().__init__()
        self.shared_encoder = encoder          # any MLP/CNN/GRU trunk
        self.task_heads = nn.ModuleList(
            nn.Linear(repr_dim, 1) for _ in range(n_tasks)
        )

    def forward(self, x):
        h = self.shared_encoder(x)
        return [head(h).squeeze(-1) for head in self.task_heads]

    def shared_repr(self, x):
        return self.shared_encoder(x)


class UncertaintyWeightedLoss(nn.Module):
    """Kendall et al. (2018) homoscedastic weighting."""

    def __init__(self, n_tasks: int = 3):
        super().__init__()
        self.log_vars = nn.Parameter(torch.zeros(n_tasks))  # log(sigma^2)

    def forward(self, losses: list) -> torch.Tensor:
        return sum(
            torch.exp(-self.log_vars[i]) * loss + self.log_vars[i]
            for i, loss in enumerate(losses)
        )

    def get_weights(self) -> list:
        with torch.no_grad():
            return [torch.exp(-lv).item() for lv in self.log_vars]

تحتوي UncertaintyWeightedLoss على معلمات، ولذلك يجب وضعها في optimizer إلى جانب النموذج: optim.Adam(list(model.parameters()) + list(uw.parameters()), ...). نسيان ذلك هو الطريقة الأكثر شيوعاً لـ "تشغيل موازنة عدم اليقين" مع تشغيل الأوزان الثابتة بصمت.

ما الذي يجب الإبلاغ عنه

لكل مخطط، وفي كل طية: أوزان المهام النهائية المتعلمة، ومقياس المهمة الأساسية، و — لأن مخطط الموازنة خيار نموذجي — عدد المخططات التي قورنت قبل اختيار أحدها.

المخطط wreturnw_{\text{return}} wvolumew_{\text{volume}} wvolw_{\text{vol}} مقياس المهمة الأساسية مقابل مهمة واحدة
ثابت (wk=1w_k = 1) 1.00 1.00 1.00
موازنة عدم اليقين
GradNorm

ثلاثة مخططات مضروبة في عدة طيات هي بالفعل بحث نموذجي صغير. وأي تحسن يُبلغ عنه هنا يجب أن يصمد أمام تصحيح الاختبارات المتعددة الموضح في شارب المخفّض والاختبارات المتعددة قبل أن يعني شيئاً.

النقل السلبي: سجّل إشارات التدرجات

تدرجات مهام متوافقة ومتعارضة عند تمثيل مشترك

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

cos(ϕL(k),ϕL(j))<0    conflicting tasks\cos\bigl(\nabla_\phi \mathcal{L}^{(k)}, \nabla_\phi \mathcal{L}^{(j)}\bigr) < 0 \implies \text{conflicting tasks}

ويقاس ذلك على المشفّر المشترك فقط — فالرؤوس خاصة بالمهام بحكم البناء، وهي "متوافقة" بشكل تافه دائماً.

import torch.nn.functional as F


def shared_grad(model, x, y, task_idx, criterion=nn.MSELoss()):
    """Gradient of task `task_idx` w.r.t. the shared encoder, flattened."""
    model.zero_grad(set_to_none=True)
    loss = criterion(model(x)[task_idx], y)
    loss.backward()
    return torch.cat([
        p.grad.detach().flatten()
        for p in model.shared_encoder.parameters()
        if p.grad is not None
    ])


def task_conflict(model, x, y_by_task, task_names):
    """Pairwise cosine similarity between per-task shared-encoder gradients."""
    grads = {
        name: shared_grad(model, x, y_by_task[name], i)
        for i, name in enumerate(task_names)
    }
    return {
        (a, b): F.cosine_similarity(
            grads[a].unsqueeze(0), grads[b].unsqueeze(0)
        ).item()
        for i, a in enumerate(task_names)
        for b in task_names[i + 1:]
    }

استدعِ هذا على دفعة محتجزة بتواتر ثابت أثناء التدريب، لا مرة واحدة في النهاية. قد يبدأ زوج ما متوافقاً ثم يتباعد حين يتخصص المشفّر؛ ورقم واحد في نهاية التدريب يخفي ذلك.

ما ينبغي البحث عنه — ونشره في الحالتين:

الزوج تشابه جيب التمام، التدريب المبكر تشابه جيب التمام، التدريب المتأخر هل ساعد MTL المهمة الأساسية؟
العائد ↔ الحجم
العائد ↔ التقلب
الحجم ↔ التقلب

إذا اتفقت تدرجات الحجم والتقلب معاً بينما تعارضتا كلتاهما مع تدرج العائد، فالاستنتاج الصحيح هو أن المهمتين المساعدتين تشكلان كتلة متماسكة لا تنتمي إليها مهمة العائد — والإصلاح هو تجميع المهام، لا إضافة سعة. عندما يكون التعارض حقيقياً، فالعلاجات القياسية هي PCGrad (Yu وآخرون، 2020)، الذي يسقط كل تدرج متعارض على المستوى العمودي للتدرج الآخر؛ وCAGrad (Liu وآخرون، 2021)، الذي يبحث عن اتجاه هبوط لا يضر بأي مهمة؛ أو إسقاط المهمة المساعدة بالكامل.

لاحظ ما هو غائب عمداً: مخطط t-SNE للتمثيل المشترك ملوناً بقيمة الهدف. إنه زخرفي — فأرقام جيب التمام أعلاه تقول كل ما كان التضمين سيلمح إليه، وتقول ذلك على هيئة أرقام.

بروتوكول التحقق

نوافذ تحقق walk-forward منفصلة عبر خط زمني للبحث

القياس أعلاه بلا قيمة في ظل بروتوكول مهمل، ويجعل MTL الفخاخ المعتادة أسوأ لأن هناك ثلاثة أهداف يمكن تسريبها بدلاً من هدف واحد.

بيانات حقيقية، لا محاكٍ. يجب أن تأتي الأهداف من بيانات OHLCV/التداول الفعلية. يولد نموذج GARCH تجريبي صلب تقلباً مرتبطاً بالعوائد بحكم البناء، وهذا بالضبط الشيء قيد الاختبار — وستقيس التجربة مولّدها الخاص. إذا أردت عملية تقلب ملائمة، فإن التنبؤ بتقلب GARCH للعملات المشفرة يلائم GARCH(1,1) بالاحتمال الأقصى على BTC/ETH حقيقيين ويتحقق من البواقي المعيارية، بينما يغطي GARCH غير المتناظر وتأثير الرافعة سبب تشويه محاكٍ غاوسي ذي استجابة متماثلة لتقلب العملات المشفرة من الأساس. والبيانات الاصطناعية مقبولة فقط عندما توفر حقيقة أرضية مضبوطة — ارتباطاً معروفاً بين المهام حدده المؤلف وتحاول استعادته — وهي تجربة مختلفة عن تجربة هنا.

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

طيات walk-forward منقاة ومحجوزة. لا يستطيع تقسيم زمني واحد 80/20 تمييز تحسن MTL عن أثر الطية — وهذه هي حجة تحسين walk-forward بأكملها، إذ يوضح ثلاثة تقسيمات وهي تنتج ثلاثة استنتاجات. أعد استخدام مولّد purged_walk_forward ذي النافذة المتسعة من نمذجة الفارق السعري بالتعلم الآلي: فهو يسقط فجوة من صفوف horizon على جانبي كل حد، وهذا مهم هنا لأن نوافذ التقلب المحقق المتداخلة تتسرب عبر الحد حتى عندما لا يتسرب هدف العائد.

خط أساس كلاسيكي. لا يثبت نموذج MTL يتفوق على ثلاثة نماذج منفردة شيئاً إذا تفوق عليه نموذج gradient boosting أو ridge لكل هدف. لائم نموذجاً واحداً لكل هدف باستخدام LightGBM أو ridge على الطيات والسمات نفسها، وأبلغ عنه في الجدول نفسه.

النموذج مقياس المهمة الأساسية ملاحظات
Ridge، لكل هدف خط أساس كلاسيكي
LightGBM، لكل هدف خط أساس كلاسيكي
MLP لمهمة واحدة، لكل هدف ثلاث شبكات منفصلة
MTL، أفضل مخطط خسارة شبكة واحدة، ثلاثة رؤوس

متى يستحق MTL العناء هنا؟

عتبة قرار مقاسة لتعقيد نموذج متعدد المهام

الشروط التي ينبغي أن يفوز فيها MTL، مصاغة كفرضيات يجب فحصها مقابل الطيات أعلاه لا كقائمة تحقق:

  • التسميات المساعدة أنظف من التسمية الأساسية. فالحجم ملحوظ مباشرة؛ أما "العائد المتوقع" فليس كذلك. إذا كان رأس العائد يلائم الضوضاء في الغالب، فإن إشارة التدرج من الرؤوس المساعدة هي الجزء الوحيد المصاغ جيداً في الهدف.
  • بيانات التدريب محدودة مقارنة بسعة المشفّر، بحيث يؤدي القيد المساعد عملاً تنظيمياً حقيقياً بدلاً من التنافس على المعلمات فقط.
  • زمن الاستدلال مهم، وتمرير أمامي واحد أفضل من ثلاثة.

والحجة المضادة قابلة للاختبار بالقدر نفسه: إذا كانت قيم cos_sim(return, ·) سالبة باستمرار، فإن المشفّر المشترك يُسحب بعيداً عن المهمة الأساسية، وتصبح الرؤوس المساعدة ضريبة لا أداة تنظيم.

الخلاصة

تدفقات تنبؤ متناغمة تتحول إلى خلاصة متعددة المهام

تنبع العوائد والحجم والتقلب من البنية الدقيقة نفسها، لذا فالتمثيل المشترك prior معقول — لكن prior ليس نتيجة. والشيئان اللذان يمكن لهذا الإعداد إثباتهما فعلاً هما مخطط موازنة الخسارة الذي تفضله البيانات (مع الإبلاغ عن الأوزان المتعلمة لا تسمية الفائز فقط)، وما إذا كانت تدرجات المهام على المشفّر المشترك متوافقة، مقاساً عبر التدريب لا مفترضاً لمجرد أن الأهداف مترابطة.

إذا أظهرت طيات walk-forward المنقاة أن شبكة MTL لا تتفوق على نموذج gradient boosting لكل هدف، فهذه هي النتيجة وتنشر بهذه الصفة — والقالب هو النتيجة السلبية الصادقة. والنتيجة السلبية بشأن النقل السلبي تظل نتيجة عن النقل السلبي.

blog.disclaimer

Authors

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

ابقَ متقدماً على السوق

اشترك في نشرتنا الإخبارية للحصول على رؤى حصرية حول تداول الذكاء الاصطناعي وتحليلات السوق وتحديثات المنصة.

نحترم خصوصيتك. يمكنك إلغاء الاشتراك في أي وقت.