PySpark برنامج تعليمي للمبتدئين: تعلم مع الأمثلة

قبل تعلم PySpark، فلنفهم:

ما هو اباتشي Spark?

Spark هو حل للبيانات الضخمة ثبت أنه أسهل وأسرع من Hadoop MapReduce. Spark هو برنامج مفتوح المصدر تم تطويره بواسطة مختبر UC Berkeley RAD في عام 2009. ومنذ طرحه للجمهور في عام 2010، Spark نمت شعبيتها ويتم استخدامها من خلال الصناعة على نطاق غير مسبوق.

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

ما هو بيSpark?

PySpark هي أداة تم إنشاؤها بواسطة أباتشي Spark مجتمع لاستخدام بايثون مع Spark. يسمح بالعمل مع RDD (مجموعة البيانات الموزعة المرنة) في Python. كما يقدم PySpark Shell لربط واجهات برمجة تطبيقات Python مع Spark الأساسية للبدء Spark سياق الكلام. Spark هو اسم المحرك لتحقيق الحوسبة العنقودية، بينما PySpark هي مكتبة بايثون للاستخدام Spark.

كيف Spark العمل؟

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

كيف Spark للعمل
كيف Spark للعمل

Spark صمم للعمل مع

  • بايثون
  • جافا
  • سكالا
  • SQL

سمة هامة من Spark هو الكم الهائل من المكتبات المدمجة، بما في ذلك MLlib للتعلم الآلي. Spark تم تصميمه أيضًا للعمل مع مجموعات Hadoop ويمكنه قراءة أنواع واسعة من الملفات، بما في ذلك بيانات Hive وCSV وJSON وCasandra data وغيرها.

لماذا استخدام Spark?

كممارس بيانات مستقبلي، يجب أن تكون على دراية بمكتبات بايثون الشهيرة: Pandas وScikit-Learn. تعتبر هاتان المكتبتان رائعتين لاستكشاف مجموعة البيانات حتى الحجم المتوسط. يتم إنشاء مشاريع التعلم الآلي المنتظمة حول ما يليwing المنهجية:

  • تحميل البيانات إلى القرص
  • استيراد البيانات إلى ذاكرة الجهاز
  • معالجة/تحليل البيانات
  • بناء نموذج التعلم الآلي
  • قم بتخزين التنبؤ مرة أخرى على القرص

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

ومع ذلك، هناك بعض المشاكل مع هذا:

  • هل تعكس مجموعة البيانات العالم الحقيقي؟
  • هل تتضمن البيانات مثالاً محددًا؟
  • هل النموذج مناسب لأخذ العينات؟

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

ماهو الحل؟

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

Pyspark يمنح عالم البيانات واجهة برمجة التطبيقات (API) التي يمكن استخدامها لحل مشكلات متابعة البيانات المتوازية. السنة التحضيريةspark يتعامل مع كومplexعمليات المعالجة المتعددة، مثل توزيع البيانات، وتوزيع التعليمات البرمجية، وجمع المخرجات من العاملين على مجموعة من الآلات.

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

• واحدة من المزايا الرئيسية Spark هو بناء archiتقنية تشمل إدارة تدفق البيانات، واستعلامات البيانات بسلاسة، والتنبؤ بالتعلم الآلي، والوصول في الوقت الفعلي إلى التحليلات المختلفة.

• Spark يعمل بشكل وثيق مع لغة SQL، أي البيانات المنظمة. يسمح بالاستعلام عن البيانات في الوقت الحقيقي.

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

في هذا بايSpark البرنامج التعليمي، سوف تتعلم كيفية بناء مصنف مع PySpark أمثلة.

كيفية تثبيت PySpark مع AWS

• Jupyter يقوم الفريق ببناء صورة Docker للتشغيل Spark بكفاءة. فيما يلي الخطوات التي يمكنك اتباعها لتثبيت PySpark مثيل في AWS.

الرجوع إلى البرنامج التعليمي لدينا على AWS و TensorFlow

الخطوة 1: إنشاء مثيل

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

الخطوة 2: افتح الاتصال

افتح الاتصال وقم بتثبيت حاوية عامل الإرساء. للمزيد ديtails، ارجع إلى البرنامج التعليمي مع TensorFlow مع عامل في حوض السفن. لاحظ أنه يجب أن تكون في دليل العمل الصحيح.

ما عليك سوى تشغيل هذه الرموز لتثبيت Docker:

sudo yum update -y
sudo yum install -y docker
sudo service docker start
sudo user-mod -a -G docker ec2-user
exit

الخطوة 3: أعد فتح الاتصال والتثبيت Spark

بعد إعادة فتح الاتصال، يمكنك تثبيت الصورة التي تحتوي على PySpark.

## Spark
docker run -v ~/work:/home/jovyan/work -d -p 8888:8888 jupyter/pyspark-notebook

## Allow preserving Jupyter notebook
sudo chown 1000 ~/work

## Install tree to see our working directory next
sudo yum install -y tree

الخطوة 4: مفتوح Jupyter

تحقق من الحاوية واسمها

docker ps

قم بتشغيل عامل الإرساء باستخدام سجلات عامل الإرساء متبوعة باسم عامل الإرساء. على سبيل المثال، يقوم عامل الإرساء بتسجيل zealous_goldwasser

انتقل إلى المتصفح الخاص بك وابدأ Jupyter. العنوان هو http://localhost:8888/. الصق كلمة المرور التي قدمتها المحطة.

ملاحظات: إذا كنت تريد تحميل/تنزيل ملف على جهاز AWS الخاص بك، فيمكنك استخدام برنامج Cyberduck، https://cyberduck.io/.

كيفية تثبيت PySpark on Windows/ ماك مع كوندا

فولوwing هي عملية مفصلة حول كيفية تثبيت PySpark on Windows/ ماك باستخدام أناكوندا:

