Automated Model Training and Deployment, Episode I

ในการทำงานการทำงานองค์กร การทำงานโปรเจค และการบรรยายที่เกี่ยวข้องกับ Big Data และ Data Science มักพบเจอ Requirements ด้านการปรับปรุง Machine Learning Model ให้สดใหม่ตามข้อมูลที่เรานำมา Train โดยอัตโนมัติ (Automated Model Refresh) โดยคาดหวังว่าจะทำให้งาน Predictive Analytics มีประสิทธิภาพมากขึ้น

เป็นโอกาสดีที่ปัจจุบันนี้ การทำ Large-Scale Machine Learning นั้น ใน Hadoop Ecosystem มีซอฟต์แวร์/เซอร์วิสให้เลือกใช้ตามวงจรชีวิตของข้อมูล ตั้งแต่การนำเข้าข้อมูล (Ingestion) อย่างเช่น Sqoop มาถึงการจัดเก็บข้อมูลลง Filesystem (Storage) เช่น HDFS แล้วเรียกข้อมูลขึ้นมาทำ Data Preparation, Feature Engineering และ Model Training ด้วย Apache Spark เมื่อได้รับ ML Models แล้วก็นำไปจัดเก็บลง Disk แล้วจึงนำไปทำ Model Deployment ต่อไปด้วย Web Framework และ REST APIs อย่างเช่น Python Flask ครบถ้วนทุกขั้นตอนได้ตั้งแต่ต้นจนจบบน Hadoop Platform. แต่ทว่าขั้นตอน end-to-end ตั้งแต่นำเข้าข้อมูล จนกระทั่งได้รับ Web UI สำหรับทำ Predictive Analytics นั้นโดยส่วนใหญ่พบว่ายังคงเป็น Manual Process ที่ซับซ้อนและยุ่งยาก. งานเขียนนี้มุ่งนำเสนอกระบวนการที่เป็นอัตโนมัติตั้งแต่การนำเข้าข้อมูลจนกระทั่งได้รับ Machine Learning Model จนถึง Model Deployment ที่ผู้ใช้สามารถสอบถามโมเดลผ่านทาง UI ในลักษณะ Prediction Services. เนื้อหาของงานเขียนแบ่งเป็น 2 ตอน ตอนที่ 1 (Episode 1) เป็นการแนะนำขั้นตอนการใช้ Apache Oozie สำหรับ Seamless Services เหล่านั้นให้เป็น Workflow ที่ส่งต่อการทำงานกันโดยอัตโนมัติและตั้งเวลาการทำงานของ Workflow (Scheduling) ได้ ส่วนตอนที่ 2 ซึ่งยกไว้ในฉบับหน้า เป็นการปรับแต่ง Services ต่างๆ ใน Workflow รวมถึงรายละเอียดการทำ Model Deployment ทั้งในมุมมอง Software Engineer และ Machine Learning Engineer

Apache Oozie เป็นซอฟต์แวร์ที่เป็น Workflow Engine สำหรับ Activate การทำงานของ Services และ run Jobs ต่างๆ ใน Hadoop Ecosystem อีกทั้งยังสามารถแจ้งเตือนผลการ Run Jobs ผ่านทางช่องทางต่างๆ เช่น email, Java Message Service (JMS) ได้เป็นต้น. ในการติดตั้ง Hadoop ไม่ว่าจะเป็น Apache Hadoop, Cloudera Hadoop และ Hortonworks Hadoop ต่างมี Apache Oozie มาให้เลือกติดตั้งได้โดย Default และภายหลังจากการติดตั้ง เราสามารถสั่งงาน Oozie ได้ผ่านทาง Command-line Interface และตรวจสอบสถานะของ Workflows ได้ผ่านทาง Oozie’s Web UI.

Workflow ที่ถูกสร้างด้วย Oozie โดยส่วนใหญ่แล้วประกอบด้วยไฟล์ 3 ไฟล์ คือ job.properties, workflow.xml และ coordinator.xml

