แชร์ผ่าน


สร้างแบบจําลองการเรียนรู้ของเครื่องด้วย Apache Spark MLlib

ในบทความนี้คุณจะได้เรียนรู้วิธีการใช้ Apache Spark MLlib เพื่อสร้างแอปพลิเคชันการเรียนรู้ของเครื่องที่ทําการวิเคราะห์เชิงทํานายอย่างง่ายบนชุดข้อมูลเปิดของ Azure Spark มีไลบรารีการเรียนรู้ของเครื่องอยู่แล้วภายใน ตัวอย่างนี้ใช้ การจัดประเภท ผ่านการถดถอยโลจิสติกส์

SparkML และ MLlib เป็นไลบรารี Spark หลักที่มีโปรแกรมอรรถประโยชน์จํานวนมากที่มีประโยชน์สําหรับงานการเรียนรู้ของเครื่อง รวมถึงโปรแกรมอรรถประโยชน์ที่เหมาะสมสําหรับ:

  • การจัดประเภท
  • ถด ถอย
  • การคลัสเตอร์
  • การสร้างแบบจําลองหัวข้อ
  • การวิเคราะห์การแยกย่อยค่าเอกพจน์ (SVD) และการวิเคราะห์คอมโพเนนต์หลัก (PCA)
  • การทดสอบสมมติฐานและการคํานวณสถิติตัวอย่าง

ทําความเข้าใจเกี่ยวกับการจัดประเภทและการถดถอยโลจิสติกส์

การจัดประเภทซึ่งเป็นงานการเรียนรู้ของเครื่องที่ได้รับความนิยมคือกระบวนการเรียงลําดับข้อมูลป้อนเข้าเป็นประเภท เป็นงานของอัลกอริทึมการจําแนกประเภทเพื่อหาวิธีกําหนด ป้ายชื่อ ให้กับข้อมูลป้อนเข้าที่คุณให้ ตัวอย่างเช่น คุณสามารถนึกภาพอัลกอริทึมการเรียนรู้ของเครื่องที่รับข้อมูลหุ้นเป็นข้อมูลป้อนเข้า และแบ่งหุ้นออกเป็นสองประเภท: หุ้นที่คุณควรขายและหุ้นที่คุณควรเก็บไว้

การถดถอย โลจิสติกเป็นอัลกอริทึมที่คุณสามารถใช้สําหรับการจัดประเภทได้ API การถดถอยโลจิสติกของ Spark มีประโยชน์สําหรับการ จําแนกประเภทไบนารี หรือจัดประเภทข้อมูลอินพุตลงในหนึ่งในสองกลุ่ม สําหรับข้อมูลเพิ่มเติมเกี่ยวกับการกระจายโลจิสติกส์ โปรดดูที่วิกิพีเดีย

โดยสรุป กระบวนการถดถอยโลจิสติกส์จะสร้าง ฟังก์ชัน ลอจิสติกส์ที่คุณสามารถใช้เพื่อคาดการณ์ความน่าจะเป็นที่เวกเตอร์ป้อนเข้าอยู่ในกลุ่มหนึ่งหรืออีกกลุ่มหนึ่ง

ตัวอย่างการวิเคราะห์เชิงทํานายเกี่ยวกับข้อมูลแท็กซี่ของ NYC

หากต้องการเริ่มต้นใช้งาน ให้ติดตั้งazureml-opendatasets ข้อมูลจะพร้อมใช้งานผ่าน ชุดข้อมูล Azure Open ชุดข้อมูลย่อยนี้ประกอบด้วยข้อมูลเกี่ยวกับทริปแท็กซี่สีเหลือง รวมถึงเวลาเริ่มต้นและสิ้นสุด และตําแหน่งที่ตั้ง ต้นทุน และแอตทริบิวต์อื่นๆ

%pip install azureml-opendatasets