لتثبيت Spark على جهازك المحلي، من الممارسات الموصى بها إنشاء بيئة كوندا جديدة. ستقوم هذه البيئة الجديدة بتثبيت Python 3.6، Spark وجميع التبعيات.

مستخدم Mac

cd anaconda3
touch hello-spark.yml
vi hello-spark.yml

Windows مستخدم

cd C:\Users\Admin\Anaconda3
echo.>hello-spark.yml
notepad hello-spark.yml

يمكنك تحرير ملف .yml. كن حذرا مع المسافة البادئة. مطلوب مسافتين قبل –

name: hello-spark 
    dependencies:
    
    - python=3.6
    - jupyter
    - ipython
    - numpy
    - numpy-base
    - pandas
    - py4j
    - pyspark
    - pytz

احفظه وأنشئ البيئة. إنه يستغرق بعض الوقت

conda env create -f hello-spark.yml

للمزيد ديtails حول الموقع، يرجى مراجعة البرنامج التعليمي لتثبيت TensorFlow

يمكنك التحقق من كافة البيئة المثبتة في جهازك

conda env list
Activate hello-spark

مستخدم Mac

source activate hello-spark

Windows مستخدم

activate hello-spark

ملحوظة: لقد قمت بالفعل بإنشاء بيئة TensorFlow محددة لتشغيل البرامج التعليمية على TensorFlow. يعد إنشاء بيئة جديدة مختلفة عن hello-tf أكثر ملاءمة. ليس من المنطقي التحميل الزائد لـ hello-tf Spark أو أي مكتبات أخرى للتعلم الآلي.

تخيل أن معظم مشروعك يتضمن TensorFlow، لكنك تحتاج إلى استخدامه Spark لمشروع واحد معين. يمكنك تعيين بيئة TensorFlow لكل مشروعك وإنشاء بيئة منفصلة له Spark. يمكنك إضافة أكبر عدد ممكن من المكتبات في Spark البيئة كما تريد دون التدخل في بيئة TensorFlow. بمجرد الانتهاء من ذلك Sparkمشروع، يمكنك محوه دون التأثير على بيئة TensorFlow.

Jupyter

ساعات العمل Jupyter دفتر الملاحظات وحاول إذا PySpark يعمل. في دفتر ملاحظات جديد، قم بلصق المتابعةwing PySpark عينة من الرموز:

import pyspark
from pyspark import SparkContext
sc =SparkContext()

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

إذا كنت بحاجة إلى تثبيت Java، عليك أن تفكر الصفحة وتحميل jdk-8u181-windows-x64.exe

Jupyter

بالنسبة لمستخدمي Mac، يوصى باستخدام "brew".

brew tap caskroom/versions
brew cask install java8

الرجوع إلى هذا البرنامج التعليمي خطوة بخطوة على كيفية تثبيت جافا

ملاحظات: استخدم الإزالة لمسح البيئة بالكامل.

 conda env remove -n hello-spark -y

Spark السياق

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

إنشاء Sparkالسياق

بادئ ذي بدء، تحتاج إلى بدء Sparkسياق الكلام.

import pyspark
from pyspark import SparkContext
sc =SparkContext()

الآن وبعد أن Sparkالسياق جاهز، يمكنك إنشاء مجموعة من البيانات تسمى RDD، مجموعة البيانات الموزعة المرنة. تتم موازنة العمليات الحسابية في RDD تلقائيًا عبر المجموعة.

nums= sc.parallelize([1,2,3,4])

يمكنك الوصول إلى الصف الأول باستخدام اللقطة

nums.take(1)
[1]

يمكنك تطبيق تحويل على البيانات باستخدام دالة لامدا. في بايSpark المثال أدناه، تقوم بإرجاع مربع الأعداد. إنه تحول الخريطة

squared = nums.map(lambda x: x*x).collect()
for num in squared:
    print('%i ' % (num))
1 
4 
9 
16

SQLContext

الطريقة الأكثر ملاءمة هي استخدام DataFrame. Sparkتم تعيين السياق بالفعل، ويمكنك استخدامه لإنشاء dataFrame. تحتاج أيضًا إلى الإعلان عن SQLContext

يسمح SQLContext بتوصيل المحرك بمصادر بيانات مختلفة. يتم استخدامه لبدء وظائف Spark SQL.

from pyspark.sql import Row
from pyspark.sql import SQLContext

sqlContext = SQLContext(sc)

الآن في هذا Spark البرنامج التعليمي لبايثون، لنقم بإنشاء قائمة من Tuple. ستحتوي كل صف على اسم الأشخاص وأعمارهم. مطلوب أربع خطوات:

الخطوة 1) قم بإنشاء قائمة Tuple بالمعلومات

[('John',19),('Smith',29),('Adam',35),('Henry',50)]

الخطوة 2) بناء RDD

rdd = sc.parallelize(list_p)

الخطوة 3) تحويل الصفوف

rdd.map(lambda x: Row(name=x[0], age=int(x[1])))

الخطوة 4) إنشاء سياق DataFrame

sqlContext.createDataFrame(ppl)
list_p = [('John',19),('Smith',29),('Adam',35),('Henry',50)]
rdd = sc.parallelize(list_p)
ppl = rdd.map(lambda x: Row(name=x[0], age=int(x[1])))
DF_ppl = sqlContext.createDataFrame(ppl)

إذا كنت تريد الوصول إلى نوع كل ميزة، فيمكنك استخدام printSchema()

DF_ppl.printSchema()
root
 |-- age: long (nullable = true)
 |-- name: string (nullable = true)

مثال للتعلم الآلي مع PySpark

والآن بعد أن أصبحت لديك فكرة مختصرة عن Spark وSQLContext، أنت جاهز لإنشاء أول برنامج للتعلم الآلي.

