محول الانصهار الزمني: التنبؤ بالسلاسل الزمنية مع التعلم العميق - البرنامج التعليمي الكامل

إنشاء تنبؤات دقيقة وقابلة للتفسير

تم الإنشاء باستخدام دالي [1]

بحسب [2]، محول الانصهار الزمني يتفوق على جميع نماذج التعلم العميق البارزة للتنبؤ بالسلاسل الزمنية.

بما في ذلك المميز شجرة تعزيز التدرج نموذج بيانات السلاسل الزمنية الجدولية.

لكن ما هو محول الاندماج الزمني (TFT)[3] ولماذا هو مثير للاهتمام جدا؟

وفي هذا المقال نشرح باختصار مستجدات محول الانصهار الزمني وبناء مشروع شامل عليه التنبؤ بالطلب على الطاقة. على وجه التحديد، سوف نغطي:

  • كيفية تحضير بياناتنا لتنسيق TFT.
  • كيفية بناء وتدريب وتقييم نموذج TFT.
  • كيفية الحصول على تنبؤات بشأن بيانات التحقق والتنبؤات خارج العينة.
  • كيفية حساب أهمية الميزة, الأنماط الموسمية, و قوة الأحداث المتطرفة باستخدام النماذج المضمنة اهتمام قابل للتفسير آلية.

دعونا الغوص في!

للحصول على تحليل متعمق لبنية محولات الانصهار الزمني، تحقق من تحليلي السابق البند.

Tزمني Fusion Tرانفورمر (TFT) هو نموذج قائم على المحولات ويعزز الاهتمام الذاتي لالتقاط الديناميكيات الزمنية المعقدة لتسلسلات زمنية متعددة.

يدعم تي اف تي:

  • سلاسل زمنية متعددة: يمكننا تدريب نموذج TFT على آلاف السلاسل الزمنية أحادية المتغير أو متعددة المتغيرات.
  • التنبؤ متعدد الأفق: يقوم النموذج بإخراج تنبؤات متعددة الخطوات لمتغير واحد أو أكثر من المتغيرات المستهدفة - بما في ذلك فترات التنبؤ.
  • ميزات غير متجانسة: يدعم TFT العديد من أنواع الميزات، بما في ذلك المتغيرات الخارجية الثابتة والمتغيرة زمنيًا.
  • توقعات قابلة للتفسير: يمكن تفسير التوقعات من حيث الأهمية المتغيرة والموسمية.

واحدة من تلك السمات فريدة من نوعها محول الانصهار الزمني. وسوف نغطي هذا في القسم التالي.

من بين نماذج السلاسل الزمنية البارزة لـ DL (على سبيل المثال، DeepAR[4])، يتميز TFT لأنه يدعم أنواعًا مختلفة من الميزات. هؤلاء هم:

  • متفاوتة الوقت معروف
  • متفاوتة الوقت غير معروف
  • وقت ثابت حقيقي
  • وقت ثابت قاطع

على سبيل المثال، تخيل أن لدينا حالة التنبؤ بالمبيعات:

لنفترض أنه يتعين علينا التنبؤ بمبيعات 3 منتجات. ال num sales هو المتغير المستهدف. ال CPI index أو ال number of visitors . متغيرة الزمن غير معروفة الميزات لأنها معروفة فقط حتى وقت التنبؤ. لكن، holidaysو special days . معروف بتغير الزمن الأحداث.

product id is قاطعة زمنية (ثابتة). ميزة. الميزات الأخرى التي هي عددية ولا تعتمد على الوقت مثل yearly_revenue يمكن تصنيفها على أنها حقيقي لا يتغير مع الزمن.

قبل الانتقال إلى مشروعنا، سنعرض أولاً برنامجًا تعليميًا مصغرًا حول كيفية تحويل بياناتك إلى ملف تنسيق السلاسل الزمنية الممتدة.

ملحوظة: تم إنشاء جميع الصور والأشكال الموجودة في هذه المقالة بواسطة المؤلف.

في هذا البرنامج التعليمي، نستخدم TemporalFusionTransformer نموذج من توقعات باي تورش المكتبة وPyTorch Lightning:

نقطة تثبيت الشعلة pytorch-البرق pytorch_forecasting