ในส่วนที่เหลือของบทความนี้ เราจะใช้ Apache Spark เพื่อดําเนินการวิเคราะห์บางอย่างเกี่ยวกับข้อมูลคําแนะนําการเดินทางโดยแท็กซี่ของ NYC จากนั้นพัฒนาแบบจําลองเพื่อคาดการณ์ว่าการเดินทางเฉพาะนั้นมีเคล็ดลับหรือไม่

สร้างแบบจําลองการเรียนรู้ของเครื่อง Apache Spark

  1. สร้างสมุดบันทึก PySpark สําหรับคําแนะนํา ให้ดู สร้างสมุดบันทึก

  2. นําเข้าชนิดที่จําเป็นสําหรับสมุดบันทึกนี้

    import matplotlib.pyplot as plt
    from datetime import datetime
    from dateutil import parser
    from pyspark.sql.functions import unix_timestamp, date_format, col, when
    from pyspark.ml import Pipeline
    from pyspark.ml import PipelineModel
    from pyspark.ml.feature import RFormula
    from pyspark.ml.feature import OneHotEncoder, StringIndexer, VectorIndexer
    from pyspark.ml.classification import LogisticRegression
    from pyspark.mllib.evaluation import BinaryClassificationMetrics
    from pyspark.ml.evaluation import BinaryClassificationEvaluator
    
  3. เราจะใช้ MLflow เพื่อติดตามการทดลองการเรียนรู้ของเครื่องและการเรียกใช้ที่สอดคล้องกัน ถ้าเปิดใช้งานการล็อกอัตโนมัติของ Microsoft Fabric เมตริกและพารามิเตอร์ที่สอดคล้องกันจะถูกบันทึกโดยอัตโนมัติ

    import mlflow
    

สร้าง DataFrame อินพุต

ในตัวอย่างนี้ เราจะโหลดข้อมูลลงในกรอบข้อมูล Pandas แล้วแปลงเป็นกรอบข้อมูล Apache Spark เมื่อใช้รูปแบบนี้ เราสามารถใช้การดําเนินการ Apache Spark อื่น ๆ เพื่อทําความสะอาดและกรองชุดข้อมูลได้

  1. เรียกใช้บรรทัดต่อไปนี้เพื่อสร้าง Spark DataFrame โดยการวางรหัสลงในเซลล์ใหม่ ขั้นตอนนี้ดึงข้อมูลผ่าน API ชุดข้อมูลที่เปิด เราสามารถกรองข้อมูลนี้ลงเพื่อดูหน้าต่างเฉพาะของข้อมูลได้ ตัวอย่างรหัสต่อไปนี้ใช้ start_date และ end_date เพื่อใช้ตัวกรองที่ส่งกลับข้อมูลเดือนเดียว

    from azureml.opendatasets import NycTlcYellow
    
    end_date = parser.parse('2018-06-06')
    start_date = parser.parse('2018-05-01')
    nyc_tlc = NycTlcYellow(start_date=start_date, end_date=end_date)
    nyc_tlc_pd = nyc_tlc.to_pandas_dataframe()
    
    nyc_tlc_df = spark.createDataFrame(nyc_tlc_pd).repartition(20)
    
    
  2. รหัสต่อไปนี้จะลดชุดข้อมูลประมาณ 10,000 แถว เพื่อเพิ่มความเร็วของการพัฒนาและการฝึกอบรม เราจะสุ่มตัวอย่างชุดข้อมูลของเราลงในขณะนี้

    # To make development easier, faster, and less expensive, sample down for now
    sampled_taxi_df = nyc_tlc_df.sample(True, 0.001, seed=1234)
    
  3. ถัดไป เราต้องการดูข้อมูลของเราโดยใช้คําสั่งที่มีอยู่แล้วภายในdisplay() ซึ่งช่วยให้เราสามารถดูตัวอย่างของข้อมูลได้อย่างง่ายดายหรือสํารวจแนวโน้มในข้อมูลแบบกราฟิก

    #sampled_taxi_df.show(10)
    display(sampled_taxi_df.limit(10))    
    

เตรียมข้อมูล