فولوwing هي خطوات إنشاء برنامج للتعلم الآلي باستخدام PySpark:

  • الخطوة 1) العملية الأساسية مع PySpark
  • الخطوة 2) معالجة البيانات
  • الخطوة 3) بناء خط أنابيب لمعالجة البيانات
  • الخطوة 4) بناء المصنف: لوجستي
  • الخطوة 5) تدريب وتقييم النموذج
  • الخطوة 6) ضبط المعلمة الفائقة

في هذا بايSpark البرنامج التعليمي للتعلم الآلي، سوف نستخدم مجموعة بيانات البالغين. الغرض من هذا البرنامج التعليمي هو معرفة كيفية استخدام Pyspark. لمزيد من المعلومات حول مجموعة البيانات، راجع هذا البرنامج التعليمي.

لاحظ أن مجموعة البيانات ليست مهمة وقد تعتقد أن الحساب يستغرق وقتًا طويلاً. Spark تم تصميمه لمعالجة كمية كبيرة من البيانات. Sparkيزداد أداء s مقارنةً بمكتبات التعلم الآلي الأخرى عندما تنمو مجموعة البيانات المعالجة بشكل أكبر.

الخطوة 1) العملية الأساسية مع PySpark

أولا وقبل كل شيء، تحتاج إلى تهيئة SQLContext الذي لم يبدأ بالفعل بعد.

#from pyspark.sql import SQLContext
url = "https://raw.githubusercontent.com/guru99-edu/R-Programming/master/adult_data.csv"
from pyspark import SparkFiles
sc.addFile(url)
sqlContext = SQLContext(sc)

وبعد ذلك، يمكنك قراءة ملف السيرة الذاتية باستخدام sqlContext.read.csv. يمكنك استخدام inferSchema المعين على True to say Spark لتخمين نوع البيانات تلقائيا. بشكل افتراضي، يتم تشغيله إلى False.

df = sqlContext.read.csv(SparkFiles.get("adult_data.csv"), header=True, inferSchema= True)

دعونا نلقي نظرة على نوع البيانات

df.printSchema()
root
 |-- age: integer (nullable = true)
 |-- workclass: string (nullable = true)
 |-- fnlwgt: integer (nullable = true)
 |-- education: string (nullable = true)
 |-- education_num: integer (nullable = true)
 |-- marital: string (nullable = true)
 |-- occupation: string (nullable = true)
 |-- relationship: string (nullable = true)
 |-- race: string (nullable = true)
 |-- sex: string (nullable = true)
 |-- capital_gain: integer (nullable = true)
 |-- capital_loss: integer (nullable = true)
 |-- hours_week: integer (nullable = true)
 |-- native_country: string (nullable = true)
 |-- label: string (nullable = true)

يمكنك رؤية البيانات مع العرض.

df.show(5, truncate = False)
+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+----------+--------------+-----+
|age|workclass       |fnlwgt|education|education_num|marital           |occupation       |relationship |race |sex   |capital_gain|capital_loss|hours_week|native_country|label|
+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+----------+--------------+-----+
|39 |State-gov       |77516 |Bachelors|13           |Never-married     |Adm-clerical     |Not-in-family|White|Male  |2174        |0           |40        |United-States |<=50K|
|50 |Self-emp-not-inc|83311 |Bachelors|13           |Married-civ-spouse|Exec-managerial  |Husband      |White|Male  |0           |0           |13        |United-States |<=50K|
|38 |Private         |215646|HS-grad  |9            |Divorced          |Handlers-cleaners|Not-in-family|White|Male  |0           |0           |40        |United-States |<=50K|
|53 |Private         |234721|11th     |7            |Married-civ-spouse|Handlers-cleaners|Husband      |Black|Male  |0           |0           |40        |United-States |<=50K|
|28 |Private         |338409|Bachelors|13           |Married-civ-spouse|Prof-specialty   |Wife         |Black|Female|0           |0           |40        |Cuba          |<=50K|
+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+----------+--------------+-----+
only showing top 5 rows

إذا لم تقم بتعيين inderShema على True، فإليك ما يحدث للنوع. هناك كل شيء في السلسلة.

df_string = sqlContext.read.csv(SparkFiles.get("adult.csv"), header=True, inferSchema=  False)
df_string.printSchema()
root
 |-- age: string (nullable = true)
 |-- workclass: string (nullable = true)
 |-- fnlwgt: string (nullable = true)
 |-- education: string (nullable = true)
 |-- education_num: string (nullable = true)
 |-- marital: string (nullable = true)
 |-- occupation: string (nullable = true)
 |-- relationship: string (nullable = true)
 |-- race: string (nullable = true)
 |-- sex: string (nullable = true)
 |-- capital_gain: string (nullable = true)
 |-- capital_loss: string (nullable = true)
 |-- hours_week: string (nullable = true)
 |-- native_country: string (nullable = true)
 |-- label: string (nullable = true)

لتحويل المتغير المستمر إلى التنسيق الصحيح، يمكنك استخدام إعادة صياغة الأعمدة. يمكنك استخدام withColumn لمعرفة ذلك Spark أي عمود لتشغيل التحويل.

# Import all from `sql.types`
from pyspark.sql.types import *

# Write a custom function to convert the data type of DataFrame columns
def convertColumn(df, names, newType):
    for name in names: 
        df = df.withColumn(name, df[name].cast(newType))
    return df 
# List of continuous features
CONTI_FEATURES  = ['age', 'fnlwgt','capital_gain', 'education_num', 'capital_loss', 'hours_week']
# Convert the type
df_string = convertColumn(df_string, CONTI_FEATURES, FloatType())
# Check the dataset
df_string.printSchema()
root
 |-- age: float (nullable = true)
 |-- workclass: string (nullable = true)
 |-- fnlwgt: float (nullable = true)
 |-- education: string (nullable = true)
 |-- education_num: float (nullable = true)
 |-- marital: string (nullable = true)
 |-- occupation: string (nullable = true)
 |-- relationship: string (nullable = true)
 |-- race: string (nullable = true)
 |-- sex: string (nullable = true)
 |-- capital_gain: float (nullable = true)
 |-- capital_loss: float (nullable = true)
 |-- hours_week: float (nullable = true)
 |-- native_country: string (nullable = true)
 |-- label: string (nullable = true)

