<jupyter_start><jupyter_text>[Loss Function](https://www.bualabs.com/archives/2673/what-is-loss-function-cost-function-error-function-loss-function-how-cost-function-work-machine-learning-ep-1/) หรือ Cost Function คือ การคำนวน Error ว่า yhat ที่โมเดลทำนายออกมา ต่างจาก y ของจริง อยู่เท่าไร แล้วหาค่าเฉลี่ย เพื่อที่จะนำมาหา Gradient ของ Loss ขึ้นกับ Weight ต่าง ๆ ด้วย Backpropagation แล้วใช้อัลกอริทึม Gradient Descent เพื่อให้ Loss น้อยลง ในการเทรนรอบถัดไปใน ep ก่อนเราได้สอน [Cross Entropy Loss](https://www.bualabs.com/archives/1945/what-is-cross-entropy-loss-logistic-regression-log-loss-loss-function-ep-3/) ไปแล้ว ในเคสนี้เราจะพูดถึง Loss Function สำหรับงาน [Regression](https://www.bualabs.com/archives/1136/train-deep-learning-model-deep-neural-networks-estimate-center-point-biwi-kinect-head-pose-regression-ep-1/) (ค่าต่อเนื่อง) กัน และ Regression Loss ที่เป็นที่นิยมมากที่สุด ได้แก่ MAE, MSE, RMSEyhat และ y สามารถเป็น Vector หรือ เลขตัวเดียวก็ได้  0. Import<jupyter_code>import torch
from torch import tensor
import matplotlib.pyplot as plt<jupyter_output><empty_output><jupyter_text>1. Data เราจะสร้างข้อมูลตัวอย่างขึ้นมา เป็นสมการเส้นตรง ให้ x เป็น เลขตั้งแต่ -50 ถึง 50 เราจะได้เอาไว้พล็อตกราฟ<jupyter_code>x = torch.arange(-50., 50.)
x<jupyter_output><empty_output><jupyter_text>ประกาศฟังก์ชันเส้นตรง f(x) = y = ax + b<jupyter_code>a = 4
b = 2

# a = -2
# b = 2

def f(x):
    return (a * x) + b<jupyter_output><empty_output><jupyter_text>yhat นำ x ผ่านฟังก์ชัน ได้ค่า yhat<jupyter_code>yhat = f(x)
yhat<jupyter_output><empty_output><jupyter_text>y ส่วนค่า y ที่เราต้องการจริง ๆ เป็นดังนี้<jupyter_code>y = tensor([102., 100.,  98.,  96.,  94.,  92.,  90.,  88.,  86.,  84.,  82.,  80.,
         78.,  76.,  74.,  72.,  70.,  68.,  66.,  64.,  62.,  60.,  58.,  56.,
         54.,  52.,  50.,  48.,  46.,  44.,  42.,  40.,  38.,  36.,  34.,  32.,
         30.,  28.,  26.,  24.,  22.,  20.,  18.,  16.,  14.,  12.,  10.,   8.,
          6.,   4.,   2.,   0.,  -2.,  -4.,  -6.,  -8., -10., -12., -14., -16.,
        -18., -20., -22., -24., -26., -28., -30., -32., -34., -36., -38., -40.,
        -42., -44., -46., -48., -50., -52., -54., -56., -58., -60., -62., -64.,
        -66., -68., -70., -72., -74., -76., -78., -80., -82., -84., -86., -88.,
        -90., -92., -94., -96.])
y<jupyter_output><empty_output><jupyter_text>เปรียบเทียบ y, yhat นำมาพล็อตกราฟ เปรียบเทียบกัน<jupyter_code>fig,ax = plt.subplots(figsize=(9, 9))
ax.scatter(x, y, label="y")
ax.plot(x.numpy(), yhat.numpy(), label="yhat", color='red')
ax.legend(loc='upper right')<jupyter_output><empty_output><jupyter_text>2. Mean Abolute Error (MAE) หรือ Least Absolute Deviations (L1 Loss) Mean Abolute Error (MAE) หรือ L1 Loss คือ การคำนวน Error ว่า yhat ต่างจาก y อยู่เท่าไร ด้วยการนำมาลบกันตรง ๆ แล้วหาค่าเฉลี่ย โดยไม่สนใจเครื่องหมาย (Absolute) เพื่อหาขนาดของ Error โดยไม่สนใจทิศทาง  2.1 สูตร MAE $$\mathrm{MAE} = \frac{\sum_{i=1}^n\left| y_i-\hat{y_i}\right|}{n}$$  2.2 โค้ด MAE Function<jupyter_code>def mae(y, yhat):
    return (y - yhat).abs().mean()<jupyter_output><empty_output><jupyter_text>2.3 การใช้งาน MAE<jupyter_code>error = mae(y, yhat)
error<jupyter_output><empty_output><jupyter_text>2.4 เปรียบเทียบ Loss แทนที่เราจะหาค่าเฉลี่ย เราจะลองเปรียบเทียบ yhat, y ตัวต่อตัว สังเกต กราฟสีม่วง ความชันจะคงที่ และจุดต่ำสุดจะอยู่ที่ y - yhat = 0 คือ โมเดลทำนาย yhat ออกมาเท่ากับ y พอดี ทำให้ MAE Loss = 0<jupyter_code>fig,ax = plt.subplots(figsize=(9, 9))
ax.scatter(x, y, label="y")
ax.plot(x.numpy(), yhat.numpy(), label="yhat", color='red')
ax.plot(x.numpy(), (y - yhat).abs().numpy(), label="MAE", color='purple')
ax.legend(loc='upper right')<jupyter_output><empty_output><jupyter_text>3. Mean Squared Error (MSE) หรือ Least Square Errors (L2 Loss) Mean Squared Error (MSE), Quadratic Loss หรือ L2 Loss คือ การคำนวน Error ว่า yhat ต่างจาก y อยู่เท่าไร ด้วยการนำมาลบกัน แล้วยกกำลังสอง (Squared) เพื่อไม่ต้องสนใจค่าติดลบ (ถ้ามี) แล้วหาค่าเฉลี่ยเนื่องจากมีการยกกำลังสอง ทำให้ค่อนข้าง Sensitive ถ้าข้อมูลไม่ดี มีบางตัวที่นอกลู่นอกทาง yhat ตัวไหนที่ผิดจาก y ไปมาก จะถูกให้ความสำคัญมากกว่า yhat ตัวอื่น ๆ จะมีผลทำให้ Loss สูง  3.1 สูตร MSE $$\operatorname{MSE}=\frac{1}{n}\sum_{i=1}^n(Y_i-\hat{Y_i})^2$$  3.2 โค้ด MSE Function<jupyter_code>def mse(y, yhat):
    return (y - yhat).pow(2).mean()<jupyter_output><empty_output><jupyter_text>3.3 การใช้งาน MSE<jupyter_code>error = mse(y, yhat)
error<jupyter_output><empty_output><jupyter_text>3.4 เปรียบเทียบ Loss แทนที่เราจะหาค่าเฉลี่ย เราจะลองเปรียบเทียบ yhat, y ตัวต่อตัว สังเกต กราฟสีม่วง ความชันจะขึ้นเร็วมาก เป็น Exponential เนื่องจาก MSE ยกกำลัง 2 และจุดต่ำสุดจะอยู่ที่ y - yhat = 0 คือ โมเดลทำนาย yhat ออกมาเท่ากับ y พอดี ทำให้ MSE Loss = 0<jupyter_code>fig,ax = plt.subplots(figsize=(9, 9))
ax.set_xlim([-50, 50])
ax.set_ylim([-200, 2000])
ax.scatter(x, y, label="y")
ax.plot(x.numpy(), yhat.numpy(), label="yhat", color='red')
ax.plot(x.numpy(), (y - yhat).pow(2).numpy(), label="MSE", color='purple')
ax.legend(loc='upper right')<jupyter_output><empty_output><jupyter_text>4. RMSE หรือ RMSD  4.1 สูตร RMSE $$\operatorname{RMSD}=\sqrt{\frac{\sum_{i=1}^n ( y_i - \hat y_i)^2}{n}}$$ Root Mean Squared Error (RMSE) หรือ Root Mean Squared Deviation (RMSD) คือ นำ MSE มาหา Squared Root ช่วยให้กลับมาเป็น Scale เดิม ทำให้ตีความได้ง่ายขึ้น  4.2 โค้ด RMSE Function<jupyter_code>def rmse(y, yhat):
    return ((y - yhat).pow(2).mean()).sqrt()<jupyter_output><empty_output><jupyter_text>4.3 การใช้งาน RMSE<jupyter_code>error = rmse(y, yhat)
error<jupyter_output><empty_output><jupyter_text>4.5 เปรียบเทียบ Loss<jupyter_code>fig,ax = plt.subplots(figsize=(9, 9))
ax.set_xlim([-50, 50])
ax.set_ylim([-200, 300])
ax.scatter(x, y, label="y")
ax.plot(x.numpy(), yhat.numpy(), label="yhat", color='red')
ax.plot(x.numpy(), (y - yhat).pow(2).sqrt().numpy(), label="RMSE", color='purple')
ax.legend(loc='upper right')<jupyter_output><empty_output><jupyter_text>5. เปรียบเทียบ MAE และ MSE 1. ค่า MSE, MAE อยู่ในช่วง 0 - Infinity เหมือนกัน ยิ่งน้อยคือยิ่งดี ถ้าเป็น 0 คือ ไม่ Error เลย1. MAE มี Slope คงที่ หมายถึง Gradient จากมีขนาดใหญ่เท่าเดิม แม้ Error จะน้อยแค่ไหนก็ตาม1. MSE มี Slope ที่เปลี่ยนแปลงไปตาม Error ถ้า Error มาก Gradient ก็มาก ถ้า Error น้อย Gradient ก็จะน้อยตามไปด้วย ช่วยให้เทรนโมเดล Fine-Tune ได้ดีกว่า1. เนื่องจาก MSE ยกกำลังสอง ก่อนที่จะหาค่าเฉลี่ย ทำให้ Sensitive กับข้อมูลแตกแถว มากกว่า MAE ถ้า MSE เจอข้อมูลไม่ดี จะทำให้ Loss มีขนาดใหญ่มาก1. เราสามารถแก้ปัญหา Gradient คงที่ของ MAE ได้ด้วยเทคนิค Dynamic Learning Rate1. ถ้าข้อมูลตัวอย่างของเรามี ข้อมูลเสีย ๆ ปะปนอยู่ MAE จะเหมาะกว่า MSE1. MAE ใช้การ Absolute ทำให้อาจจะทำให้มีปัญหาได้ กับการคำนวนทางคณิตศาสตร์อื่น ๆ  6. Loss Function อื่น ๆ สำหรับงาน Regression นอกจาก MAE, MSE และ RMSE แล้ว มีตัวอื่น ๆ ที่เป็นที่นิยมอีก เช่น Huber Loss (Smooth Mean Absolute Error), Log-Cosh Loss, Quantile Loss เราจะอธิบายต่อไป<jupyter_code><jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.19862813776999416, 'fraction_numerical': 0.04495037945125511, 'mean_word_length': 5.04320987654321, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 65, 'https://': 3, 'lorem ipsum': 0, 'www.': 3, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '16', 'dir': 'jupyter-structured-clean-dedup', 'id': '36988', 'license': 'MIT', 'n_tokens_mistral': 4250, 'n_tokens_neox': 4273, 'n_words': 617, 'path': 'nbs/17a-loss-function-mae-rmse.ipynb', 'repo_name': 'gnoparus/bualabs', 'size': '6852'}