All possible combinations with conditions in python
Recursive function backtracking
การทำ Forward-looking model สำหรับ IFRS 9 ด้วย Multiple linear regression ขั้นตอน Features selection ด้วย Univariate analysis หรือ Multivariate analysis ด้วยวิธีใด ๆ ก็ตาม สิ่งที่ได้เป็นผลลัพธ์คือตัวแปรจำนวนหนึ่ง ที่สามารถนำไปใช้พัฒนาเป็นโมเดลต่อ แต่จำนวนตัวแปรที่ผ่าน Features selection อาจมีจำนวนมากเกินไป เกินกว่าที่ควรจะเป็นใน 1 โมเดล
ดังนั้นวิธีการที่นิยมใช้สำหรับ IFRS 9 คือแทนที่การรันด้วยตัวแปรทั้งหมด ซึ่งอาจทำให้เกิดความยุ่งยากในการแปลผล หรือ Model maintenance การจัด Combinations ก็เป็นอีกทางเลือกที่ดีมาก เพราะสามารถกำหนดได้ว่าต้องการให้ Model มีจำนวน Independence variables กี่ตัว
Simple combinations
ก่อนไปถึงการจัด Combinations ด้วยเงื่อนไขตามที่ต้องการ อยากให้ดูการใช้ Library itertools สำหรับการทำ Combinations ตามจำนวนที่ต้องการ ขอใช้เป็น Mock-up dataset เพื่อแสดงให้เห็นตัวอย่างการทำงานของ Library
List ข้อมูลประกอบด้วย 4 Lists ย่อยภายในซึ่งประกอบไปด้วย
- สมาชิกตัวที่ 1 คือ Variable ที่ต้องการจัด Combinations
- สมาชิกตัวที่ 2 คือ Cluster ที่ Variable นั้น ๆ อยู่จัดให้อยู่
- สมาชิกตัวที่ 3 คือ ฟอร์มเดิมของ Variable ก่อน Transformation
สนใจเฉพาะสมาชิกตัวที่ 1 จากแต่ละ List เพราะยังไม่ต้องการใส่เงื่อนไขใด ๆ เข้าไปใน Combinations
['GDP_M3', 'HPI_M3_lg2', 'HPI_M6', 'Export_M9']
ใช้ itertools.combinations()
ผ่านเป็น List ของ Variables และกำหนดให้สมาชิกใน Combinations มีเท่ากับ 2
('GDP_M3', 'HPI_M3_lg2')
('GDP_M3', 'HPI_M6')
('GDP_M3', 'Export_M9')
('HPI_M3_lg2', 'HPI_M6')
('HPI_M3_lg2', 'Export_M9')
('HPI_M6', 'Export_M9')
ผลลัพธ์ที่มีทั้งหมด 6 Combinations สามารถคิดได้จาก 4c2 โดยที่ 4 คือจำนวนของสมาชิกทั้งหมดที่มีโอกาสโดยเลือก และ 2 คือจำนวนในการเลือกแต่ละครั้ง ตัวอย่างเช่น GDP_M3
มีโอกาสจับคู่กับทั้ง 3 คือ HPI_M3_lg2, HPI_M6
และ Export_M9
ต่อมา HPI_M3_lg2
มีโอกาสจับคู่เหลือ 2 คือ HPI_M6
และ Export_M9
สุดท้าย HPI_M6
มีโอกาสจับคู่กับ Export_M9
เท่านั้น
หากสังเกตดูจะเห็นได้ว่าการทำ Combinations แบบนี้ยังไม่สมเหตุสมผลเท่าไหร่ เช่น (‘GDP_M3’, ‘HPI_M3_lg2’)
เป็น Combinations ที่เกิดจากสมาชิกที่มาจาก Cluster เดียวกัน หรือ (‘HPI_M3_lg2’, ‘HPI_M6’)
แม้ว่ามาจากคนละ Cluster แต่ HPI ยังคงเป็นตัวแปรเดียวกับที่อยู่ในฟอร์มที่ต่างกันเท่านั้น
ปัญหานี้อาจส่งผลให้เกิด Multicollinearity ขึ้นใน Combination นั้น ๆ หรือหากใช้งานจริง อาจทำให้โมเดลอธิบายผลได้ยาก ดังนั้นการจัด Combinations ด้วยเงื่อนไขจึงเป็นทางเลือกที่น่าสนใจ
Combinations with conditions
เมื่อรู้ว่ามีสิ่งที่ไม่ต้องการเกิดขึ้นจาก Combinations ดังนั้นจึงสามารถสร้างเป็นเงื่อนไขได้คือ ไม่ให้สมาชิกใน Combination มาจาก Cluster เดียวกัน และไม่ให้สมาชิกใน Combination นั้น ๆ มาจากตัวแปรประเภทเดียวกัน
ยกตัวอย่างให้เห็นภาพมากขึ้นกว่าเดิม ถ้าใช้ข้อมูล Mock-up เดิมที่มีอยู่ผลลัพธ์ที่ได้จากเงื่อนไขนี้คือ
GDP_M3
สามารถจับคู่ได้กับHPI_M6
และExport_M9
เพราะทั้งสองมาจากคนละ Cluster และไม่ใช่ตัวแปรประเภทเดียวกันHPI_M3_lg2
สามารถจับคู่ได้กับExport_M9
เท่านั้น เพราะทั้งสองมาจากคนละ Cluster และไม่ใช่ตัวแปรประเภทเดียวกัน ส่วนHPI_M6
ไม่สามารถจับคู่ได้ แม้ว่าอยู่คนละ Cluster กัน เพราะเป็นตัวแปรประเภทเดียวกัน และGDP_M3
ไม่สามารถจับคู่ได้ เพราะอยู่ใน Cluster เดียวกัน แม้ว่าเป็นตัวแปรคนละประเภท
Recursive function backtracking
Backtracking เป็น Algorithm ในการเขียนโปรแกรมชนิดนึง โดยมีหลักการทำงานแบบ Recursively ที่พยายามแก้ไขปัญหาและลบคำตอบที่ไม่ต้องการออกจากผลลัพธ์ หลักการ Backtracking จึงถูกนำมาใช้ในการพัฒนาการสร้าง Combinations ด้วยเงื่อนไขที่ได้อธิบายไว้ก่อนหน้านี้
เขียนเป็น Recursive function หรือฟังก์ชั่นที่เรียกใช้งานตัวเอง ไปจนกว่าจะถึงเงื่อนไขให้หยุด โดยมีการจัด Combinations แบบ 1–1 และเก็บตัวแปร เช่น clusterTracker
หรือ subGroupTracker
เพื่อเช็คเงื่อนไขการ .add()
หรือ .remove()
ตัวแปรที่ไม่ต้องการออกจาก Combination นั้น ๆ
โดยการทำงานทั้งหมดของ Function สามารถแสดงเป็นภาพคร่าว ๆ ได้ตามด้านล่าง
Process นี้จะวนไปเรื่อย ๆ จนเกิดจะเข้าเงื่อนไขหยุด และ Return ผลลัพธ์ที่เป็น Combinations ตามเงื่อนไขที่สร้างเอาไว้
ลองใช้ข้อมูลเดิม จัดเป็น 2 Combinations เพื่อทดสอบ Apply function
['HPI_M3_lg2', 'Export_M9']
['GDP_M3', 'Export_M9']
['GDP_M3', 'HPI_M6']
จากเดิมที่คำตอบเกิดจาก 4c2 มีค่าเท่ากับ 6 Combinations แต่เมื่อผ่าน Backtracking ผลลัพธ์จึงเหลือเพียง 3 Combinations ตามเงื่อนไขที่ต้องการ
With real dataset
ใช้ Dataset ที่ผ่านการจัด Cluster ด้วย PROC VARCLUS
จากโปรแกรม SAS แต่สามารถรันได้ด้วย Python เช่นกัน
สร้างเป็น List of lists ที่เก็บตัวแปรที่จำเป็นต่อการสร้างเงื่อนไขไว้คือ Variable, cluster และ Root form ของ Variable นั้น ๆ
[['GDP_C_lg12', 1, 'GDP'],
['MPI_C_lg12', 1, 'MPI'],
['RSI_C_lg12', 1, 'RSI'],
['PCI_C_lg12', 1, 'PCI'],
['CPI_M9_lg6', 2, 'CPI']]
จัดเป็น Combinations ที่มีสมาชิกมากที่สุดเท่ากับ 3 ด้วย Recursive function backtracking
[['GDP_C_lg12', 'CPI_M9_lg6', 'PII_M12_lg10'], ['GDP_C_lg12', 'CPI_M9_lg6', 'OP_C'], ['GDP_C_lg12', 'CPI_M9_lg6', 'PII_M12_lg11']]
สร้างเป็น DataFrame และ Plot ผลลัพธ์ของการจัด Combinations ด้วย Conditions ต่างที่อธิบายมาตามเนื้อหาของ Blog ตอนนี้
Conclusion
สุดท้ายแล้วเนื้อหาของ Blog ตอนนี้คือการนำเอา Recursive function backtracking ที่เป็น Algorithm ชนิดหนึ่งในการเขียนโปรแกรม มาประยุกต์ใช้งานในการพัฒนาโมเดลของ IFRS 9 เพื่อให้เกิดความสมเหตุสมผลมากขึ้น และสามารถช่วยในการอธิบายในเชิงของการใช้งานได้มากกว่าเดิม
สำหรับ Colab notebok ของเนื้อหา Blog ตอนนี้ สามารถดูได้ที่ GitHub ด้านบน