ไฟล์ชื่อ job.properties ใช้ระบุ arguments ต่างๆ ที่จำเป็นต่อการทำงานของ Workflow เช่น host address ของ NameNode ที่เกือบทุก Services ใน Hadoop อื่นๆ จำเป็นต้องใช้ในการ Read/Write ข้อมูลลง HDFS เป็นต้น นอกจากนี้ job.properties ยังใช้ตั้งเวลาการทำงานของ Workflow อีกด้วย (Scheduling Workflow) ส่วนอีกไฟล์หนึ่งคือ workflow.xml ใช้ระบุ Logic ในการตัดสินใจเพื่อให้ Oozie ส่งต่องานการทำงานจาก Services สู่ Services อื่นๆ เช่น เมื่อ Sqoop ดึงข้อมูลจาก RDBMS มาวางไว้ใน HDFS ได้ครบถ้วนแล้วก็ให้ Oozie ไป run Job ของ Spark ML เพื่อสร้าง ML Models แต่ในทางตรงกันข้าม หาก Sqoop ไม่สามารถวางข้อมูลได้ครบถ้วน หรือเกิดความผิดพลาดในการทำงาน ก็ไม่ต้องไป run Job แต่ให้ส่ง email แจ้งเตือน Admin ต่อไป เป็นต้น สุดท้ายไฟล์ชื่อ coordinator.xml เราใช้ไฟล์นี้เชื่อมต่อการทำงานระหว่าง Workflows ได้

รูปที่ 1 แสดง Technology Architecture Framework สำหรับทำ Automated Model Training and Deployment

สภาพแวดล้อมของระบบคอมพิวเตอร์ที่ใช้ในงานเขียนนี้ประกอบด้วย:

รูปที่ 2 แสดง Hostname ใน Hadoop Cluster

(a) VM จำนวน 4 VMs บน Google Cloud Platform แต่ละเครื่องมี Spec.: 4 vCPUs, RAM 15 GB, HD 100 GB, OS: CentOS 7 โดยทุก VMs เป็น Node ใน Hortonworks Hadoop Cluster (HDP version 3.1.1) เรียบร้อยแล้ว และมีรายละเอียดทางเทคนิคอื่นๆ [ตามรูปที่ 1 สีเหลือง] ดังนี้

  • Apache Ambari version 2.7.1.0 มี Ambari Server ทำงานอยู่ที่ hw4 และ Ambari Client ทำงานอยู่ทุก Node ใน Cluster
  • มี Client Program อย่างเช่น hdfs, sqoop, oozie และอื่นๆ อยู่ใน hw4
  • ใช้ Command Shell (Terminal) ของ VM ชื่อ hw4 ภายใต้ Privilege ของ User: hdfs ในทุกขั้นตอนของงานเขียนนี้

(b) VM จำนวน 1 VM บน Google Cloud Platform มี Spec. เช่นเดียวกับข้อ (a) โดยมีการทำงานของ Python Flask เรียบร้อยแล้ว ซึ่งเราจะใช้ run Prediction Service ที่ใช้โดยนักการตลาด [รูปที่ 1 สีฟ้า]

( c) Pyspark Code สำหรับ run เป็น Job ของ Spark เพื่อทำ Data Cleansing, Data Transformation, Feature Engineering, Model Training [ตามรูปที่ 1 สีเหลือง]

(1) ตรวจสอบความพร้อมการใช้งาน Oozie

[root@hw4 ~]# su — hdfs
Last login: Thu Jan 14 03:41:11 UTC 2021 on pts/0
[hdfs@hw4 ~]$ oozie version
Oozie client build version: 4.3.1.3.0.1.0–187

(2) สร้างไฟล์ job.properties และไฟล์ workflow.xml เพื่อกำหนดค่าการทำงานของ Workflow

(2.1) job.properties

[hdfs@hw4 ~]$ mkdir -p funnelWorkflow[hdfs@hw4 ~]$ cd funnelWorkflow[hdfs@hw4 funnelWorkflow]$ nano job.properties

อธิบาย argument ที่สำคัญของ job.properties

บรรทัดที่ 1, 2, 3, 4 มีการกำหนด argument ต่างๆ เป็น hw1.c.all-ih.internal ซึ่งเป็น hostname ของ Job Tracker (YARN), MapReduce, NameNode (HDFS) ตามลำดับ

