โครงงานประจำภาค วิชา Social Network Analysis
จุดประสงค์เพื่อหาพฤติกรรมคล้ายคลึงกันสำหรับผู้เรียนผ่าน MOOCs (Massive Open Online Courses) เพื่อวิเคราะห์ว่าผู้เรียนคนดังกล่าวอยู่ในกลุ่มที่มีแนวโน้มว่าจะยุติการเรียนกลางคัน (Dropout) ก่อนที่จะศึกษาเนื้อหาครบตามโครงสร้างหลักสูตรหรือไม่
สิ่งที่ต้องการ
- ชุดข้อมูล (Dataset): เป็นชุดข้อมูลผู้เรียน ซึ่งเป็นชุดข้อมูลที่เก็บจากการใช้งานจริงของ MOOCs จัดเก็บโดยมหาวิทยาลัย Stanford
- Neo4J Desktop: ใช้ Ne04j Community ได้ โดยเวอร์ชันขณะศึกษาอยู่ที่เวอร์ชัน 1.4.4 โดยต้องการส่วนขยาย (Plugin) 2 รายการด้วยกัน โดยติดตั้งหลังจากสร้างฐานข้อมูล
- APOC คือชุดคำสั่งเพิ่มเติมเพื่อวิเคราะห์ข้อมูล
- Graph Data Science Library คือ เครื่องเมือสำหรับใช้คำสั่งประมวลผลทางด้าน Data Science ได้ (ติดตั้งได้หลังจากที่สั่งเริ่มต้นการทำงานของเซิร์ฟเวอร์ หากเวอร์ชันต่ำกว่า 1.4.4 สามารถติดตั้งได้ทันที่หลังจากสร้างฐานข้อมูลเสร็จ)
วิธีการติดตั้ง
-
สร้างฐานข้อมูล: โดยสร้างแบบ Local DBMS หลังจากนั้นให้แก้ไขค่า
Settings
2 ค่าดังนี้dbms.memory.heap.initial_size
: ให้เปลี่ยนจากค่าเดิมเป็น2G
dbms.memory.heap.max_size
: เปลี่ยนค่าความจำ (Memory) ที่จะใช้งานให้เพิ่มมากขึ้น แนะนำที่4G
แต่ไม่ควรกำหนดค่าให้มากกว่าจำนวนที่มีในเครื่อง
-
จัดเตรียมชุดข้อมูล: ให้แตกไฟล์
sna-moock.dataset.7z
(dataset/sna-mooc.dataset.7z
) (dataset
) จะได้ไฟล์นามสกุลcsv
เกิดขึ้นมาภายในโฟลเดอร์ที่จัดเตรียมไว้- ใน Neo4j ให้เลือกปุ่ม 3 จุด ด้านขวาสุดของมุ่ม
Open
ในฐานข้อมูลที่ต้องการจัดเตรียมข้อมูล แล้วเลือกที่เมนูOpen folder > Import
- นำไฟล์
csv
ที่เตรียมไว้ก่อนหน้านี้ทั้งหมดมาใส่ไว้ภายในโฟลเดอร์ที่import
- ใน Neo4j ให้เลือกปุ่ม 3 จุด ด้านขวาสุดของมุ่ม
-
สร้างกราฟ: ในขั้นตอนนี้จะแบ่งเป็นส่วนย่อยๆ ดังนี้
- กำหนดเงื่อนไข (Constrain) ในการสร้างโหนด เพื่อป้องกันไม่ให้
id
ของโหนดต่างๆ ซ้ำกันCREATE CONSTRAINT unique_course_id ON (c:Course) ASSERT c.course_id IS UNIQUE; CREATE CONSTRAINT unique_learner_id ON (l:Learner) ASSERT l.learner_id IS UNIQUE; CREATE CONSTRAINT unique_enrollment_id ON (e:Enrollment) ASSERT e.enrollment_id IS UNIQUE; CREATE CONSTRAINT unique_course_module_id ON (m:Module) ASSERT m.module_id IS UNIQUE; CREATE CONSTRAINT unique_module_object_id ON (o:ModuleObject) ASSERT o.object_id IS UNIQUE;
- สร้างโหนดของหลักสูตร (
Course
) โดยอ่านจากไฟล์course_date.csv
LOAD CSV WITH HEADERS FROM "file:///course_date.csv" AS row WITH row, DATE(row.`from`) AS date_from, DATE(row.`to`) AS date_to CREATE (c:Course {course_id: row.`course_id`, open_from: date_from, close_at: date_to});
- สร้างโหนดการลงทะเบียน (
Enrollment
) ด้วยข้อมูลจากไฟล์course_enrollment.csv
เพื่อใช้จัดเก็บพฤติกรรมการลงทะเบียนแต่ละวิชาของผู้เรียนLOAD CSV WITH HEADERS FROM "file:///course_enrollment.csv" AS row WITH row MATCH (c:Course {course_id: row.`course_id`}) MERGE (e:Enrollment {enrollment_id: row.`enrollment_id`}) MERGE (l:Learner {learner_id: row.`username`}) CREATE (l)-[:PERFORMED]->(e)-[:ENROLL]->(c);
- ใส่ป้ายกำกับ (property) ให้กับโหนดการลงทะเบียน เพื่อใช้แบ่งแยกว่าการลงทะเบียนใดบ้างเป็นการลงทะเบียนที่ผู้เรียนมีพฤติกรรมยุติการเรียนกลางคัน
LOAD CSV FROM "file:///enrollment_labelled.csv" AS row WITH row MATCH (e:Enrollment {enrollment_id: row[0]}) SET e.learning_status = CASE row[1] WHEN "1" THEN "dropout" ELSE "learn" END;
- เพิ่มโหนดส่วนประกอบหลักสูตร (
Module
และModuleObject
) ซึ่งเป็นเนื้อหาที่อยู่ในหลักสูตร เพื่อช่วยให้ผู้สอนใช้แบ่งแยกเนื้อหาในหลักสูตรนั้นให้เป็นสัดส่วนLOAD CSV WITH HEADERS FROM "file:///course_module_objects.csv" AS row WITH row, SPLIT(TRIM(row.`children`), " ") AS children MATCH (c:Course {course_id: row.`course_id`}) MERGE (m:Module {module_id: row.`module_id`, category: row.`category`, start_date: row.`start`}) CREATE (c)-[:HAS]->(m) WITH m, children UNWIND children AS k MERGE (o:ModuleObject {object_id: k}) CREATE (m)-[:CONTAIN]->(o);
- เพิ่มความสัมพันธ์ของผู้เรียนและเนื้อหาในบทเรียน แบ่งออกเป็น 2 ส่วนด้วยกัน นั่นคือ (
:Enrollment
)--(:Event
)--(:Module
) และ (:Enrollment
)--(:Event
)--(:ModuleObject
)
:auto USING PERIODIC COMMIT LOAD CSV WITH HEADERS FROM "file:///course_object_participation.csv" AS row WITH row, DATETIME(row.`time`) AS ts MATCH (o:ModuleObject {object_id: row.`object`}) MATCH (e:Enrollment {enrollment_id: row.`enrollment_id`}) CREATE ( ev:Event { action: row.`event`, timestamp: ts, source: row.`source` } ) CREATE (e)-[:ACTION]->(ev)-[:PARTICIPATE]->(o);
และ
:auto USING PERIODIC COMMIT LOAD CSV WITH HEADERS FROM "file:///course_object_participation.csv" AS row WITH row, DATETIME(row.`time`) AS ts MATCH (m:Module {module_id: row.`object`}) MATCH (e:Enrollment {enrollment_id: row.`enrollment_id`}) CREATE ( ev:Event { action: row.`event`, timestamp: ts, source: row.`source` } ) CREATE (e)-[:ACTION]->(ev)-[:PARTICIPATE]->(m);
จะเห็นได้ว่าคำสั่งทั้ง 2 นี้เพิ่มคำสั่ง
:auto USING PERIODIC COMMIT
ไว้ที่บันทัดแรก เนื่องจากจำนวนโหนดที่สร้างขึ้นด้วยขั้นตอนนี้จากทั้ง 2 คำสั่งมีจำนวนมาก ดังนั้น เพื่อให้โปรแกรมบันทึกโหนดที่สร้างขึ้นเป็นระยะๆ ทำให้เครื่องที่มีหน่วยความจำตามที่แนะนำสามารถประมวลผลคำสั่งนี้ได้ หากไม่ใส่จำเป็นจะต้องปรับค่าdbms.memory.heap.max_size=12G
เพื่อใช้หน่วยความจำขนาด 12GB เพื่อทำงาน - กำหนดเงื่อนไข (Constrain) ในการสร้างโหนด เพื่อป้องกันไม่ให้
-
คำสั่งสรุปข้อมูลเบื้องต้น
- สรุปจำนวนโหนดโดยแบ่งตามป้ายกำกับ
ตัวอย่างผลลัพธ์
MATCH (n) RETURN DISTINCT count(labels(n)) AS node_count, labels(n)[0] AS node_name;
node_count node_name 39 Course 72 Enrollment 53,870 Learner - จำนวนการลงทะเบียนที่ผู้เรียนที่ยุติการเรียนกลางคัน
ตัวอย่างผลลัพธ์
MATCH (:Enrollment {learning_status: "dropout"}) RETURN COUNT(e) AS total_dropout;
total_dropout 72,395 - หลักสูตรที่ผู้มีผู้เรียนยุติการเรียนกลางคันไปมากที่สุด พร้อมทั้งจำนวน โดนเรียงจากมากที่สุดไปน้อยที่สุด เฉพาะ 10 อันดับแรก
ตัวอย่างผลลัพธ์
MATCH (:Enrollment {learning_status: "dropout"})--(e:Event)--()-[:PART_OF]-(c:Course) RETURN c.course_id AS course_id, count(e) AS number_of_event ORDER BY number_of_event DESC;
course_id number_of_event DPnLzkJJqOOPRJfBxIHbQEERiYHu5ila 87,653 I7Go4XwWgpjRJM8EZGEnBpkfSmBNOlsO 86,161 shM3Yy9vxHn2aqjSYfQXOcwGo0hWh3MI 65,276 - โครงสร้างของหลักสูตร ซึ่งในที่นี้จะดึงโครงสร้างเนื้อหาของหลักสูตรที่มีผู้เรียนยุติการเรียนกลางคันออกมา ดังข้อมูลที่แสดงในตารางก่อนหน้า
ตัวอย่างผลลัพธ์
MATCH (c:Course {course_id: "DPnLzkJJqOOPRJfBxIHbQEERiYHu5ila"})-[:PART_OF]-(n)-[:PART_OF]-(m) WHERE labels(n)[0] IN ["Module", "ModuleObject"] OR labels(m)[0] = "ModuleObject" RETURN c, m, n
<ไม่มีตัวอย่างข้อมูล เนื่องจากเป็นกราฟ>
- สรุปจำนวนโหนดโดยแบ่งตามป้ายกำกับ
รายงานฉบับเต็ม
ในการศึกษาวิจัยครั้งนี้ได้จัดทำรายงานการวิจัยเพื่อบันทึกการดำเนินงานไว้ สามารถเข้าถึงได้ได้ที่ ไฟล์ sna-learner-behavior.pdf (pdf, LaTeX ในโฟลเดอร์ docs/report