تتضمن العملية برمتها 3 أشياء:

  1. قم بإنشاء إطار بيانات الباندا باستخدام بيانات السلاسل الزمنية الخاصة بنا.
  2. لف إطار البيانات الخاص بنا في ملف TimeSeriesDataset حتة.
  3. تمرير لدينا TimeSeriesDataset سبيل المثال TemporalFusionTransformer.

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

لنقم بإنشاء مجموعة بيانات تدريب بسيطة لإظهار كيفية القيام بذلك TimeSeriesDataset الأشغال:

يجب علينا تنسيق بياناتنا بالطريقة التالية: يمثل كل مربع ملون سلسلة زمنية مختلفة، ممثلة بـه group .

شكل 1: إطار بيانات Sample_data الباندا

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

بعد ذلك، نقوم بتغليف إطار البيانات الخاص بنا في ملف TimeSeriesDataset نموذج:

جميع الحجج لا تحتاج إلى شرح: The max_encoder_length يحدد فترة الاسترجاع و max_prediction_length يحدد عدد نقاط البيانات التي سيتم توقعها. في حالتنا، ننظر إلى الوراء 3 خطوات زمنية في الماضي لإخراج توقعين.

TimeSeriesDataset يعمل المثيل الآن كمحمل بيانات. دعونا نطبع دفعة ونتحقق من كيفية تمرير بياناتنا إلى TFT:

تحتوي هذه الدفعة على قيم التدريب [0,1] من السلسلة الزمنية الأولى (group 0) وقيم الاختبار[2,3,4]. إذا قمت بإعادة تشغيل هذا الرمز، فسوف تحصل على قيم مختلفة لأنه يتم خلط البيانات بشكل افتراضي.

سوف يستخدم مشروعنا مخططات حمل الكهرباء 20112014 XNUMX [5] مجموعة البيانات من UCI. يمكن تنزيل دفتر الملاحظات الخاص بهذا المثال من هنا:

تحتوي مجموعة البيانات هذه على استخدام الطاقة (بالكيلوواط) لـ 370 عميلاً/مستهلكًا بتردد 15 دقيقة. تمتد البيانات إلى 4 سنوات (2011-2014).

تم إنشاء بعض المستهلكين بعد عام 2011، لذا فإن استخدامهم للطاقة في البداية يكون صفرًا.

نقوم بالمعالجة المسبقة للبيانات وفقًا لـ [3]:

  • تجميع المتغير المستهدف لدينا power_usage بالساعة.
  • ابحث عن أقرب تاريخ لكل سلسلة زمنية حيث تكون الطاقة غير صفرية.
  • إنشاء ميزات جديدة: month, day, hour و day_of_week.
  • حدد كل الأيام بينهما 2014–01–01 و 2014–09–07.

لنبدأ:

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

مجلد مشترك https://archive.ics.uci.edu/ml/machine-learning-databases/00321/LD2011_2014.txt.zip
!فك الضغط
LD2011_2014.txt.zip

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

يمثل كل عمود مستهلكًا. الأكثر أولية power_usage القيم هي 0.

بعد ذلك، نقوم بتجميع البيانات كل ساعة. نظرًا لحجم النموذج وتعقيده، فإننا نقوم بتدريب نموذجنا على 5 مستهلكين فقط (لأولئك الذين لديهم قيم غير الصفر).

الآن نقوم بإعداد مجموعة البيانات الخاصة بنا TimeSeriesDataset شكل. لاحظ أن كل عمود يمثل سلسلة زمنية مختلفة. ومن ثم، فإننا "نذيب" إطار البيانات الخاص بنا، بحيث يتم تكديس جميع السلاسل الزمنية عموديًا بدلاً من أفقيًا. وفي هذه العملية، نقوم بإنشاء ميزاتنا الجديدة.

يتم استدعاء إطار البيانات النهائي الذي تمت معالجته مسبقًا time_df. لنطبع محتوياته:

time_df هو الآن بالتنسيق المناسب لـ TimeSeriesDataset. كما خمنت الآن، نظرًا لأن التفاصيل تتم كل ساعة، فإن hours_from_start المتغير سيكون مؤشر الوقت.

تحليل البيانات استكشافية