บรรทัดที่ 5, 6 มีการกำหนด argument เพื่อให้ Oozie ใช้ทั้ง Default Library และ Customized Library Path

บรรทัดที่ 8 มีการกำหนด argument เป็น queueName=daily ซึ่งเป็นการกำหนด Queue ใน Job Scheduler ของ YARN โดยให้ Jobs ที่ run ใน Workflow ทั้งหมดใช้ Resource และถูกบริหารจัดการภายในขอบเขตของ Queue ชื่อ daily

บรรทัดที่ 15 เป็นการกำหนด argument เป็น master=yarn-cluster ซึ่งเป็นการกำหนดให้ Spark ทำงานใน mode, “yarn-cluster”

บรรทัดที่ 10–13 เป็นการกำหนด argument ต่างๆ ที่กำหนดช่วงวันเวลาเริ่มต้นและสิ้นสุดการทำงานของ Workflow ตลอดจนความถี่ในการทำงานตามช่วงวันเวลาดังกล่าว ซึ่งในที่นี้กำหนดให้ Workflow ทำงานทุก 150 นาที

(2.2) workflow.xml

[hdfs@hw4 funnelWorkflow]$ nano workflow.xml

Copy workflow.xml ไปวางไว้ที่ HDFS


[hdfs@hw4 funnelWorkflow]$ hdfs dfs -mkdir -p /user/refinedzone/
[hdfs@hw4 funnelWorkflow]$ hdfs dfs -put -f workflow.xml /user/refinedzone/

อธิบายค่าการทำงานที่สำคัญของ workflow.properties

ค่าการทำงานของ Sqoop

บรรทัดที่ 4–27 เป็นการกำหนดค่าการทำงานของ Sqoop Import เพื่อ Import ข้อมูลจาก MySQL Server จาก Table ชื่อ mysql_funnel ที่อยู่ใน Database ชื่อ funnel_db โดยให้วางข้อมูลที่ import มาไว้ใน HDFS ที่ path: /user/rawzone/funnel-sqoop-toHDFS

บรรทัดที่ 28–29 เป็นการระบุเงื่อนไขในการส่งต่องานจาก Sqoop โดยกำหนดว่า หาก Sqoop ทำงานสำเร็จให้ส่งต่องานให้ Hive แต่หากไม่สำเร็จให้หยุดการทำงานของ Workflow ทันที พร้อม return Message Errors

ค่าการทำงานของ Hive

จากหลักนิยมโดยทั่วไปก่อนที่จะนำข้อมูลไปพัฒนาเป็น Feature เพื่อเข้าสู่กระบวนการ Train Model นั้น มักจะมีการสำรวจคุณภาพข้อมูลอย่างเช่น การทำ EDA เป็นเบื้องต้น (Exploratory Data Analysis) ด้วยเหตุนี้ เราสามารถนำข้อมูลดิบจาก /user/rawzone/funnel-sqoop-toHDFS มาผลิตเป็น Summary Report ที่สะท้อนให้เห็นคุณภาพของข้อมูล และใช้เป็นปัจจัยหนึ่งในการพิจารณาความน่าเชื่อถือของ Machine Learning Model ได้ต่อไป Hive เป็น Service หนึ่งของ Hadoop ที่ใช้ประมวลผลข้อมูลเชิงสรุป ในงานเขียนนี้จึงการกำหนดค่าการทำงานของ Hive ลงไปใน Workflow ด้วย

บรรทัดที่ 32–44 เป็นการกำหนดให้ Hive สร้าง Summary Report และเนื่องจากความสำเร็จของการสร้าง Summary Report ไม่ได้กระทบต่อกระบวนการผลิต Machine Learning Model บรรทัดที่ 45–46 จึงกำหนดให้ส่งต่อการทำงานให้ Spark ทุกกรณีไม่ว่าจะสร้าง Report สำเร็จหรือไม่ก็ตาม

ค่าการทำงานของ Spark

บรรทัดที่ 50–64 เป็นการกำหนดให้ Spark ทำ Job Submission โดย run ไฟล์ชื่อ deploy.py ซึ่งเป็นการอ่านข้อมูลจาก /user/rawzone/funnel-sqoop-toHDFS มาสร้าง Machine Learning Model

