الحصول على إحصاءات من البيانات المهيكلة وغير المهيكلة باستخدام حزمة BigQuery DataFrames المتوافقة مع الذكاء الاصطناعي

1. نظرة عامة

في هذا التمرين العملي، ستستخدم إطارات بيانات BigQuery من دفتر ملاحظات Python في BigQuery Studio للحصول على إحصاءات من البيانات باستخدام Python. استفِد من الذكاء الاصطناعي التوليدي من Google لتحليل بيانات النصوص غير المنظَّمة وعرضها بشكل مرئي.

ستنشئ دفتر ملاحظات Python لتصنيف وتلخيص قاعدة بيانات عامة لشكاوى العملاء. يمكن تكييف هذه الطريقة للعمل على أي بيانات نصية غير منظَّمة.

الأهداف

في هذه الميزة الاختبارية، ستتعرّف على كيفية تنفيذ المهام التالية:

  • تفعيل واستخدام دفاتر ملاحظات Python في BigQuery Studio
  • الربط بخدمة BigQuery باستخدام حزمة BigQuery DataFrames
  • إنشاء تضمينات من بيانات نصية غير منظَّمة باستخدام BigQuery ML والربط بنقطة نهاية لتضمين النصوص في Vertex AI
  • تجميع التضمينات باستخدام BigQuery ML
  • تلخيص المجموعات باستخدام نموذج لغوي كبير من خلال BigQuery ML

2. المتطلبات

  • متصفّح، مثل Chrome أو Firefox
  • مشروع على السحابة الإلكترونية من Google Cloud تم تفعيل الفوترة فيه

قبل البدء

لإكمال التعليمات الواردة في هذا الدرس التطبيقي حول الترميز، يجب أن يكون لديك مشروع على Google Cloud تم تفعيل BigQuery Studio فيه، بالإضافة إلى حساب فوترة مرتبط.

  1. في Google Cloud Console، ضِمن صفحة اختيار المشروع، اختَر أو أنشِئ مشروعًا على Google Cloud.
  2. تأكَّد من تفعيل الفوترة لمشروعك على Google Cloud. كيفية التحقّق من تفعيل الفوترة في مشروع
  3. اتّبِع التعليمات لتفعيل BigQuery Studio لإدارة مواد العرض.

إعداد BigQuery Studio

أنشئ دفتر ملاحظات فارغًا واربطه بوقت تشغيل.

  1. انتقِل إلى BigQuery Studio في Google Cloud Console.
  2. انقر على بجانب الزر +.
  3. انقر على ورقة ملاحظات Python.
  4. أغلِق أداة اختيار النموذج.
  5. انقر على + رمز لإنشاء خلية رمز جديدة.
  6. ثبِّت أحدث إصدار من حزمة BigQuery DataFrames من خلية الرمز البرمجي.اكتب الأمر التالي.
    %pip install --upgrade bigframes --quiet
    
    انقر على الزر 🞂 أو اضغط على Shift + Enter لتشغيل خلية الرمز.

3- قراءة مجموعة بيانات عامة

ابدأ حزمة BigQuery DataFrames بتنفيذ ما يلي في خلية رمز جديدة:

import bigframes.pandas as bpd

bpd.options.bigquery.ordering_mode = "partial"

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

قاعدة بيانات شكاوى المستهلكين

يتم توفير قاعدة بيانات شكاوى المستهلكين على BigQuery من خلال برنامج مجموعات البيانات العامة في Google Cloud. هذه مجموعة من الشكاوى حول المنتجات والخدمات المالية الاستهلاكية، ويتم جمع البيانات من قِبل "مكتب حماية المستهلك المالي" في الولايات المتحدة.

في BigQuery، أرسِل طلب بحث إلى الجدول bigquery-public-data.cfbp_complaints.complaint_database لتحليل "قاعدة بيانات شكاوى المستهلكين". استخدِم طريقة bigframes.pandas.read_gbq() لإنشاء DataFrame من سلسلة طلب بحث أو رقم تعريف جدول.

نفِّذ ما يلي في خلية رمز جديدة لإنشاء DataFrame باسم "feedback":