إن اختيار 5 مستهلكين/سلسلة زمنية ليس عشوائيًا. ال power usage لكل سلسلة زمنية خصائص مختلفة، مثل القيمة المتوسطة:

time_df[['consumer_id','power_usage']].groupby('consumer_id').mean()

لنرسم الشهر الأول من كل سلسلة زمنية:

الرقم 2: الشهر الأول لجميع السلاسل الزمنية/المستهلكين الخمسة.

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

لاحظ أيضًا أن طرق التنبؤ الأخرى بالسلاسل الزمنية مثل أريما يجب أن تستوفي بعض المتطلبات (على سبيل المثال، يجب أن تصبح السلسلة الزمنية ثابتة أولاً). باستخدام TFT، يمكننا ترك بياناتنا كما هي.

إنشاء محمل البيانات

في هذه الخطوة، نمرر لدينا time_df إلى TimeSeriesDataSet التنسيق وهو مفيد للغاية لأنه:

  • إنه يعفينا من كتابة أداة تحميل البيانات الخاصة بنا.
  • يمكننا تحديد كيفية تعامل TFT مع ميزات مجموعة البيانات.
  • يمكننا تطبيع مجموعة البيانات لدينا بسهولة. في حالتنا، التطبيع إلزامي لأن جميع التسلسلات الزمنية تختلف في الحجم. وهكذا نستخدم GroupNormalizer لتطبيع كل سلسلة زمنية على حدة.

يستخدم نموذجنا فترة مراجعة مدتها أسبوع واحد (7*24) للتنبؤ باستخدام الطاقة خلال الـ 24 ساعة القادمة.

لاحظ أيضًا أن hours_from_start هو مؤشر الوقت وميزة تغيير الوقت. ال power_usage هو المتغير المستهدف لدينا. من أجل التوضيح، مجموعة التحقق الخاصة بنا هي اليوم الأخير:

النموذج الأساسي

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

كخط أساس ساذج، نتوقع منحنى استخدام الطاقة في اليوم السابق:

تدريب نموذج محول الاندماج الزمني

يمكننا تدريب نموذج TFT الخاص بنا باستخدام ما هو مألوف مدرب واجهة من PyTorch Lightning.

لاحظ الأمور التالية:

  • نستخدم التوقف المبكر رد الاتصال لمراقبة فقدان التحقق من الصحة.
  • نستخدم لوح الشد لتسجيل مقاييس التدريب والتحقق لدينا.
  • يستخدم نموذجنا الخسارة الكمية - نوع خاص من الخسارة يساعدنا على إخراج فترات التنبؤ. لمعرفة المزيد عن وظيفة الخسارة الكمية، تحقق من هذه المقالة.
  • نستخدم 4 رؤساء الاهتمام، مثل الورقة الأصلية.

نحن الآن جاهزون لبناء نموذجنا وتدريبه:

هذا كل شيء! بعد 6 فترات، يبدأ الإيقاف المبكر ويوقف التدريب.

تحميل وحفظ أفضل نموذج

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