(3) ปรับปรุง Libraries ของ Oozie ที่ใช้สำหรับ activate Services/Jobs ต่างๆ ใน Workflow

Oozie มี Libraries Path เป็นของตัวเองอยู่ใน HDFS ด้วยเหตุนี้เมื่อเรานำ Oozie ไป Activate การทำงานของ Services หรือ run Jobs ต่างๆ ตามที่กำหนดไว้ใน Workflow จึงต้องมีการ copy Library Files ที่เกี่ยวข้องมาวางไว้ใน Oozie’s Libraries Path ด้วย อย่างไรก็ตามในงานเขียนนี้เราจะสร้าง Customized Lib. Path ขึ้นมาใหม่ แล้วนำ Library Files ทั้งหมดที่เกี่ยวข้อง มาวางไว้ที่นี่

(3.1) ตรวจสอบ Default Path สำหรับ Oozie’s Libraries

[hdfs@hw4 funnelWorkflow]$ hdfs dfs -ls /user/oozie/share/lib/
Found 1 items
drwxr-xr-x - oozie hdfs 0 2020-12-30 03:04 /user/oozie/share/lib/lib_20201230030349

(3.2) สร้าง Customized Lib. Path ที่ HDFS แล้ว Copy .jar files และไฟล์อื่นๆ ที่จำเป็นต่อการทำงานของ Services/Jobs ต่างๆ ใน Workflow ลงไปใน Customized Lib. Path

[hdfs@hw4 funnelWorkflow]$ hdfs dfs -mkdir -p /user/oozielib/

Copy .jar file สำหรับทำ Sqoop Import จาก MySQL เข้าสู่ Customized Lib. Path

[hdfs@hw4 funnelWorkflow]$ hdfs dfs -put -f /usr/share/java/mysql-connector-java.jar /user/oozielib/

Copy .jar files และ Library Files อื่นๆ สำหรับ run Job ของ Spark เข้าสู่ Customized Lib. Path

