Tutorial

จัดการกับ Skew Data ด้วย Log Transform

By Arnon Puitrakul - 15 ตุลาคม 2021 - 2 min read min(s)

จัดการกับ Skew Data ด้วย Log Transform

ตอนที่เราเรียนสถิติ หรือบางคนอาจจะเรียนใน Data Science มา เราจะมีภาพที่เป็น Conceptual ในหัวว่า Data ที่ดีควรหน้าตาเป็นอย่างไร แต่ในโลกแห่งความเป็นจริง มันมักจะไม่เป็นแบบนั้น ยิ่งคนที่ทำงานกับ Data เยอะ ๆ น่าจะรู้ดีเลยว่า โลกเรามันโหดร้าย และ คนให้ Data เรามันก็เ_ยกว่านั้นเยอะมาก สิ่งที่เราได้มาทำงานมันไม่ได้สวยหรูเหมือนในหนังสือเรียนหรือในบทเรียนต่าง ๆ ที่เราเจอมา หนึ่งในปัญหาใหญ่ ๆ ที่เรามักจะได้เจอคือพวก Skew Data หรือพวกข้อมูลที่เมื่อเราเอามาวางเรียงกันแล้วดูการกระจายตัว มันจะไม่ได้เป็นไปตาม Normal Distribution แต่มันกลายเป็น Left ไม่ก็ Right Skew ดี ๆ หน่อยมันก็เลื่อนไปไม่เยอะ อาจจะไม่มีผลอะไร แต่ถ้ามัน Shift ไปเยอะนี่สิ เดือดร้อน ทำให้ในวันนี้เรามาดูกันว่า ถ้าเราเจอของพวกนี้ เราจะทำยังไงกับมันได้บ้าง

Central Tendencies

ก่อนที่เราจะไปคุยกันเรื่องว่า Data มัน Skew มากน้อย เราอยากจะพามารู้จักหนึ่งในเรื่องที่เราน่าจะได้เรียนกันในประถม หรือ มัธยม กันบ้างแล้ว นั่นคือเรื่องของ Central Tendencies หรือค่ากลางนั่นเอง

หลัก ๆ แล้ว การหาค่าตรงกลางของ Dataset เราทำได้หลายวิธีมาก ๆ เช่นวิธีที่เรารู้จักกันดีอย่างการหาค่าเฉลี่ย (Average), ค่ามัธยฐาน (Median) และ ฐานนิยม (Mode) การหาค่าพวกนี้น่าจะไม่ยากสำหรับเราแล้วละ

เมื่อก่อนตอนเราเรียนเรื่องพวกนี้ตอนประถม เราไม่เข้าใจเลยว่า มันหาค่าพวกนี้ไปทำไม มันมีอะไรสัมพันธ์กันด้วยเหรอ แต่จริง ๆ แล้วเราจะบอกว่า ค่าพวกนี้มันสัมพันธ์กัน มันบอกอะไรเราได้เยอะมาก ๆ แต่ตัวอย่างที่เข้ากับหัวข้อนี้คือ การ Skew ของข้อมูลผ่านทั้ง 3 ค่านี้

โดยปกติเอาเคสที่เป็น Ideal เราจะเห็นว่าข้อมูลจะอิงตาม Normal Distribution นั่นคือ Average = Median = Mode เป๊ะ ๆ แล้วถ้าข้อมูลมัน Skew ไป มันจะหน้าตาเป็นอย่างไร