!zip -r model.zip Lightning_logs/lightning_logs/version_1/*

لتحميل النموذج مرة أخرى، قم بفك الضغط model.zip وقم بتنفيذ ما يلي - فقط تذكر أفضل مسار للنموذج:

تحقق من Tensorboard

ألق نظرة فاحصة على منحنيات التدريب والتحقق باستخدام Tensorboard:

تقييم النموذج

احصل على تنبؤات بشأن مجموعة التحقق من الصحة واحسب المتوسط P50 (الوسيط الكمي) خسارة:

شهدت السلاسل الزمنية الأخيرة خسارة أعلى قليلاً لأن حجمها النسبي مرتفع أيضًا.

مؤامرة التنبؤات على بيانات التحقق من الصحة

إذا مررنا mode=raw على تنبؤ() الطريقة، نحصل على مزيد من المعلومات، بما في ذلك التنبؤات لجميع الكميات السبعة. لدينا أيضًا إمكانية الوصول إلى قيم الاهتمام (المزيد حول ذلك لاحقًا).

نلقي نظرة فاحصة على raw_predictions المتغير:

نستخدم مؤامرة_التنبؤ () لإنشاء مؤامراتنا. بالطبع، يمكنك إنشاء قطعة الأرض المخصصة الخاصة بك - مؤامرة_التنبؤ () له فائدة إضافية تتمثل في إضافة قيم الاهتمام.

ملحوظة: يتنبأ نموذجنا بنقاط البيانات الـ 24 التالية خلال مرة واحدة. هذا ليس سيناريو تنبؤ متجدد حيث يتنبأ النموذج بحدوث عزباء قيمة كل مرة و"تجميع" جميع التوقعات معًا.

نقوم بإنشاء قطعة أرض واحدة لكل مستهلك (5 في المجموع).

الرقم 3: التنبؤات بشأن بيانات التحقق من صحة MT_002
الرقم 4: التنبؤات بشأن بيانات التحقق من صحة MT_004
الرقم 5: التنبؤات بشأن بيانات التحقق من صحة MT_005
الرقم 6: التنبؤات بشأن بيانات التحقق من صحة MT_006
الرقم 7: التنبؤات بشأن بيانات التحقق من صحة MT_008

النتائج مثيرة للإعجاب للغاية.

الأهداف و محول الانصهار الزمني كان النموذج قادرًا على التقاط سلوك جميع السلاسل الزمنية الخمس، من حيث الموسمية والحجم!

لاحظ أيضًا أن:

  • لم نقم بإجراء أي ضبط للمعلمات الفائقة.
  • لم نطبق أي تقنية هندسية مميزة.

في القسم التالي، نعرض كيفية تحسين نموذجنا من خلال تحسين المعلمة الفائقة.

توقعات المؤامرة لسلسلة زمنية محددة

في السابق، قمنا برسم التنبؤات على بيانات التحقق من الصحة باستخدام idx الوسيطة، والتي تتكرر على جميع السلاسل الزمنية في مجموعة البيانات الخاصة بنا. يمكننا أن نكون أكثر تحديدًا وتنبؤات الإخراج على سلسلة زمنية محددة:

الرقم 7: توقعات اليوم السابق ل MT_004 على مجموعة التدريب

In الشكل شنومكس، نحن نرسم اليوم السابق MT_004 المستهلك لمؤشر الوقت = 26512.

تذكر، عمود فهرسة الوقت لدينا hours_from_start يبدأ من 26304 ويمكننا الحصول على تنبؤات من 26388 فصاعدًا (لأننا حددنا سابقًا min_encoder_length=max_encoder_length // 2 وهو يساوي 26304 + 168//2=26388

التوقعات خارج العينة

لنقم بإنشاء تنبؤات خارج العينة، بما يتجاوز نقطة البيانات النهائية لبيانات التحقق من الصحة - وهي 2014–09–07 23:00:00

كل ما علينا فعله هو إنشاء إطار بيانات جديد يحتوي على:

  • عدد N=max_encoder_length التواريخ الماضية، والتي تعمل كنافذة مراجعة - ال بيانات التشفير في مصطلحات TFT.
  • التواريخ المستقبلية للحجم max_prediction_length التي نريد حساب توقعاتنا لها - بيانات فك التشفير.

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

الرقم 7: التنبؤ باليوم التالي لـ MT_002

يعد التنبؤ الدقيق أمرًا واحدًا، لكن إمكانية التفسير مهمة أيضًا كثيرًا في أيامنا هذه.

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

محول الانصهار الزمني يوفر ثلاثة أنواع من التفسير:

  • الموسمية: TFT تستفيد من روايتها انتباه متعدد الرؤوس قابل للتفسير آلية حساب أهمية خطوات الزمن الماضي.
  • الميزة الحكيمة: TFT تستفيد منه شبكة الاختيار المتغيرة وحدة لحساب أهمية كل ميزة.
  • قوة الأحداث المتطرفة: يمكننا التحقق من كيفية تصرف السلاسل الزمنية أثناء الأحداث النادرة

إذا كنت تريد أن تتعلم بعمق حول الأعمال الداخلية لـ انتباه متعدد الرؤوس قابل للتفسير و شبكة التحديد المتغيرة, تحقق من مقالتي السابقة.

التفسير الموسمي الحكيم

يستكشف TFT أوزان الانتباه لفهم الأنماط الزمنية عبر الخطوات الزمنية الماضية.

تمثل الخطوط الرمادية في جميع المؤامرات السابقة درجات الاهتمام. انظر إلى تلك المؤامرات مرة أخرى، هل لاحظت أي شيء؟ الشكل 8 يظهر نتائج الشكل 7 ويمثل أيضًا درجات الاهتمام:

الرقم 8: توقع اليوم التالي لـ MT_001 مع عرض المواسم

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

إذا قمنا بحساب متوسط ​​منحنيات الانتباه عبر جميع الخطوات الزمنية والسلاسل الزمنية (وليس فقط الخمسة منها التي استخدمناها في هذا البرنامج التعليمي)، فسنحصل على الشكل المتماثل الشكل 9 من ورق TFT:

الرقم 9: الأنماط الزمنية لمجموعة بيانات الكهرباء (مصدر)

السؤال: ما هو جيد هذا؟ ألا يمكننا ببساطة تقدير الأنماط الموسمية باستخدام طرق مثل مخططات ACF وتحلل إشارة الوقت وما إلى ذلك؟

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

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

ميزة التفسير الحكيم

شبكة الاختيار المتغيرة يمكن لعنصر TFT تقدير الحجم بسهولة أهمية الميزة:

الرقم 10: يتميز بأهمية بيانات التحقق من الصحة

In الشكل 10، نلاحظ ما يلي:

  • hour و day_of_week الحصول على درجات قوية، سواء كملاحظات سابقة أو متغيرات مشتركة مستقبلية. يشترك المعيار الموجود في الورقة الأصلية في نفس النتيجة.
  • power_usage من الواضح أنه المتغير المشترك الأكثر تأثيرًا.
  • consumer_id ليس مهمًا جدًا هنا لأننا نستخدم 5 مستهلكين فقط. في ورقة TFT، حيث يستخدم المؤلفون جميع المستهلكين البالغ عددهم 370، يكون هذا المتغير أكثر أهمية.

ملحوظة: إذا لم يكن المتغير الثابت للتجميع مهمًا، فمن المحتمل جدًا أن يتم تصميم مجموعة البيانات الخاصة بك بشكل جيد أيضًا من خلال نموذج توزيع واحد (مثل ARIMA).

كشف الأحداث المتطرفة

تشتهر السلاسل الزمنية بكونها عرضة للتغيرات المفاجئة في خصائصها أثناء الأحداث النادرة (يشار إليها أيضًا باسم الصدمات).

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

هل هذا نوع من الضوضاء العشوائية أم نمط ثابت مخفي يفلت من نموذجنا؟

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

لا تحتوي بعض الميزات على جميع قيمها موجودة في مجموعة بيانات التحقق من الصحة، لذلك نعرض فقط hour و consumer_id:

الرقم 11: التنبؤات مقابل الفعليات (الوسائل الطبيعية) على مدار الساعة
الرقم 12: التوقعات مقابل الفعليات (الوسائل المقيسة) على Consumer_id

وفي كلا الشكلين، كانت النتائج مشجعة. في الشكل 12، نلاحظ أن المستهلك MT_004 أداء ضعيف قليلاً مقارنة بالمستهلكين الآخرين. يمكننا التحقق من ذلك إذا قمنا بتطبيع خسارة P50 لكل مستهلك مع متوسط ​​استخدام الطاقة الذي قمنا بحسابه مسبقًا.

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

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

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

تكمن المشكلة في أنه نظرًا لأن TFT هو نموذج قائم على المحولات، فستحتاج إلى موارد أجهزة كبيرة!

محول الانصهار الزمني يعد بلا شك علامة فارقة لمجتمع Time-Series.

لا يحقق النموذج نتائج SOTA فحسب، بل يوفر أيضًا إطارًا لتفسير التنبؤات. النموذج متوفر أيضا في السهام مكتبة python، والتي تعتمد على مكتبة PyTorch Forecasting.

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

محول الاندماج الزمني: التنبؤ بالسلاسل الزمنية مع التعلم العميق - إعادة نشر البرنامج التعليمي الكامل من المصدر https://towardsdatascience.com/temporal-fusion-transformer-time-series-forecasting-with-deep-learning-complete-tutorial-d32c1e51cd91?source= rss—-7f60cf5620c9—4 عبر https://towardsdatascience.com/feed

<!–

->

الطابع الزمني:

اكثر من مستشارو Blockchain