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

الوحدة 3 — البيانات على Cloud Storage وBigQuery

الوحدتان السابقتان جهّزتا المشروع والدفتر. هذه الوحدة تُنشئ العمود الفقريّ للبيانات: أين تعيش المعاملات الخامّة، كيف تتحوّل إلى خصائص جاهزة للتدريب، وكيف تُقدَّم إلى Vertex AI بشكل مُوثَّق قابل لإعادة الاستعمال. القرارات هنا تتحكّم بأداء التدريب وكلفته للأشهر المقبلة.

دلوان لهدفين مختلفين

Cloud Storage (GCS) هو نظام الملفّات الشيئيّ. للفيل الأحمر نُنشئ دلوين:

gsutil mb -l europe-west1 -c standard gs://fraud-features-lab
gsutil mb -l europe-west1 -c standard gs://fraud-models-lab

# دورة حياة: نُبقي إصدارات نموذج 90 يومًا
gsutil lifecycle set lifecycle.json gs://fraud-models-lab

القاعدة: دلو لكلّ نوع فنّيّ. الخلط بين الميزات والنماذج والسجلّات في دلو واحد يُصعّب سياسات الاحتفاظ، يُشوِّش الفواتير، ويُعقِّد سياسات IAM. سياسة اليوم على النماذج (احتفاظ 90 يومًا) تختلف عن سياسة السجلّات (احتفاظ 30 يومًا) وعن سياسة الميزات المشتركة (احتفاظ دائم مع نسخة إقليميّة ثانية).

فئات التخزين: standard للاستعمال اليومي؛ nearline بعد 30 يومًا؛ coldline بعد 90؛ archive بعد سنة. lifecycle.json أدناه ينقل ملفّات النماذج القديمة تلقائيًّا:

{
"lifecycle": {
"rule": [
{"action": {"type": "SetStorageClass", "storageClass": "NEARLINE"},
"condition": {"age": 30}},
{"action": {"type": "Delete"}, "condition": {"age": 365}}
]
}
}

تنسيقات الملفّات: Parquet قبل CSV

لأيّ مجموعة بيانات جدوليّة أكبر من بضعة ميغابايت، Parquet هو الخيار الافتراضيّ:

  • ضغط عموديّ بكفاءة عالية (ثلث حجم CSV بالمتوسّط).
  • قراءة عمود واحد لا تستدعي قراءة الجدول كلّه.
  • الأنواع (تاريخ، عدد صحيح، منطقيّ) محفوظة، لا تُفقَد كما في CSV.

في الفيل الأحمر، جدول المعاملات (2 مليار سطر تاريخيًّا) بCSV يزن نحو 700 غيغا، وبParquet نحو 220 غيغا مع كسب سرعة قراءة عشرين ضعفًا.

CSV يبقى مبرَّرًا حين يستقبل الملفّ نظامٌ لا يقرأ Parquet (مثل تصدير إلى تطبيق قديم). داخل السلسلة التقنيّة كلّها، Parquet دائمًا.

من BigQuery إلى إطار بيانات

BigQuery هو مستودع التحليل الذي يستقبل الأحداث الخامّة من نظام الدفع. الجدول الأساسيّ للفيل الأحمر:

fraud-detection-lab.transactions.raw
- event_ts TIMESTAMP
- card_hash STRING
- amount NUMERIC
- merchant_country STRING
- device_id STRING
- is_fraud BOOL (توسيم مصرفيّ يصل بتأخّر أسبوع)

استخراج البيانات إلى ذاكرة الدفتر:

from google.cloud import bigquery

client = bigquery.Client(project="fraud-detection-lab")

sql = """
SELECT
card_hash,
amount,
merchant_country,
device_id,
IF(is_fraud, 1, 0) AS y
FROM `fraud-detection-lab.transactions.raw`
WHERE DATE(event_ts) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 90 DAY)
AND DATE_SUB(CURRENT_DATE(), INTERVAL 8 DAY)
"""

df = client.query(sql).to_dataframe(create_bqstorage_client=True)

ملاحظتان بالغتا الأهمّية:

  1. INTERVAL 8 DAY على الحدّ الأعلى: التوسيم يصل متأخّرًا أسبوعًا (تحكيم النزاعات)، فأخذ آخر يوم يعني تدريبًا على بيانات ناقصة التوسيم. هذه فخّ من فخاخ MLOps الكلاسيكيّة.
  2. مسح الفهرس الزمنيّ: DATE(event_ts) يمنع BigQuery من استعمال تقسيم الجدول على event_ts بكفاءة، إن كان مقسَّمًا. البديل الأداءيّ الأصحّ: event_ts >= TIMESTAMP_SUB(...) بدل DATE(event_ts) >= ....

تصدير مباشر إلى GCS

لتفادي تمرير مليونَي سطر عبر ذاكرة الدفتر، يُفضَّل التصدير المباشر من BigQuery إلى Parquet على GCS، ثمّ قراءتها في التدريب:

EXPORT DATA OPTIONS(
uri='gs://fraud-features-lab/features/2026-09-05/*.parquet',
format='PARQUET',
compression='SNAPPY',
overwrite=true
) AS
SELECT ... FROM `fraud-detection-lab.transactions.raw` WHERE ...

نتيجة الاستعلام تُقسَّم على عدّة ملفّات (تُشير إليها * في المسار)، ما يُتيح للتدريب قراءتها بالتوازي.

مجموعات بيانات Vertex