from pyspark.ml.feature import StringIndexer
#stringIndexer = StringIndexer(inputCol="label", outputCol="newlabel")
#model = stringIndexer.fit(df)
#df = model.transform(df)
df.printSchema()

اختيار الأعمدة

يمكنك تحديد وإظهار الصفوف مع تحديد وأسماء الميزات. أدناه، تم تحديد العمر وfnlwgt.

df.select('age','fnlwgt').show(5)
+---+------+
|age|fnlwgt|
+---+------+
| 39| 77516|
| 50| 83311|
| 38|215646|
| 53|234721|
| 28|338409|
+---+------+
only showing top 5 rows

العد حسب المجموعة

إذا كنت تريد حساب عدد مرات الظهور حسب المجموعة، فيمكنك التسلسل:

  • مجموعة من()
  • عدد()

معاً. في بايSpark في المثال أدناه، يمكنك حساب عدد الصفوف حسب مستوى التعليم.

df.groupBy("education").count().sort("count",ascending=True).show()
+------------+-----+
|   education|count|
+------------+-----+
|   Preschool|   51|
|     1st-4th|  168|
|     5th-6th|  333|
|   Doctorate|  413|
|        12th|  433|
|         9th|  514|
| Prof-school|  576|
|     7th-8th|  646|
|        10th|  933|
|  Assoc-acdm| 1067|
|        11th| 1175|
|   Assoc-voc| 1382|
|     Masters| 1723|
|   Bachelors| 5355|
|Some-college| 7291|
|     HS-grad|10501|
+------------+-----+

وصف البيانات

للحصول على إحصائيات ملخصة للبيانات، يمكنك استخدام الوصف (). سوف يقوم بحساب :

  • عد
  • تعني
  • الانحراف المعياري
  • دقيقة
  • ماكس
df.describe().show()
+-------+------------------+-----------+------------------+------------+-----------------+--------+----------------+------------+------------------+------+------------------+----------------+------------------+--------------+-----+
|summary|               age|  workclass|            fnlwgt|   education|    education_num| marital|      occupation|relationship|              race|   sex|      capital_gain|    capital_loss|        hours_week|native_country|label|
+-------+------------------+-----------+------------------+------------+-----------------+--------+----------------+------------+------------------+------+------------------+----------------+------------------+--------------+-----+
|  count|             32561|      32561|             32561|       32561|            32561|   32561|           32561|       32561|             32561| 32561|             32561|           32561|             32561|         32561|32561|
|   mean| 38.58164675532078|       null|189778.36651208502|        null| 10.0806793403151|    null|            null|        null|              null|  null|1077.6488437087312| 87.303829734959|40.437455852092995|          null| null|
| stddev|13.640432553581356|       null|105549.97769702227|        null|2.572720332067397|    null|            null|        null|              null|  null| 7385.292084840354|402.960218649002|12.347428681731838|          null| null|
|    min|                17|          ?|             12285|        10th|                1|Divorced|               ?|     Husband|Amer-Indian-Eskimo|Female|                 0|               0|                 1|             ?|<=50K|
|    max|                90|Without-pay|           1484705|Some-college|               16| Widowed|Transport-moving|        Wife|             White|  Male|             99999|            4356|                99|    Yugoslavia| >50K|
+-------+------------------+-----------+------------------+------------+-----------------+--------+----------------+------------+------------------+------+------------------+----------------+------------------+--------------+-----+

إذا كنت تريد إحصائيات التلخيص لعمود واحد فقط، أضف اسم العمود داخل description()

df.describe('capital_gain').show()
+-------+------------------+
|summary|      capital_gain|
+-------+------------------+
|  count|             32561|
|   mean|1077.6488437087312|
| stddev| 7385.292084840354|
|    min|                 0|
|    max|             99999|
+-------+------------------+

حساب الجدولي

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

df.crosstab('age', 'label').sort("age_label").show()
+---------+-----+----+
|age_label|<=50K|>50K|
+---------+-----+----+
|       17|  395|   0|
|       18|  550|   0|
|       19|  710|   2|
|       20|  753|   0|
|       21|  717|   3|
|       22|  752|  13|
|       23|  865|  12|
|       24|  767|  31|
|       25|  788|  53|
|       26|  722|  63|
|       27|  754|  81|
|       28|  748| 119|
|       29|  679| 134|
|       30|  690| 171|
|       31|  705| 183|
|       32|  639| 189|
|       33|  684| 191|
|       34|  643| 243|
|       35|  659| 217|
|       36|  635| 263|
+---------+-----+----+
only showing top 20 rows

لا يمكنك أن ترى أن أي شخص لديه إيرادات تزيد عن 50 ألفًا عندما يكون صغيرًا.

عمود الإسقاط

هناك نوعان من واجهة برمجة التطبيقات البديهية لإسقاط الأعمدة:

  • إسقاط (): إسقاط عمود
  • dropna(): إسقاط NA

أدناه تقوم بإسقاط العمود education_num

df.drop('education_num').columns

['age',
 'workclass',
 'fnlwgt',
 'education',
 'marital',
 'occupation',
 'relationship',
 'race',
 'sex',
 'capital_gain',
 'capital_loss',
 'hours_week',
 'native_country',
 'label']

تصفية البيانات

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

df.filter(df.age > 40).count()

13443

إحصائيات وصفية حسب المجموعة

وأخيرًا، يمكنك تجميع البيانات حسب المجموعة وحساب العمليات الإحصائية مثل المتوسط.