เราลองดูกราฟที่มันเป็นลักษณะของการ Skew Left ก่อน ก็คือ ข้อมูลมันจะเทไปทางขวาซะเยอะ นั่นทำให้ Mode จะต้องเป็นค่าฝั่งขวา ๆ แน่ ๆ ในที่นี้ก็คือแท่งสุดท้ายเลย แล้ว Median ละ มันควรจะอยู่ตรงไหน แน่นอนว่า มันเกิดจากการที่เราเอาข้อมูลมาเรียงแล้วเลือกตรงกลาง ทำให้ มันก็ต้องอยู่ตรงกลางแน่ ๆ ซึ่งแน่นอนว่า น้อยกว่า Mode ชัวร์ และสุดท้าย Mean ละ ถ้าเราคิดง่าย ๆ เราบอกว่า Mean มันเป็นค่าที่เกิดจากเอา Data Point มาบวกกันหารด้วยจำนวนของ Data Point นั่นคือ จุดที่ค่าส่วนใหญ่มันอยู่ ซึ่งมันก็น่าจะอยู่น้อยกว่า Median แน่ ๆ ทำให้ ถ้าเราดู กราฟที่ Skew Left เราจะสังเกตุได้ว่า Mean < Median < Mode

กลับกัน ถ้าข้อมูลมัน Skew Right หรือก็คือ ข้อมูลมันเทไปทางซ้ายซะเยอะ ทำให้แน่นอนว่า Mode ไปซ้ายแน่ ๆ ในที่นี้ก็คือ ซ้ายสุดชัวร์ ๆ ส่งผลให้ Median ที่อยู่ตำแหน่งตรงกลางจริง ๆ ย่อมเยอะกว่า Mode แน่ ๆ และสุดท้าย Mean พื้นที่ส่วนใหญ่ยังไงก็มากกว่า Median แน่ ๆ ทำให้มันเลยกลายเป็น Mean > Median > Mode ตรงกันข้ามกับ Skew Left

ดังนั้นจะเห็นได้เลยว่า ค่า Central Tendencies อย่าง Mean, Median และ Mode นั้นมีความสัมพันธ์กัน เราสามารถใช้ค่าพวกนี้แหละ ในการประเมินการกระจายตัวของข้อมูลได้อย่างง่ายดายเลยทีเดียว นั่นทำให้เราจะต้องรู้จักค่าพวกนี้ไว้

Skewed Data ทำไมเราต้องสนใจมัน ?

โลกแห่งความจริงมันช่างแตกต่างจากโลกแห่งความฝันยิ่งนัก Data ก็เช่นกัน ดังนั้นข้อมูลที่เรามักจะได้มาส่วนใหญ่ ชอบ Skew กันหมดเลย แต่ถามว่า อ้าว แล้วไงละ มันทำไมกับเราละ

เราจะเห็นว่ามัน Skew Left มาก ๆ เลย ช่วงของ Mean มันเลยจะอยู่แถว ๆ ซ้ายมือซะเยอะมาก ๆ แต่ด้านขวามือ มันมีน้อยมาก ๆ ทำให้กลายเป็นว่า ข้อมูลที่อยู่ในด้านขวามือเป็น Outliner ไปซะงั้น นั่นทำให้เกิดปัญหาได้ เอ๊ะ แล้วปัญหาแบบไหนละ

เราขอยกตัวอย่างว่า ถ้าเกิดเราเอาข้อมูลที่มันมี Outliner หนัก ๆ แบบ Extreme เลย มาทำ Linear Regression เราจะเห็นได้เลยว่าระยะห่างระหว่าง Data Point ที่เป็น Outliner กับ เส้นที่ Linear Regression วางไว้ มันจะห่างกันมาก ๆ เลยทีเดียว

แน่นอนว่ามันไม่ได้ส่งผลกับแค่ Data Point ตัวที่เป็น Outliner เท่านั้น เราลองดูในรูปเปรียบเทียบกัน รูปนึงเราเอา Outliner ออก และ อีกรูปมันยังอยู่ เราจะเห็นได้ว่า ตัวที่มี Outliner ระยะห่างเฉลี่ย ระหว่าง Data Point แต่ละจุดกับเส้นที่ Linear Regression วาด มันจะมากกว่า ตัวที่เราเอา Outliner ออกไปแล้ว ถ้าคิดง่าย ๆ เวลาเราคำนวณเพื่อหา Linear Regression ให้เรานึกภาพว่าแต่ละ Data Point มันจะมีแรงดึง เพื่อให้เส้นมันผ่าน หรือเข้าหา ทุก Data Point ให้ได้มากที่สุด แล้วพอมาเจอ Outliner ที่มันมีแรงดึงมากกว่าชาวบ้านเขา เลยทำให้เส้นมันพยายามเบ้ไปหา Outliner มากขึ้น เลยทำให้ค่าเฉลี่ยระยะทางระหว่าง Data Point กับ Linear Regression (Mean Error) มันเพิ่มขึ้นนั่นเอง