Vertex AI Datasets هو كتالوج يُعطي مجموعتنا هويّة رقميّة قابلة للاستعمال في تدريب مُدار، وAutoML، وخطوط الإنتاج:

from google.cloud import aiplatform

ds = aiplatform.TabularDataset.create(
display_name="fraud-features-2026-09-05",
gcs_source=["gs://fraud-features-lab/features/2026-09-05/*.parquet"],
)
print(ds.resource_name)
# projects/.../locations/europe-west1/datasets/1234567890

المجموعة المُسجَّلة تحمل:

  • مصدرًا: مسار GCS أو جدول BigQuery
  • معرِّفًا مستقرًّا: يُشار إليه في التدريبات لاحقًا
  • ما وراء بيانات: تاريخ الإنشاء، من أنشأها، الأعمدة المكتشَفة

لسنا مضطرّين لاستعمال Datasets لكلّ تجربة (تدريب مخصّص يقبل مسار GCS مباشرة)، لكنّها الوسيلة الوحيدة لربط النموذج بالبيانات التي دُرِّب عليها في لسانِيّة (lineage) الوحدة 9 كاملةً.

كلفة استعلامات BigQuery

BigQuery يُفوتَر على البايتات المسحوبة في وضعه على الطلب، بسعر نحو 5 دولار لكلّ تيرابايت مقروء. استعلام يقرأ كامل جدول 700 غيغا يكلّف نحو 3.5 دولار، ورؤيته ينفَّذ عشر مرّات يوميًّا يعني 35 دولارًا في اليوم بلا داعٍ.

طرائق تقليص المسح:

  • التقسيم (partitioning): جدول مقسَّم على event_ts يوميًّا، الاستعلام لأسبوع يقرأ 7 أقسام لا كامل التاريخ. أوّل إجراء يوم إنشاء الجدول:

    CREATE TABLE transactions.raw
    PARTITION BY DATE(event_ts)
    CLUSTER BY merchant_country
    AS SELECT * FROM ...
  • التجميع (clustering): على أعمدة يُفلتَر بها كثيرًا (البلد، نوع البطاقة). داخل كلّ قسم، BigQuery يعرف أين تقع القيمة ويقرأ أقلّ.

  • SELECT أعمدة محدَّدة لا SELECT *: كل عمود إضافيّ في القراءة يُضاف إلى الفاتورة.

  • معاينة الكلفة قبل التنفيذ عبر --dry-run:

    bq query --use_legacy_sql=false --dry_run "SELECT ..."

هذه الأداة تقدّم بايتات المسح المتوقّعة بدون تنفيذ. يجعلها الفرق الجديّ إلزاميّة على الاستعلامات الجديدة.

للفرق ذات الحجم الكبير، الفوترة بالسعة (slots) تُبدَّل بعدد ثابت من وحدات المعالجة تُدفَع شهريًا، فتصير الفاتورة قابلة للتنبّؤ. لمشروع دورتنا التجريبيّ، الفوترة على الطلب أنسب.

تقسيم التدريب والصلاحيّة

قسمة زمنيّة، لا عشوائيّة، على السلاسل الزمنيّة:

df = df.sort_values("event_ts")
n = len(df)
train = df.iloc[: int(0.7 * n)]
val = df.iloc[int(0.7 * n): int(0.85 * n)]
test = df.iloc[int(0.85 * n):]

القسمة العشوائيّة تُسرِّب عن غير قصد بيانات المستقبل إلى التدريب، فتُنتِج تقييمًا متفائلًا كاذبًا. تفصيل هذا الفخّ درسته الدورة 20 (MLOps)؛ نُذكِّر به هنا لأنّه يُنسى ما إن نضع أيدينا في الأنابيب السحابيّة.

INTERVAL 0 DAY هو الفخّ الأشهر

كلّ فريق يمرّ به مرّة: تدريب على «آخر 90 يومًا» يعني عندهم >= DATE_SUB(CURRENT_DATE(), INTERVAL 90 DAY). لكنّ اليوم الحاليّ توسيمه غير مكتمل. يُدرَّب النموذج على معدّل احتيال يبدو صفريًّا في اليومَين الأخيرَين، فيُحرِّف عتبات القرار. القاعدة: INTERVAL 8 DAY (أو أطول) عند التوسيم المتأخّر، ووثِّق ذلك في اسم الحقل.

اسم الملفّ يوثّق التاريخ

دلائل GCS التي تحوي تاريخًا في المسار (features/YYYY-MM-DD/) تُتيح إعادة تدريب دقيقة على البيانات ذاتها لاحقًا، وهي كتالوج مضمَّن. تصنيف الملفّات بأسماء غامضة كـdata_v3_final.parquet يمنع أيّ إمكانيّة لاسترجاع نموذج الأسبوع الماضي.

في الخلاصة

  • دلو لكلّ نوع فنّيّ مع دورة حياة تُدير الفئات آليًّا.
  • Parquet قبل CSV لأيّ حجم يستحقّ الذكر.
  • BigQuery فوترة على البايتات المسحوبة؛ التقسيم والتجميع و--dry-run توفّر أضعاف كلفتها.
  • Vertex Datasets تُعطي المجموعة معرِّفًا مستقرًّا وتربطها بالنموذج في اللسانيّة.
  • التقسيم بين تدريب واختبار زمنيّ، مع هامش على التوسيم المتأخّر.

الوحدة التالية: كيف نحوّل هذا الجدول إلى تدريب مخصّص يعمل داخل حاوية على وحدة معالجة رسوميّة.