การเตรียมข้อมูลเป็นขั้นตอนสําคัญในกระบวนการเรียนรู้ของเครื่อง ซึ่งเกี่ยวข้องกับการทําความสะอาด การแปลง และการจัดระเบียบข้อมูลดิบเพื่อให้เหมาะสําหรับการวิเคราะห์และการวางรูปแบบ ในโค้ดต่อไปนี้ คุณดําเนินการขั้นตอนการเตรียมข้อมูลหลายขั้นตอน:

  • ลบค่าผิดปกติและค่าที่ไม่ถูกต้องโดยการกรองชุดข้อมูล
  • ลบคอลัมน์ที่ไม่จําเป็นสําหรับการฝึกแบบจําลอง
  • สร้างคอลัมน์ใหม่จากข้อมูลดิบ
  • สร้างป้ายกํากับเพื่อดูว่าจะมีคําแนะนําหรือไม่สําหรับการเดินทางโดยแท็กซี่ที่กําหนด
taxi_df = sampled_taxi_df.select('totalAmount', 'fareAmount', 'tipAmount', 'paymentType', 'rateCodeId', 'passengerCount'\
                        , 'tripDistance', 'tpepPickupDateTime', 'tpepDropoffDateTime'\
                        , date_format('tpepPickupDateTime', 'hh').alias('pickupHour')\
                        , date_format('tpepPickupDateTime', 'EEEE').alias('weekdayString')\
                        , (unix_timestamp(col('tpepDropoffDateTime')) - unix_timestamp(col('tpepPickupDateTime'))).alias('tripTimeSecs')\
                        , (when(col('tipAmount') > 0, 1).otherwise(0)).alias('tipped')
                        )\
                .filter((sampled_taxi_df.passengerCount > 0) & (sampled_taxi_df.passengerCount < 8)\
                        & (sampled_taxi_df.tipAmount >= 0) & (sampled_taxi_df.tipAmount <= 25)\
                        & (sampled_taxi_df.fareAmount >= 1) & (sampled_taxi_df.fareAmount <= 250)\
                        & (sampled_taxi_df.tipAmount < sampled_taxi_df.fareAmount)\
                        & (sampled_taxi_df.tripDistance > 0) & (sampled_taxi_df.tripDistance <= 100)\
                        & (sampled_taxi_df.rateCodeId <= 5)
                        & (sampled_taxi_df.paymentType.isin({"1", "2"}))
                        )

จากนั้นเราจะส่งผ่านข้อมูลเป็นครั้งที่สองเพื่อเพิ่มคุณลักษณะสุดท้าย

taxi_featurised_df = taxi_df.select('totalAmount', 'fareAmount', 'tipAmount', 'paymentType', 'passengerCount'\
                                                , 'tripDistance', 'weekdayString', 'pickupHour','tripTimeSecs','tipped'\
                                                , when((taxi_df.pickupHour <= 6) | (taxi_df.pickupHour >= 20),"Night")\
                                                .when((taxi_df.pickupHour >= 7) & (taxi_df.pickupHour <= 10), "AMRush")\
                                                .when((taxi_df.pickupHour >= 11) & (taxi_df.pickupHour <= 15), "Afternoon")\
                                                .when((taxi_df.pickupHour >= 16) & (taxi_df.pickupHour <= 19), "PMRush")\
                                                .otherwise(0).alias('trafficTimeBins')
                                              )\
                                       .filter((taxi_df.tripTimeSecs >= 30) & (taxi_df.tripTimeSecs <= 7200))

สร้างแบบจําลองการถดถอยโลจิสติกส์

งานสุดท้ายคือการแปลงข้อมูลที่ติดป้ายชื่อเป็นรูปแบบที่สามารถวิเคราะห์ผ่านการถดถอยโลจิสติกส์ ข้อมูลป้อนเข้าไปยังอัลกอริทึมการถดถอยโลจิสติกส์ต้องเป็นชุดของ คู่ป้ายชื่อ/เวกเตอร์คุณลักษณะ ซึ่ง เวกเตอร์ คุณลักษณะคือเวกเตอร์ของตัวเลขที่แสดงจุดอินพุต