feedback = bpd.read_gbq(
    "bigquery-public-data.cfpb_complaints.complaint_database"
)

التعرّف على المعلومات الأساسية حول DataFrame

استخدِم طريقة DataFrame.peek() لتنزيل عيّنة صغيرة من البيانات.

شغِّل هذه الخلية:

feedback.peek()

الناتج المتوقّع:

  date_received                  product ... timely_response  consumer_disputed complaint_id  
0    2014-03-05  Bank account or service ...            True              False       743665   
1    2014-01-21  Bank account or service ...            True              False       678608   
2    2020-12-31          Debt collection ...            True               <NA>      4041190   
3    2014-02-12          Debt collection ...            True              False       714350   
4    2015-02-23          Debt collection ...            True              False      1251358   

ملاحظة: يتطلّب head() الترتيب وهو أقل كفاءة بشكل عام من peek() إذا كنت تريد عرض عيّنة من البيانات.

كما هو الحال مع مكتبة pandas، استخدِم السمة DataFrame.dtypes لعرض جميع الأعمدة المتاحة وأنواع البيانات المقابلة لها. يتم عرضها بطريقة متوافقة مع مكتبة pandas.

شغِّل هذه الخلية:

feedback.dtypes

الناتج المتوقّع:

date_received                   date32[day][pyarrow]
product                              string[pyarrow]
subproduct                           string[pyarrow]
issue                                string[pyarrow]
subissue                             string[pyarrow]
consumer_complaint_narrative         string[pyarrow]
company_public_response              string[pyarrow]
company_name                         string[pyarrow]
state                                string[pyarrow]
zip_code                             string[pyarrow]
tags                                 string[pyarrow]
consumer_consent_provided            string[pyarrow]
submitted_via                        string[pyarrow]
date_sent_to_company            date32[day][pyarrow]
company_response_to_consumer         string[pyarrow]
timely_response                              boolean
consumer_disputed                            boolean
complaint_id                         string[pyarrow]
dtype: object

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

شغِّل هذه الخلية:

# Exclude some of the larger columns to make the query more efficient.
feedback.drop(columns=[
  "consumer_complaint_narrative",
  "company_public_response",
  "company_response_to_consumer",
]).describe()

الناتج المتوقّع:

         product  subproduct    issue  subissue  company_name    state ... timely_response  consumer_disputed  complaint_id
count    3458906     3223615  3458906   2759004       3458906  3417792 ...         3458906             768399       3458906
nunique       18          76      165       221          6694       63 ...               2                  2       3458906

4. استكشاف البيانات

قبل الانتقال إلى الشكاوى الفعلية، استخدِم طرقًا مشابهة لطريقة عمل مكتبة pandas في DataFrame لعرض البيانات بشكل مرئي.

تمثيل DataFrame بشكل مرئي

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

احتساب عدد الشكاوى الواردة من كل ولاية

complaints_by_state = (
  feedback.groupby(
    "state", as_index=False,
  ).size()
  .rename(columns={"size": "total_complaints"})
  .sort_values(by="total_complaints", ascending=False)
)

حوِّل هذا إلى DataFrame في pandas باستخدام الطريقة DataFrame.to_pandas().

complaints_pd = complaints_by_state.head(10).to_pandas()

استخدِم طرق تصور البيانات في pandas على DataFrame الذي تم تنزيله.

complaints_pd.plot.bar(x="state", y="total_complaints")

رسم بياني شريطي يعرض كاليفورنيا كولاية تضمّ أكبر عدد من الشكاوى

الربط بمجموعات بيانات أخرى

في السابق، كنت تنظر إلى الشكاوى حسب الولاية، ولكن هذا الإجراء لا يقدّم سياقًا مهمًا. بعض الولايات لديها عدد سكان أكبر من غيرها. يمكنك الربط بمجموعة بيانات سكانية، مثل استطلاع المجتمع الأمريكي الذي يجريه مكتب الإحصاء الأمريكي وجدول bigquery-public-data.geo_us_boundaries.states.

us_states = bpd.read_gbq("bigquery-public-data.geo_us_boundaries.states")
us_survey = bpd.read_gbq("bigquery-public-data.census_bureau_acs.state_2020_5yr")