df.groupby('marital').agg({'capital_gain': 'mean'}).show()
+--------------------+------------------+
|             marital| avg(capital_gain)|
+--------------------+------------------+
|           Separated| 535.5687804878049|
|       Never-married|376.58831788823363|
|Married-spouse-ab...| 653.9832535885167|
|            Divorced| 728.4148098131893|
|             Widowed| 571.0715005035247|
|   Married-AF-spouse| 432.6521739130435|
|  Married-civ-spouse|1764.8595085470085|
+--------------------+------------------+

الخطوة 2) المعالجة المسبقة للبيانات

تعد معالجة البيانات خطوة حاسمة في التعلم الآلي. بعد إزالة البيانات المهملة، يمكنك الحصول على بعض الأفكار المهمة.

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

أضف مربع العمر

لإضافة ميزة جديدة، يجب عليك:

  1. حدد العمود
  2. قم بتطبيق التحويل وإضافته إلى DataFrame
from pyspark.sql.functions import *

# 1 Select the column
age_square = df.select(col("age")**2)

# 2 Apply the transformation and add it to the DataFrame
df = df.withColumn("age_square", col("age")**2)

df.printSchema()
root
 |-- age: integer (nullable = true)
 |-- workclass: string (nullable = true)
 |-- fnlwgt: integer (nullable = true)
 |-- education: string (nullable = true)
 |-- education_num: integer (nullable = true)
 |-- marital: string (nullable = true)
 |-- occupation: string (nullable = true)
 |-- relationship: string (nullable = true)
 |-- race: string (nullable = true)
 |-- sex: string (nullable = true)
 |-- capital_gain: integer (nullable = true)
 |-- capital_loss: integer (nullable = true)
 |-- hours_week: integer (nullable = true)
 |-- native_country: string (nullable = true)
 |-- label: string (nullable = true)
 |-- age_square: double (nullable = true)

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

COLUMNS = ['age', 'age_square', 'workclass', 'fnlwgt', 'education', 'education_num', 'marital',
           'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss',
           'hours_week', 'native_country', 'label']
df = df.select(COLUMNS)
df.first()
Row(age=39, age_square=1521.0, workclass='State-gov', fnlwgt=77516, education='Bachelors', education_num=13, marital='Never-married', occupation='Adm-clerical', relationship='Not-in-family', race='White', sex='Male', capital_gain=2174, capital_loss=0, hours_week=40, native_country='United-States', label='<=50K')

استبعاد هولندا-هولندا

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

دعونا نتحقق من أصل الأسرة

df.filter(df.native_country == 'Holand-Netherlands').count()
df.groupby('native_country').agg({'native_country': 'count'}).sort(asc("count(native_country)")).show()
+--------------------+---------------------+
|      native_country|count(native_country)|
+--------------------+---------------------+
|  Holand-Netherlands|                    1|
|            Scotland|                   12|
|             Hungary|                   13|
|            Honduras|                   13|
|Outlying-US(Guam-...|                   14|
|          Yugoslavia|                   16|
|            Thailand|                   18|
|                Laos|                   18|
|            Cambodia|                   19|
|     Trinadad&Tobago|                   19|
|                Hong|                   20|
|             Ireland|                   24|
|             Ecuador|                   28|
|              Greece|                   29|
|              France|                   29|
|                Peru|                   31|
|           Nicaragua|                   34|
|            Portugal|                   37|
|                Iran|                   43|
|               Haiti|                   44|
+--------------------+---------------------+
only showing top 20 rows

تضم الميزة original_country أسرة واحدة فقط قادمة من هولندا. أنت تستبعده.

df_remove = df.filter(df.native_country !=	'Holand-Netherlands')

الخطوة 3) بناء خط أنابيب معالجة البيانات

على غرار scikit-Learn، Pyspark لديه API خط الأنابيب.

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

على سبيل المثال، أحد التحولات الشاملة في التعلم الآلي يتكون من تحويل سلسلة إلى برنامج تشفير واحد ساخن، أي عمود واحد بواسطة مجموعة. عادةً ما يكون أحد برامج التشفير الساخنة عبارة عن مصفوفة مليئة بالأصفار.

خطوات تحويل البيانات مشابهة جدًا لخطوات scikit-Learn. أنت بحاجه إلى:

  • فهرسة السلسلة إلى رقمية
  • قم بإنشاء برنامج تشفير سريع واحد
  • تحويل البيانات

هناك واجهتان من واجهات برمجة التطبيقات (APIs) تقومان بهذه المهمة: StringIndexer وOneHotEncoder

  1. أولاً، عليك تحديد عمود السلسلة المراد فهرسته. inputCol هو اسم العمود في مجموعة البيانات. OutputCol هو الاسم الجديد المعطى للعمود المحول.
StringIndexer(inputCol="workclass", outputCol="workclass_encoded")
  1. احتواء البيانات وتحويلها