จะเห็นได้เลยว่าข้อมูลที่มัน Skew หรือมี Outliner เยอะ ๆ มันสามารถทำให้ Statistics Model นึงแตกไปเลยก็ได้ ทำให้เรามีทางเลือกในการวิเคราะห์น้อยลง แต่ไม่ได้หายไปทั้งหมด เพราะวิธีพวกที่เป็น Tree-Based ก็ถือว่าทนทานต่อ Outliner ได้ดีกว่า ก็อาจจะเป็นตัวเลือกที่ดี แต่การมีตัวเลือกเยอะ ๆ ไม่ดีกว่าอ่อ เราลองมาดูกันว่า เราจะใช้วิธีไหนได้บ้างในการจัดการกับพวก Skewed Data

Log Transform

วิธีแรกที่เราน่าจะคิดขึ้นมาในหัวกันได้แบบเร็ว ๆ เลย คือการทำ Log Transform หรือก็คือการ Take Log ใส่เข้าไปใน Data Point ของเราไปเลย เราขอไม่เล่าลึกมากละกันว่าทำไม Log Transform ถึงแก้ปัญหาเรื่องของ Skewness ได้ แต่เพื่อให้เข้าใจง่ายขึ้น ลองดูด้านล่างนี้

Original Log Transformed
1 0
10 1
100 10
1000 100
10000 1000

จากตารางด้านบน เราทำ Log Base 10 Transform ให้ดูเป็นตัวอย่าง ในข้อมูลดั้งเดิมคือ Column แรก เราะจะเห็นได้เลยว่า ข้อมูลของเรามัน Vary ไปไกลมาก ๆ ตั้งแต่ 0 จนไปถึง 10,000 เลย นั่นแปลว่า ถ้าข้อมูลของเรามี Outliner อยู่สัก 10,000 แต่ Data ส่วนใหญ่เราอยู่ที่ 10 นั่นแปลว่า มันห่างกัน 9,990 เลยนะ ซึ่งถือว่าเยอะมาก ๆ พอเรา Plot ออกมาดู เราจะเห็นได้เลยว่า มันไกลมาก ๆ

แต่เมื่อเรา Log Transform ไป เราจะเห็นได้เลยว่า ระยะห่างระหว่าง 10 และ 10,000 ล่นลงมาเหลือแค่ 999 เท่านั้น จากเดิม 9,990 หรือถ้าเราลองเทียบอีกเคสอย่าง 100 กับ 1,000 จากเดิมห่างกัน 900 เมื่อเรา Take Log เข้าไปมันเหลือ 90 เท่านั้น ถ้าเราลองเทียบกันดูเราจะเห็นว่า การทำ Log Transform มันทำให้ระยะห่างมันสั้นลงมาก ๆ แต่มันก็ยังไม่ตอบคำถามว่าทำไมมันจะช่วยลดการ Skew ของ Data ได้