ดังนั้น คุณจําเป็นต้องแปลงคอลัมน์ตามประเภทเป็นตัวเลข โดยเฉพาะอย่างยิ่ง คุณจําเป็นต้องแปลง trafficTimeBins คอลัมน์ และ weekdayString เป็นการแสดงจํานวนเต็ม มีหลายวิธีในการดําเนินการแปลง ตัวอย่างต่อไปนี้ใช้ OneHotEncoder วิธีการ

# Because the sample uses an algorithm that works only with numeric features, convert them so they can be consumed
sI1 = StringIndexer(inputCol="trafficTimeBins", outputCol="trafficTimeBinsIndex")
en1 = OneHotEncoder(dropLast=False, inputCol="trafficTimeBinsIndex", outputCol="trafficTimeBinsVec")
sI2 = StringIndexer(inputCol="weekdayString", outputCol="weekdayIndex")
en2 = OneHotEncoder(dropLast=False, inputCol="weekdayIndex", outputCol="weekdayVec")

# Create a new DataFrame that has had the encodings applied
encoded_final_df = Pipeline(stages=[sI1, en1, sI2, en2]).fit(taxi_featurised_df).transform(taxi_featurised_df)

การดําเนินการนี้ส่งผลให้ DataFrame ใหม่มีคอลัมน์ทั้งหมดในรูปแบบที่ถูกต้องเพื่อฝึกแบบจําลอง

ฝึกแบบจําลองการถดถอยโลจิสติกส์

งานแรกคือการแยกชุดข้อมูลออกเป็นชุดการฝึกและการทดสอบหรือชุดการตรวจสอบ

# Decide on the split between training and test data from the DataFrame
trainingFraction = 0.7
testingFraction = (1-trainingFraction)
seed = 1234

# Split the DataFrame into test and training DataFrames
train_data_df, test_data_df = encoded_final_df.randomSplit([trainingFraction, testingFraction], seed=seed)

ตอนนี้มี DataFrames สองแบบ ในงานถัดไปคือการสร้างสูตรแบบจําลองและเรียกใช้กับ DataFrame สําหรับการฝึก จากนั้นคุณสามารถตรวจสอบกับ dataFrame ทดสอบได้ ทดลองใช้สูตรแบบจําลองเวอร์ชันต่างๆ เพื่อดูผลกระทบของชุดค่าผสมที่แตกต่างกัน

## Create a new logistic regression object for the model
logReg = LogisticRegression(maxIter=10, regParam=0.3, labelCol = 'tipped')

## The formula for the model
classFormula = RFormula(formula="tipped ~ pickupHour + weekdayVec + passengerCount + tripTimeSecs + tripDistance + fareAmount + paymentType+ trafficTimeBinsVec")

## Undertake training and create a logistic regression model
lrModel = Pipeline(stages=[classFormula, logReg]).fit(train_data_df)

## Predict tip 1/0 (yes/no) on the test dataset; evaluation using area under ROC
predictions = lrModel.transform(test_data_df)
predictionAndLabels = predictions.select("label","prediction").rdd
metrics = BinaryClassificationMetrics(predictionAndLabels)
print("Area under ROC = %s" % metrics.areaUnderROC)

ผลลัพธ์จากเซลล์นี้คือ:

Area under ROC = 0.9749430523917996

สร้างการแสดงภาพของการคาดการณ์

ตอนนี้คุณสามารถสร้างการแสดงภาพขั้นสุดท้ายเพื่อแปลผลลัพธ์แบบจําลองได้แล้ว เส้น โค้ง ROC เป็นวิธีหนึ่งในการตรวจสอบผลลัพธ์

## Plot the ROC curve; no need for pandas, because this uses the modelSummary object
modelSummary = lrModel.stages[-1].summary

plt.plot([0, 1], [0, 1], 'r--')
plt.plot(modelSummary.roc.select('FPR').collect(),
         modelSummary.roc.select('TPR').collect())
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.show()

Graph that shows the ROC curve for logistic regression in the tip model.