model = stringIndexer.fit(df)		
`indexed = model.transform(df)``
  1. قم بإنشاء أعمدة الأخبار بناءً على المجموعة. على سبيل المثال، إذا كانت هناك 10 مجموعات في الميزة، فستحتوي المصفوفة الجديدة على 10 أعمدة، عمود واحد لكل مجموعة.
OneHotEncoder(dropLast=False, inputCol="workclassencoded", outputCol="workclassvec")
### Example encoder
from pyspark.ml.feature import StringIndexer, OneHotEncoder, VectorAssembler

stringIndexer = StringIndexer(inputCol="workclass", outputCol="workclass_encoded")
model = stringIndexer.fit(df)
indexed = model.transform(df)
encoder = OneHotEncoder(dropLast=False, inputCol="workclass_encoded", outputCol="workclass_vec")
encoded = encoder.transform(indexed)
encoded.show(2)
+---+----------+----------------+------+---------+-------------+------------------+---------------+-------------+-----+----+------------+------------+----------+--------------+-----+-----------------+-------------+
|age|age_square|       workclass|fnlwgt|education|education_num|           marital|     occupation| relationship| race| sex|capital_gain|capital_loss|hours_week|native_country|label|workclass_encoded|workclass_vec|
+---+----------+----------------+------+---------+-------------+------------------+---------------+-------------+-----+----+------------+------------+----------+--------------+-----+-----------------+-------------+
| 39|    1521.0|       State-gov| 77516|Bachelors|           13|     Never-married|   Adm-clerical|Not-in-family|White|Male|        2174|           0|        40| United-States|<=50K|              4.0|(9,[4],[1.0])|
| 50|    2500.0|Self-emp-not-inc| 83311|Bachelors|           13|Married-civ-spouse|Exec-managerial|      Husband|White|Male|           0|           0|        13| United-States|<=50K|              1.0|(9,[1],[1.0])|
+---+----------+----------------+------+---------+-------------+------------------+---------------+-------------+-----+----+------------+------------+----------+--------------+-----+-----------------+-------------+
only showing top 2 rows

بناء خط الانابيب

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

  1. تشفير البيانات الفئوية
  2. فهرسة ميزة التسمية
  3. إضافة متغير مستمر
  4. تجميع الخطوات.

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

1. تشفير البيانات الفئوية

هذه الخطوة هي تمامًا نفس المثال أعلاه، باستثناء أنك تقوم بالتكرار فوق جميع الميزات الفئوية.

from pyspark.ml import Pipeline
from pyspark.ml.feature import OneHotEncoderEstimator
CATE_FEATURES = ['workclass', 'education', 'marital', 'occupation', 'relationship', 'race', 'sex', 'native_country']
stages = [] # stages in our Pipeline
for categoricalCol in CATE_FEATURES:
    stringIndexer = StringIndexer(inputCol=categoricalCol, outputCol=categoricalCol + "Index")
    encoder = OneHotEncoderEstimator(inputCols=[stringIndexer.getOutputCol()],
                                     outputCols=[categoricalCol + "classVec"])
    stages += [stringIndexer, encoder]

2. قم بفهرسة ميزة التسمية

Spark، مثل العديد من المكتبات الأخرى، لا تقبل قيم السلسلة للتسمية. يمكنك تحويل ميزة التسمية باستخدام StringIndexer وإضافتها إلى مراحل القائمة

# Convert label into label indices using the StringIndexer
label_stringIdx =  StringIndexer(inputCol="label", outputCol="newlabel")
stages += [label_stringIdx]

3. إضافة متغير مستمر

إن inputCols الخاص بـ VectorAssembler عبارة عن قائمة من الأعمدة. يمكنك إنشاء قائمة جديدة تحتوي على كافة الأعمدة الجديدة. يقوم الكود الموجود أدناه بملء القائمة بالميزات الفئوية المشفرة والميزات المستمرة.

assemblerInputs = [c + "classVec" for c in CATE_FEATURES] + CONTI_FEATURES

4. قم بتجميع الخطوات.

وأخيرًا، قمت باجتياز كافة الخطوات الموجودة في VectorAssembler

assembler = VectorAssembler(inputCols=assemblerInputs, outputCol="features")stages += [assembler]

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

# Create a Pipeline.
pipeline = Pipeline(stages=stages)
pipelineModel = pipeline.fit(df_remove)
model = pipelineModel.transform(df_remove)

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

model.take(1)

[Row(age=39, age_square=1521.0, workclass='State-gov', fnlwgt=77516, education='Bachelors', education_num=13, marital='Never-married', occupation='Adm-clerical', relationship='Not-in-family', race='White', sex='Male', capital_gain=2174, capital_loss=0, hours_week=40, native_country='United-States', label='<=50K', workclassIndex=4.0, workclassclassVec=SparseVector(8, {4: 1.0}), educationIndex=2.0, educationclassVec=SparseVector(15, {2: 1.0}), maritalIndex=1.0, maritalclassVec=SparseVector(6, {1: 1.0}), occupationIndex=3.0, occupationclassVec=SparseVector(14, {3: 1.0}), relationshipIndex=1.0, relationshipclassVec=SparseVector(5, {1: 1.0}), raceIndex=0.0, raceclassVec=SparseVector(4, {0: 1.0}), sexIndex=0.0, sexclassVec=SparseVector(1, {0: 1.0}), native_countryIndex=0.0, native_countryclassVec=SparseVector(40, {0: 1.0}), newlabel=0.0, features=SparseVector(99, {4: 1.0, 10: 1.0, 24: 1.0, 32: 1.0, 44: 1.0, 48: 1.0, 52: 1.0, 53: 1.0, 93: 39.0, 94: 77516.0, 95: 2174.0, 96: 13.0, 98: 40.0}))]

الخطوة 4) بناء المصنف: لوجستي

لجعل الحساب أسرع، يمكنك تحويل النموذج إلى DataFrame.

تحتاج إلى تحديد التسمية الجديدة والميزات من النموذج باستخدام الخريطة.

from pyspark.ml.linalg import DenseVector
input_data = model.rdd.map(lambda x: (x["newlabel"], DenseVector(x["features"])))

أنت جاهز لإنشاء بيانات القطار كإطار بيانات. يمكنك استخدام sqlContext

df_train = sqlContext.createDataFrame(input_data, ["label", "features"])

تحقق من الصف الثاني

df_train.show(2)
+-----+--------------------+
|label|            features|
+-----+--------------------+
|  0.0|[0.0,0.0,0.0,0.0,...|
|  0.0|[0.0,1.0,0.0,0.0,...|
+-----+--------------------+
only showing top 2 rows

قم بإنشاء مجموعة تدريب/اختبار

لقد قمت بتقسيم مجموعة البيانات بنسبة 80/20 باستخدام RandomSplit.

# Split the data into train and test sets
train_data, test_data = df_train.randomSplit([.8,.2],seed=1234)

دعونا نحسب عدد الأشخاص الذين لديهم دخل أقل/أعلى من 50 ألفًا في كل من مجموعة التدريب والاختبار

train_data.groupby('label').agg({'label': 'count'}).show()
+-----+------------+
|label|count(label)|
+-----+------------+
|  0.0|       19698|
|  1.0|        6263|
+-----+------------+
test_data.groupby('label').agg({'label': 'count'}).show()
+-----+------------+
|label|count(label)|
+-----+------------+
|  0.0|        5021|
|  1.0|        1578|
+-----+------------+

بناء التراجع اللوجستي

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

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

# Import `LinearRegression`
from pyspark.ml.classification import LogisticRegression

# Initialize `lr`
lr = LogisticRegression(labelCol="label",
                        featuresCol="features",
                        maxIter=10,
                        regParam=0.3)

# Fit the data to the model
linearModel = lr.fit(train_data)

# يمكنك رؤية المعاملات من الانحدار

# Print the coefficients and intercept for logistic regression
print("Coefficients: " + str(linearModel.coefficients))
print("Intercept: " + str(linearModel.intercept))
Coefficients: [-0.0678914665262,-0.153425526813,-0.0706009536407,-0.164057586562,-0.120655298528,0.162922330862,0.149176870438,-0.626836362611,-0.193483661541,-0.0782269980838,0.222667203836,0.399571096381,-0.0222024341804,-0.311925857859,-0.0434497788688,-0.306007744328,-0.41318209688,0.547937504247,-0.395837350854,-0.23166535958,0.618743906733,-0.344088614546,-0.385266881369,0.317324463006,-0.350518889186,-0.201335923138,-0.232878560088,-0.13349278865,-0.119760542498,0.17500602491,-0.0480968101118,0.288484253943,-0.116314616745,0.0524163478063,-0.300952624551,-0.22046421474,-0.16557996579,-0.114676231939,-0.311966431453,-0.344226119233,0.105530129507,0.152243047814,-0.292774545497,0.263628334433,-0.199951374076,-0.30329422583,-0.231087515178,0.418918551,-0.0565930184279,-0.177818073048,-0.0733236680663,-0.267972912252,0.168491215697,-0.12181255723,-0.385648075442,-0.202101794517,0.0469791640782,-0.00842850210625,-0.00373211448629,-0.259296141281,-0.309896554133,-0.168434409756,-0.11048086026,0.0280647963877,-0.204187030092,-0.414392623536,-0.252806580669,0.143366465705,-0.516359222663,-0.435627370849,-0.301949286524,0.0878249035894,-0.210951740965,-0.621417928742,-0.099445190784,-0.232671473401,-0.1077745606,-0.360429419703,-0.420362959052,-0.379729467809,-0.395186242741,0.0826401853838,-0.280251589972,0.187313505214,-0.20295228799,-0.431177064626,0.149759018379,-0.107114299614,-0.319314858424,0.0028450133235,-0.651220387649,-0.327918792207,-0.143659581445,0.00691075160413,8.38517628783e-08,2.18856717378e-05,0.0266701216268,0.000231075966823,0.00893832698698]
Intercept: -1.9884177974805692

الخطوة 5) تدريب النموذج وتقييمه

لتوليد التنبؤ لمجموعة الاختبار الخاصة بك،

يمكنك استخدام الخط الخطي مع التحويل () في test_data

# Make predictions on test data using the transform() method.
predictions = linearModel.transform(test_data)

يمكنك طباعة العناصر في التنبؤات

predictions.printSchema()
root
 |-- label: double (nullable = true)
 |-- features: vector (nullable = true)
 |-- rawPrediction: vector (nullable = true)
 |-- probability: vector (nullable = true)
 |-- prediction: double (nullable = false)

أنت مهتم بالتسمية والتنبؤ والاحتمال

selected = predictions.select("label", "prediction", "probability")
selected.show(20)
+-----+----------+--------------------+
|label|prediction|         probability|
+-----+----------+--------------------+
|  0.0|       0.0|[0.91560704124179...|
|  0.0|       0.0|[0.92812140213994...|
|  0.0|       0.0|[0.92161406774159...|
|  0.0|       0.0|[0.96222760777142...|
|  0.0|       0.0|[0.66363283056957...|
|  0.0|       0.0|[0.65571324475477...|
|  0.0|       0.0|[0.73053376932829...|
|  0.0|       1.0|[0.31265053873570...|
|  0.0|       0.0|[0.80005907577390...|
|  0.0|       0.0|[0.76482251301640...|
|  0.0|       0.0|[0.84447301189069...|
|  0.0|       0.0|[0.75691912026619...|
|  0.0|       0.0|[0.60902504096722...|
|  0.0|       0.0|[0.80799228385509...|
|  0.0|       0.0|[0.87704364852567...|
|  0.0|       0.0|[0.83817652582377...|
|  0.0|       0.0|[0.79655423248500...|
|  0.0|       0.0|[0.82712311232246...|
|  0.0|       0.0|[0.81372823882016...|
|  0.0|       0.0|[0.59687710752201...|
+-----+----------+--------------------+
only showing top 20 rows

قيم النموذج

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

قبل أن تنظر إلى ROC، دعنا نبني مقياس الدقة. أنت أكثر دراية بهذا المقياس. مقياس الدقة هو مجموع التنبؤ الصحيح على إجمالي عدد الملاحظات.

يمكنك إنشاء DataFrame باستخدام التسمية و"التنبؤ".

cm = predictions.select("label", "prediction")

يمكنك التحقق من عدد الفئة في التسمية والتنبؤ

cm.groupby('label').agg({'label': 'count'}).show()
+-----+------------+
|label|count(label)|
+-----+------------+
|  0.0|        5021|
|  1.0|        1578|
+-----+------------+
cm.groupby('prediction').agg({'prediction': 'count'}).show()
+----------+-----------------+
|prediction|count(prediction)|
+----------+-----------------+
|       0.0|             5982|
|       1.0|              617|
+----------+-----------------+

على سبيل المثال، في مجموعة الاختبار، هناك 1578 أسرة يزيد دخلها عن 50 ألفًا و5021 أدناه. ومع ذلك، توقع المصنف وجود 617 أسرة يزيد دخلها عن 50 ألفًا.

يمكنك حساب الدقة عن طريق حساب العدد عندما يتم تصنيف التسمية بشكل صحيح على إجمالي عدد الصفوف.

cm.filter(cm.label == cm.prediction).count() / cm.count()

0.8237611759357478

يمكنك تجميع كل شيء معًا وكتابة دالة لحساب الدقة.

def accuracy_m(model): 
    predictions = model.transform(test_data)
    cm = predictions.select("label", "prediction")
    acc = cm.filter(cm.label == cm.prediction).count() / cm.count()
    print("Model accuracy: %.3f%%" % (acc * 100)) 
accuracy_m(model = linearModel)
Model accuracy: 82.376%

مقاييس ROC

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

### Use ROC 
from pyspark.ml.evaluation import BinaryClassificationEvaluator

# Evaluate model
evaluator = BinaryClassificationEvaluator(rawPredictionCol="rawPrediction")
print(evaluator.evaluate(predictions))
print(evaluator.getMetricName())

0.8940481662695192 منطقة تحت ROC

print(evaluator.evaluate(predictions))

0.8940481662695192

الخطوة 6) ضبط المعلمة الفائقة

وأخيرًا وليس آخرًا، يمكنك ضبط المعلمات الفائقة. مشابه ل تعلم scikit يمكنك إنشاء شبكة معلمات، وإضافة المعلمات التي تريد ضبطها.

لتقليل وقت الحساب، يمكنك فقط ضبط معلمة التنظيم بقيمتين فقط.

from pyspark.ml.tuning import ParamGridBuilder, CrossValidator

# Create ParamGrid for Cross Validation
paramGrid = (ParamGridBuilder()
             .addGrid(lr.regParam, [0.01, 0.5])
             .build())

وأخيرًا، تقوم بتقييم النموذج باستخدام طريقة التقييم المتقاطع بخمسة طيات. يستغرق التدريب حوالي 5 دقيقة.

from time import *
start_time = time()

# Create 5-fold CrossValidator
cv = CrossValidator(estimator=lr,
                    estimatorParamMaps=paramGrid,
                    evaluator=evaluator, numFolds=5)

# Run cross validations
cvModel = cv.fit(train_data)
# likely take a fair amount of time
end_time = time()
elapsed_time = end_time - start_time
print("Time to train model: %.3f seconds" % elapsed_time)

زمن تدريب النموذج: 978.807 ثانية

أفضل معلمة تنظيمية هي 0.01 بدقة 85.316 بالمائة.

accuracy_m(model = cvModel)
Model accuracy: 85.316%

يمكنك استخراج المعلمة الموصى بها عن طريق ربط cvModel.bestModel مع extractParamMap()

bestModel = cvModel.bestModel
bestModel.extractParamMap()
{Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='aggregationDepth', doc='suggested depth for treeAggregate (>= 2)'): 2,
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='elasticNetParam', doc='the ElasticNet mixing parameter, in range [0, 1]. For alpha = 0, the penalty is an L2 penalty. For alpha = 1, it is an L1 penalty'): 0.0,
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='family', doc='The name of family which is a description of the label distribution to be used in the model. Supported options: auto, binomial, multinomial.'): 'auto',
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='featuresCol', doc='features column name'): 'features',
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='fitIntercept', doc='whether to fit an intercept term'): True,
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='labelCol', doc='label column name'): 'label',
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='maxIter', doc='maximum number of iterations (>= 0)'): 10,
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='predictionCol', doc='prediction column name'): 'prediction',
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='probabilityCol', doc='Column name for predicted class conditional probabilities. Note: Not all models output well-calibrated probability estimates! These probabilities should be treated as confidences, not precise probabilities'): 'probability',
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='rawPredictionCol', doc='raw prediction (a.k.a. confidence) column name'): 'rawPrediction',
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='regParam', doc='regularization parameter (>= 0)'): 0.01,
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='standardization', doc='whether to standardize the training features before fitting the model'): True,
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='threshold', doc='threshold in binary classification prediction, in range [0, 1]'): 0.5,
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='tol', doc='the convergence tolerance for iterative algorithms (>= 0)'): 1e-06}

نبذة عامة

Spark هي أداة أساسية لعالم البيانات. فهو يسمح للممارس بربط التطبيق بمصادر بيانات مختلفة، وإجراء تحليل البيانات بسلاسة أو إضافة نموذج تنبؤي.

لنبدء ب Spark، تحتاج إلى بدء Spark السياق مع:

'Sparkسياق()'

و و SQL سياق الاتصال بمصدر البيانات:

"SQLContext ()"

ستتعلم في البرنامج التعليمي كيفية تدريب الانحدار اللوجستي:

  1. قم بتحويل مجموعة البيانات إلى Dataframe باستخدام:
rdd.map(lambda x: (x["newlabel"], DenseVector(x["features"])))
sqlContext.createDataFrame(input_data, ["label", "features"])

لاحظ أن اسم عمود التسمية هو newlabel ويتم تجميع كافة الميزات في الميزات. قم بتغيير هذه القيم إذا كانت مختلفة في مجموعة البيانات الخاصة بك.

  1. قم بإنشاء مجموعة القطار/الاختبار
randomSplit([.8,.2],seed=1234)
  1. درب النموذج
LogisticRegression(labelCol="label",featuresCol="features",maxIter=10, regParam=0.3)
lr.fit()
  1. يتوقع
linearModel.transform()