การจะตอบคำถามนี้ เราอยากให้ดู Graph ด้านบน เป็น Logarithmic Function โดยที่แกน X จะเป็นจำนวนตัวเลขปกติ และ แกน Y จะเป็นจำนวนหลังจากเรา Transform แล้ว เราจะเห็นว่า กราฟไม่ได้เรียงตัวเป็นแบบ Linear แต่ถ้าเราลองดูดี ๆ เราจะเห็นเลยว่า เมื่อค่ามันเยอะขึ้นเรื่อย ๆ ความชันมันจะน้อยลงเรื่อย ๆ นั่นแปลว่า ยิ่งค่ามันห่างมากขึ้นเรื่อย ๆ การเพิ่มขึ้นมันก็น้อยลง ทำให้ค่าที่อยู่ใกล้ ๆ มันไกลกันมากขึ้น นั่นทำให้เราสามารถ Transform ข้อมูลให้มันเกือบ ๆ หรือประมาณว่า Normal Distribution จาก Outliner ได้นั่นเอง

Python Implementation

import math

data_point = 20
transformed_data_point = math.log(data_point, 10)

สำหรับคนที่ใช้ Python ก็สามารถ Apply Log Transformation ได้ง่ายมาก ๆ โดยเราอาจจะใช้ log() ที่ติดมากับตัว Python เลยก็ได้ โดยเราจะต้อง Import Math Module เข้ามาก่อน และเรียกคำสั่ง log() เข้ามาใช้งานได้เลย ในนั้นเราก็จะใส่เป็น Data Point ของเรา และตามด้วย เราจะ Log ด้วยฐานอะไร ก็เรียบร้อย แล้วปัญหาของ log() ใน Python แบบนี้คือมันยุ่งยาก เพราะเวลาเราทำงานจริง เรามีหลาย Data Point มาก ๆ อาจจะเก็บเป็น List หรือ Numpy Array อะไรก็ว่ากันไป ทำให้เราจะต้องค่อย ๆ Loop เข้าไปทำทีละตัวเอง

import numpy as np

np.log(data_points)

แต่ถ้าเราใช้ Numpy เลย เราแค่ใส่ Data Point ที่อาจจะอยู่ในรูปแบบของ List หรือ Numpy Array ลงไปได้เลย โดยใน Function np.log() มันจะเป็น Natural Log หรือก็คือฐาน e นั่นเอง ถ้าเราอยากได้ฐานอะไรก็ได้ละ

import numpy as np

base = 20

np.log(data_points) / np.log(base)

เราก็ใช้สมบัติข้อนึงของ Log ได้ เพราะ log(50) ฐาน e เราสามารถเขียนเป็น log(50) หารด้วย log(e) แล้วเราก็หารกับ log(20) ฐาน e มันก็จะเขียนได้เป็น log(20) หารด้วย log(e) และเราก็เอาทั้ง 2 Expression มาหารกัน log(e) ก็จะตัดกัน เหลือเป็น log(50) หารด้วย log(20) หรือก็คือ log(50) ฐาน 20 นั่นเอง อันนี้สมบัติพื้นฐานปกติเลย แต่เราสามารถเอามาใช้ได้ สุดท้ายแล้วเราก็จะได้ Data Point ที่ผ่านการทำ Log Transformation เรียบร้อยนั่นเอง

สรุป

Log Transform เป็นวิธีหนึ่งในการแปลงข้อมูล (Data Transformation) ที่ช่วยทำให้ลดการ Skew ไปมาของข้อมูลให้อยู่ในรูปที่ใกล้เคียงกับ Normal Distribution ได้ เพราะข้อมูลที่มีการ Skew เกิดขึ้นส่งผลเป็นอย่างมากกับ Prediction Power ที่เราจะได้ เมื่อเราทำงานที่เป็น Machine Learning โดยเฉพาะ Regression ทั้งหลาย ในความเป็นจริงแล้ว มันยังมีอีกหลายวิธีมาก ๆ ในการทำ Data Transformation เพื่อลดการ Skew ของข้อมูลได้ เช่น Square-Root Transformation และ Box-Cox Transformation แต่วิธีอย่าง Log Transformation ที่เราเอามาเล่าในวันนี้น่าจะเป็นตัวที่ง่าย และใช้บ่อยที่สุดเลยเอามาเป็นตัวอย่างในวันนี้กัน