# Ensure there are leading 0s on GEOIDs for consistency across tables.
us_states = us_states.assign(
    geo_id=us_states["geo_id"].str.pad(2, fillchar="0")
)

us_survey = us_survey.assign(
    geo_id=us_survey["geo_id"].str.pad(2, fillchar="0")
)

تحدّد هيئة American Community Survey الولايات حسب GEOID. انضم إلى جدول الولايات للحصول على عدد السكان حسب رمز الولاية المكوّن من حرفين.

pops = us_states.set_index("geo_id")[["state"]].join(
  us_survey.set_index("geo_id")[["total_pop"]]
)

الآن، ادمج هذه البيانات مع قاعدة بيانات الشكاوى لمقارنة عدد السكان بعدد الشكاوى.

complaints_and_pops = complaints_by_state.set_index("state").join(
    pops.set_index("state")
)

أنشئ رسمًا بيانيًا بالنقاط المبعثرة لمقارنة عدد سكان الولايات بعدد الشكاوى.

(
  complaints_and_pops
  .to_pandas()
  .plot.scatter(x="total_pop", y="total_complaints")
)

رسم بياني للنقاط المبعثرة يقارن بين عدد السكان وعدد الشكاوى

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

5- احتساب عمليات التضمين

في كثير من الأحيان، تكون المعلومات المهمة مخفية في بيانات غير منظَّمة، مثل النصوص أو المقاطع الصوتية أو الصور. في هذا المثال، يتضمّن المحتوى النصي للشكوى الكثير من المعلومات المفيدة في قاعدة بيانات الشكاوى.

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

اختيار مجموعة فرعية من قاعدة البيانات

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

import bigframes.pandas as bpd

bpd.options.bigquery.ordering_mode = "partial"

feedback = bpd.read_gbq(
    "bigquery-public-data.cfpb_complaints.complaint_database"
)

# Note: if not using ordering_mode = "partial", you must specify these in read_gbq
# for these to affect query efficiency.
# feedback = bpd.read_gbq(
#    "bigquery-public-data.cfpb_complaints.complaint_database",
#     columns=["consumer_complaint_narrative"],
#     filters= [
#         ("consumer_complaint_narrative", "!=", ""),
#         ("date_received", "==", "2022-12-01")])

feedback.shape

تم إرسال حوالي 1,000 شكوى في 2022-12-01 مقارنةً بحوالي 3.5 مليون صف في قاعدة البيانات الإجمالية (يمكنك التأكّد من ذلك باستخدام feedback.shape).

اختَر البيانات الخاصة بتاريخ 2022-12-01 وعمود consumer_complaint_narrative فقط.

import datetime

feedback = feedback[
    # Filter rows by passing in a boolean Series.
    (feedback["date_received"] == datetime.date(2022, 12, 1))
    & ~(feedback["date_received"].isnull())
    & ~(feedback["consumer_complaint_narrative"].isnull())
    & (feedback["consumer_complaint_narrative"] != "")
    & (feedback["state"] == "CA")

    # Uncomment the following if using free credits for a workshop.
    # Billing accounts with free credits have limited Vertex AI quota.
    # & (feedback["product"] == "Mortgage")
][
    # Filter columns by passing in a list of strings.
    ["consumer_complaint_narrative"]
]

feedback.shape

تتطلّب الطريقة drop_duplicates من مكتبة pandas ترتيبًا إجماليًا للصفوف لأنّها تحاول اختيار الصف الأول أو الأخير المطابق والاحتفاظ بالفهرس المرتبط به.

بدلاً من ذلك، يمكنك التجميع باستخدام استدعاء الطريقة groupby لإزالة الصفوف المكرّرة.

feedback = (
  feedback.groupby("consumer_complaint_narrative", as_index=False)
  .size()
)[["consumer_complaint_narrative"]]

feedback.shape

إنشاء تضمينات

تنشئ BigQuery DataFrames متّجهات التضمين من خلال فئة TextEmbeddingGenerator. ويستند ذلك إلى طريقة ML.GENERATE_EMBEDDING في BigQuery ML التي تستدعي نماذج تضمين النصوص التي توفّرها Vertex AI.