[hdfs@hw4 funnelWorkflow]$ hdfs dfs -cp -f  /user/oozie/share/lib/lib_20201230030349/spark/oozie-sharelib-spark-* /user/oozielib/[hdfs@hw4 funnelWorkflow]$ hdfs dfs -rm /user/oozielib/hive*[hdfs@hw4 funnelWorkflow]$ hdfs dfs -put -f /usr/hdp/current/spark2-client/jars/* /user/oozielib/

ข้อสังเกตคือ มีการลบทุกไฟล์ที่ขึ้นต้นด้วย hive ทิ้งไปจาก /user/oozielib/ เนื่องจากไฟล์ดังกล่าว conflict ไฟล์ที่ขึ้นต้นด้วย hive ใน Default Library Path (/user/oozie/share/lib/lib_20201230030349)

(3.3) สร้างไฟล์ hiveCreateTable.sql แล้วนำไปวางไว้ใน Customized Lib. Path

[hdfs@hw4 funnelWorkflow]$ nano hiveCreateTable.sql
[hdfs@hw4 funnelWorkflow]$ hdfs dfs -put -f hiveCreateTable.sql /user/refinedzone/

(4) สร้างไฟล์ coordinator.xml เพื่อเชื่อมต่อการทำงานระหว่าง Workflows แม้ว่าในงานเขียนนี้มีเพียง Workflow เดียว แต่เพื่อรองรับ Workflows ที่เพิ่มมากขึ้นในอนาคตจึงควรต้องมีไฟล์นี้ไว้

(4.1) สร้างไฟล์ coordinator.xml

[hdfs@hw4 funnelWorkflow]$ nano coordinator.xml

(4.2) นำไฟล์ coordinator.xml ไปวางไว้ใน HDFS

[hdfs@hw4 funnelWorkflow]$ hdfs dfs -put -f coordinator.xml /user/refinedzone/

(5) วาง deploy.py ไว้ที่ HDFS แล้วจึง run Oozie เพื่อให้ทำงานตามตารางเวลาและ Workflow

(5.1) สร้างไฟล์ deploy.py ที่ใช้ทำ Data Cleansing, Data Transformation, Feature Engineering และ Model Training

[hdfs@hw4 funnelWorkflow]$ nano deploy.py

อธิบายโค้ดที่สำคัญของ deploy.py

deploy.py เป็น Pyspark Code ที่ใช้สร้าง Machine Learning Model โดยนำไป run ด้วย Spark

บรรทัดที่ 1–20 เป็นการกำหนดสภาพแวดล้อมในการ Execution ของ Spark และให้ Spark อ่านข้อมูลจาก /user/rawzone/funnel-sqoop-toHDFS มาเป็น DataFrame จากนั้นนำ DataFrame มาคัดเลือกเอาเฉพาะ Attribute ที่สนใจในบรรทัดที่ 21–38

บรรทัดที่ 39–264 เป็นกระบวนการทำ Data Cleansing และ Data Transformation กับ DataFrame เช่น การจัดการค่า Null, การยุบรวมหลายๆ record ด้วย groupby, การทำ Data Enhancement สร้าง Atrributes ใหม่ๆ ขึ้นมาจาก Attributes เดิม ทั้งนี้ก็เพื่อผลิต DataFrame ที่บรรจุข้อมูลที่มีคุณภาพเหมาะแก่การนำไปทำ Machine Learning

บรรทัดที่ 265–363 เป็นการกระบวนการสร้าง Machine Learning Model ที่ประกอบด้วยการทำ Feature Engineering และการทำ Machine Learning ผลลัพธ์คือ Machine Learning Model ที่ถูกจัดเก็บไว้ใน path: /user/refinedzone/model

(5.2) นำ deploy.py ไปวางไว้ที่ HDFS

[hdfs@hw4 funnelWorkflow]$ hdfs dfs -put -f deploy.py /user/refinedzone/

(5.3) Run coordinator.xml และ workflow.xml ด้วย Oozie Client Program

[hdfs@hw4 funnelWorkflow]$ oozie job — oozie http://hw1:11000/oozie -config job.properties -run

(6) ตรวจสอบการทำงานของ Workflow และ ผลลัพธ์ Machine Learning Model

(6.1) ตรวจสอบการทำงานของ Workflow

รูปที่ 3 แสดงหน้าจอ Web UI ของ Oozie

(6.2) ตรวจสอบผลลัพธ์ Machine Learning Model

[hdfs@hw4 funnelWorkflow]$ hdfs dfs -ls /user/refinedzone/model
Found 2 items
drwxr-xr-x — hdfs hdfs 0 2021–01–14 07:08 /user/refinedzone/model/metadata
drwxr-xr-x — hdfs hdfs 0 2021–01–14 07:08 /user/refinedzone/model/stages

ณ จุดนี้ เมื่อข้อมูลใน MySQL มีการเปลี่ยนแปลง Machine Learning Model ก็ควรจะเปลี่ยนแปลงไปตามข้อมูลด้วยตามวงรอบการทำงานของ Workflow ดังนั้นเราควรจะเห็น Machine Learning Model ใหม่ๆ จากการ Train ในทุกๆ 150 นาที

งานเขียนนี้มุ่งนำเสนอการวิธีใช้ Apache Oozie เพื่อสร้าง Workflow เชื่อมการทำงานของ Sqoop, HDFS, Hive, Spark โดยที่แต่ละ Service ส่งต่อผลลัพธ์ซึ่งกันและกันอย่างอัตโนมัติ ผลลัพธ์สุดท้ายคือ Machine Learning Model ที่ถูกบันทึกอยู่ในดิสก์ซึ่งเป็นก้าวแรกของการทำ Model Deployment ในตอนต่อไป (Episode II) ผมจะขยายงานเขียนนี้ด้วยกล่าวถึง Prediction Service และนำเสนอแนวทางการสร้าง Web UI การทำ Model Query ด้วย REST API และ Python Flask บน Scalable Environments

Experienced Senior Big Data & Data Science Consultant with a history of working in many enterprises and various domains . Skilled in Apache Spark, and Hadoop.

Experienced Senior Big Data & Data Science Consultant with a history of working in many enterprises and various domains . Skilled in Apache Spark, and Hadoop.