from bigframes.ml.llm import TextEmbeddingGenerator

embedding_model = TextEmbeddingGenerator(
    model_name="text-embedding-004"
)
feedback_embeddings = embedding_model.predict(feedback)

إليك مثال على شكل عمليات التضمين. وتمثّل هذه المتجهات المعنى الدلالي للنص كما يفهمه نموذج تضمين النص.

feedback_embeddings.peek()

الناتج المتوقّع:

                        ml_generate_embedding_result  \
0  [ 7.36380890e-02  2.11779331e-03  2.54309829e-...   
1  [-1.10935252e-02 -5.53950183e-02  2.01338865e-...   
2  [-7.85628427e-03 -5.39347418e-02  4.51385677e-...   
3  [ 0.02013054 -0.0224789  -0.00164843  0.011354...   
4  [-1.51684484e-03 -5.02693094e-03  1.72322839e-...   

تحتوي هذه المتّجهات على العديد من السمات. إليك مثالاً على متّجه تضمين واحد:

feedback_embeddings["ml_generate_embedding_result"].peek().iloc[0]

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

فلتر عمليات التضمين لتضمين الصفوف التي لم يحدث فيها أي خطأ فقط

mask = feedback_embeddings["ml_generate_embedding_status"] == ""
valid_embeddings = feedback_embeddings[mask]
valid_embeddings.shape

6. التجميع باستخدام تضمينات النص

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

from bigframes.ml.cluster import KMeans

num_clusters = 5
cluster_model = KMeans(n_clusters=num_clusters)
cluster_model.fit(valid_embeddings["ml_generate_embedding_result"])
clusters = cluster_model.predict(valid_embeddings)
clusters.peek()

أزِل أي أخطاء في التضمين.

mask = clusters["ml_generate_embedding_status"] == ""
clusters = clusters[mask]

يمكنك إلقاء نظرة سريعة على توزيع التعليقات لكل مركز ثقل.

clusters.groupby("CENTROID_ID").size()

7. تلخيص المجموعات

قدِّم بعض التعليقات المرتبطة بكل نقطة مركزية واطلب من Gemini تلخيص الشكاوى. هندسة الطلبات هي مجال ناشئ، ولكن هناك أمثلة جيدة على الإنترنت، مثل https://www.promptingguide.ai/.

from bigframes.ml.llm import GeminiTextGenerator

preamble = "What is the main concern in this list of user complaints:"
suffix = "Write the main issue using a formal tone."

# Now let's sample the raw comments and get the LLM to summarize them.
prompts = []
for centroid_id in range(1, num_clusters + 1):
  cluster = clusters[clusters["CENTROID_ID"] == centroid_id]
  comments = "\n".join(["- {0}".format(x) for x in cluster.content.peek(40)])
  prompts.append("{}:\n{}\n{}".format(preamble, comments, suffix))

prompt_df = bpd.DataFrame(prompts)
gemini = GeminiTextGenerator(model_name="gemini-1.5-flash-001")
issues = gemini.predict(X=prompt_df, temperature=0.0)
issues.peek()

استخدام Gemini لكتابة تقرير من الملخّصات

from IPython.display import display, Markdown

prompt = "Turn this list of issues into a short, concise report:"
for value in issues["ml_generate_text_llm_result"]:
  prompt += "- {}".format(value)
prompt += "Using a formal tone, write a markdown text format report."

summary_df = bpd.DataFrame(([prompt]))
summary = gemini.predict(X=summary_df, temperature=0.0)

report = (summary["ml_generate_text_llm_result"].values[0])
display(Markdown(report))

8. تَنظيم

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

9- تهانينا!

لقد حلّلت بيانات منظَّمة وغير منظَّمة باستخدام BigQuery DataFrames. خلال هذه الرحلة، استكشفت مجموعات البيانات العامة في Google Cloud، ودفاتر ملاحظات Python في BigQuery Studio، وBigQuery ML، وVertex AI، وميزات اللغة الطبيعية إلى Python في BigQuery Studio. أحسنت!

الخطوات التالية