|
|
# สร้างโมเดลการถดถอยโดยใช้ Scikit-learn: การถดถอยสี่วิธี
|
|
|
|
|
|
## หมายเหตุสำหรับผู้เริ่มต้น
|
|
|
|
|
|
การถดถอยเชิงเส้นถูกใช้เมื่อเราต้องการทำนาย **ค่าตัวเลข** (เช่น ราคาบ้าน อุณหภูมิ หรือยอดขาย)
|
|
|
มันทำงานโดยการหาค่าเส้นตรงที่เป็นตัวแทนความสัมพันธ์ระหว่างคุณลักษณะป้อนเข้าและผลลัพธ์
|
|
|
|
|
|
ในบทเรียนนี้ เราจะมุ่งเน้นที่การเข้าใจแนวคิดก่อนที่จะสำรวจเทคนิคการถดถอยขั้นสูงเพิ่มเติม
|
|
|

|
|
|
> อินโฟกราฟิกโดย [Dasani Madipalli](https://twitter.com/dasani_decoded)
|
|
|
## [แบบทดสอบก่อนเรียน](https://ff-quizzes.netlify.app/en/ml/)
|
|
|
|
|
|
> ### [บทเรียนนี้มีในภาษา R!](../../../../2-Regression/3-Linear/solution/R/lesson_3.html)
|
|
|
### บทนำ
|
|
|
|
|
|
จนถึงตอนนี้คุณได้สำรวจความหมายของการถดถอยด้วยข้อมูลตัวอย่างที่รวบรวมมาจากชุดข้อมูลราคาฟักทองที่เราจะใช้ตลอดบทเรียนนี้แล้ว คุณยังได้ทำการสร้างภาพด้วย Matplotlib
|
|
|
|
|
|
ตอนนี้คุณพร้อมที่จะเจาะลึกการถดถอยสำหรับ ML แล้ว ในขณะที่การสร้างภาพช่วยให้คุณเข้าใจข้อมูลได้ แต่พลังที่แท้จริงของการเรียนรู้ของเครื่องมาจากการ _ฝึกโมเดล_ โมเดลถูกฝึกด้วยข้อมูลในอดีตเพื่อจับความสัมพันธ์ของข้อมูลโดยอัตโนมัติ และช่วยให้คุณทำนายผลลัพธ์สำหรับข้อมูลใหม่ที่โมเดลไม่เคยเห็นมาก่อน
|
|
|
|
|
|
ในบทเรียนนี้ คุณจะได้เรียนรู้เพิ่มเติมเกี่ยวกับการถดถอยสองประเภท: _การถดถอยเชิงเส้นพื้นฐาน_ และ _การถดถอยพหุนาม_ พร้อมกับคณิตศาสตร์เบื้องหลังเทคนิคเหล่านี้ โมเดลเหล่านี้จะช่วยให้เราทำนายราคาฟักทองขึ้นอยู่กับข้อมูลนำเข้าที่แตกต่างกัน
|
|
|
|
|
|
[](https://youtu.be/CRxFT8oTDMg "ML for beginners - Understanding Linear Regression")
|
|
|
|
|
|
> 🎥 คลิกที่ภาพด้านบนเพื่อดูวิดีโอสั้นเกี่ยวกับการถดถอยเชิงเส้น
|
|
|
|
|
|
> ตลอดหลักสูตรนี้ เราสมมติว่ามีความรู้คณิตศาสตร์ขั้นต่ำ และพยายามทำให้เรียนรู้ได้ง่ายสำหรับนักเรียนจากสาขาอื่น ดังนั้นดูบันทึก 🧮 คำอธิบายภาพ แผนภาพ และเครื่องมือช่วยเรียนรู้อื่นๆ เพื่อช่วยในการเข้าใจ
|
|
|
|
|
|
### ข้อกำหนดเบื้องต้น
|
|
|
|
|
|
คุณน่าจะคุ้นเคยกับโครงสร้างข้อมูลฟักทองที่เรากำลังตรวจสอบแล้ว คุณสามารถพบข้อมูลที่เตรียมไว้ล่วงหน้าและทำความสะอาดไว้ในไฟล์ _notebook.ipynb_ ของบทเรียนนี้ ในไฟล์จะแสดงราคาฟักทองต่อบัชเชลในกรอบข้อมูลใหม่ ตรวจสอบให้แน่ใจว่าคุณสามารถรันโน้ตบุ๊กเหล่านี้ในเคอร์เนลของ Visual Studio Code ได้
|
|
|
|
|
|
### การเตรียมตัว
|
|
|
|
|
|
เพื่อเตือนความจำ คุณกำลังโหลดข้อมูลนี้เพื่อที่จะตั้งคำถามเกี่ยวกับมัน
|
|
|
|
|
|
- เวลาไหนที่ดีที่สุดในการซื้อฟักทอง?
|
|
|
- ฉันคาดหวังราคาของกล่องฟักทองขนาดเล็กได้เท่าไหร่?
|
|
|
- ควรซื้อฟักทองในตะกร้าครึ่งบัชเชลหรือในกล่อง 1 1/9 บัชเชล?
|
|
|
ลองขุดลึกลงไปในข้อมูลนี้กันต่อ
|
|
|
|
|
|
ในบทเรียนที่แล้ว คุณได้สร้างกรอบข้อมูล Pandas และเติมข้อมูลบางส่วนจากชุดข้อมูลต้นฉบับ โดยปรับราคาต่อบัชเชล แต่ด้วยวิธีนี้ คุณได้รวบรวมข้อมูลเพียงประมาณ 400 จุดข้อมูลและเฉพาะในเดือนฤดูใบไม้ร่วงเท่านั้น
|
|
|
|
|
|
ดูข้อมูลที่เราโหลดไว้ล่วงหน้าในโน้ตบุ๊กที่แนบมากับบทเรียนนี้ ข้อมูลนี้ถูกโหลดไว้ล่วงหน้าและสร้างแผนภูมิแบบกระจาย (scatterplot) แรกเพื่อนำเสนอข้อมูลเดือน อาจจะได้รับรายละเอียดมากขึ้นเกี่ยวกับลักษณะของข้อมูลโดยการทำความสะอาดเพิ่มเติม
|
|
|
|
|
|
## เส้นการถดถอยเชิงเส้น
|
|
|
|
|
|
อย่างที่คุณได้เรียนในบทเรียนที่ 1 เป้าหมายของการฝึกการถดถอยเชิงเส้นคือสามารถวาดเส้นเพื่อ:
|
|
|
|
|
|
- **แสดงความสัมพันธ์ของตัวแปร** แสดงความสัมพันธ์ระหว่างตัวแปร
|
|
|
- **ทำนายผลลัพธ์** ทำนายตำแหน่งของจุดข้อมูลใหม่ที่สัมพันธ์กับเส้นนั้นได้อย่างแม่นยำ
|
|
|
|
|
|
โดยปกติสำหรับ **Least-Squares Regression** จะใช้วาดเส้นในลักษณะนี้ คำว่า “Least-Squares” หมายถึงกระบวนการลดข้อผิดพลาดรวมในโมเดลของเราให้ต่ำสุด สำหรับแต่ละจุดข้อมูล เราจะวัดระยะห่างในแนวดิ่ง (เรียกว่า residual) ระหว่างจุดจริงกับเส้นถดถอยของเรา
|
|
|
|
|
|
เรานำค่าระยะเหล่านี้มาทำกำลังสองด้วยสองเหตุผลหลัก:
|
|
|
|
|
|
1. **ขนาดไม่สนใจทิศทาง:** เราต้องการให้ข้อผิดพลาด -5 และ +5 มีน้ำหนักเท่ากัน การทำกำลังสองทำให้ค่าทั้งหมดเป็นบวก
|
|
|
|
|
|
2. **ลงโทษจุดแปลกปลอม:** การทำกำลังสองให้น้ำหนักมากกว่ากับข้อผิดพลาดที่ใหญ่กว่า จึงบังคับให้เส้นอยู่ใกล้กับจุดที่อยู่ห่างไกลมาก
|
|
|
|
|
|
จากนั้นเราจะนำค่ากำลังสองทั้งหมดมารวมกัน เป้าหมายของเราคือหาค่าเส้นที่ทำให้ผลรวมต่ำที่สุด (ค่าต่ำสุด) — ซึ่งทำให้ได้ชื่อว่า "Least-Squares"
|
|
|
|
|
|
> **🧮 แสดงคณิตศาสตร์**
|
|
|
>
|
|
|
> เส้นนี้เรียกว่า _เส้นที่พอดีที่สุด_ สามารถแสดงเป็น [สมการ](https://en.wikipedia.org/wiki/Simple_linear_regression):
|
|
|
>
|
|
|
> ```
|
|
|
> Y = a + bX
|
|
|
> ```
|
|
|
>
|
|
|
> `X` คือ 'ตัวแปรอธิบาย' และ `Y` คือ 'ตัวแปรตาม' ความชันของเส้นคือ `b` และ `a` คือจุดตัดแกนนอน แสดงถึงค่าของ `Y` เมื่อ `X = 0`
|
|
|
>
|
|
|
>
|
|
|
>
|
|
|
> เริ่มต้นด้วยการคำนวณความชัน `b` อินโฟกราฟิกโดย [Jen Looper](https://twitter.com/jenlooper)
|
|
|
>
|
|
|
> ในอีกทางหนึ่ง และอ้างอิงคำถามต้นฉบับของข้อมูลฟักทองของเรา: "ทำนายราคาฟักทองต่อบัชเชลตามเดือน" `X` จะหมายถึงราคา และ `Y` จะหมายถึงเดือนที่ขาย
|
|
|
>
|
|
|
>
|
|
|
>
|
|
|
> คำนวณค่าของ Y ถ้าคุณจ่ายประมาณ 4 ดอลลาร์ ต้องเป็นเดือนเมษายนแน่ๆ อินโฟกราฟิกโดย [Jen Looper](https://twitter.com/jenlooper)
|
|
|
>
|
|
|
> คณิตศาสตร์ที่ใช้คำนวณเส้นต้องแสดงความชันของเส้น ซึ่งขึ้นอยู่กับจุดตัดหรือที่ที่ `Y` อยู่เมื่อ `X = 0`
|
|
|
>
|
|
|
> คุณสามารถศึกษาวิธีการคำนวณค่าสำหรับค่าต่างๆ เหล่านี้ได้ที่เว็บไซต์ [Math is Fun](https://www.mathsisfun.com/data/least-squares-regression.html) และเยี่ยมชม [เครื่องคิดเลข Least-squares](https://www.mathsisfun.com/data/least-squares-calculator.html) เพื่อดูว่าค่าตัวเลขต่างๆ ส่งผลต่อเส้นอย่างไร
|
|
|
|
|
|
## ความสัมพันธ์
|
|
|
|
|
|
อีกคำหนึ่งที่ต้องเข้าใจคือ **สัมประสิทธิ์สหสัมพันธ์** ระหว่างตัวแปร X และ Y ที่กำหนด โดยใช้ scatterplot คุณสามารถเห็นสัมประสิทธิ์นี้ได้อย่างรวดเร็ว กราฟที่มีจุดกระจายเรียงเป็นเส้นตรงจะมีความสัมพันธ์สูง แต่กราฟที่จุดกระจายกระจัดกระจายไปทั่วระหว่าง X และ Y จะมีความสัมพันธ์ต่ำ
|
|
|
|
|
|
โมเดลการถดถอยเชิงเส้นที่ดีจะต้องมีสัมประสิทธิ์สหสัมพันธ์สูง (ใกล้ 1 มากกว่า 0) โดยใช้วิธี Least-Squares Regression กับเส้นถดถอย
|
|
|
|
|
|
✅ รันโน้ตบุ๊กที่แนบมากับบทเรียนนี้และดูกราฟกระจายข้อมูลระหว่างเดือนกับราคา ข้อมูลที่เชื่อมโยงเดือนกับราคาขายในฟักทองดูเหมือนจะมีความสัมพันธ์สูงหรือต่ำ ตามการตีความด้วยสายตาของคุณจากแผนภูมิการกระจาย? นั่นจะเปลี่ยนไปไหมถ้าคุณใช้มาตรวัดที่ละเอียดขึ้นแทน `เดือน` เช่น *วันของปี* (จำนวนวันตั้งแต่ต้นปี)?
|
|
|
|
|
|
ในโค้ดด้านล่างนี้ เราจะสมมติว่าเราได้ทำความสะอาดข้อมูลแล้ว และได้กรอบข้อมูลชื่อ `new_pumpkins` ที่คล้ายกับต่อไปนี้:
|
|
|
|
|
|
ID | Month | DayOfYear | Variety | City | Package | Low Price | High Price | Price
|
|
|
---|-------|-----------|---------|------|---------|-----------|------------|-------
|
|
|
70 | 9 | 267 | PIE TYPE | BALTIMORE | 1 1/9 bushel cartons | 15.0 | 15.0 | 13.636364
|
|
|
71 | 9 | 267 | PIE TYPE | BALTIMORE | 1 1/9 bushel cartons | 18.0 | 18.0 | 16.363636
|
|
|
72 | 10 | 274 | PIE TYPE | BALTIMORE | 1 1/9 bushel cartons | 18.0 | 18.0 | 16.363636
|
|
|
73 | 10 | 274 | PIE TYPE | BALTIMORE | 1 1/9 bushel cartons | 17.0 | 17.0 | 15.454545
|
|
|
74 | 10 | 281 | PIE TYPE | BALTIMORE | 1 1/9 bushel cartons | 15.0 | 15.0 | 13.636364
|
|
|
|
|
|
> โค้ดสำหรับทำความสะอาดข้อมูลมีให้ใน [`notebook.ipynb`](notebook.ipynb) เราได้ทำขั้นตอนการทำความสะอาดเหมือนในบทเรียนก่อน และคำนวณคอลัมน์ `DayOfYear` ด้วยนิพจน์ดังนี้:
|
|
|
|
|
|
```python
|
|
|
day_of_year = pd.to_datetime(pumpkins['Date']).apply(lambda dt: (dt-datetime(dt.year,1,1)).days)
|
|
|
```
|
|
|
|
|
|
เมื่อคุณเข้าใจคณิตศาสตร์เบื้องหลังการถดถอยเชิงเส้นแล้ว ให้เราสร้างโมเดลการถดถอยเพื่อดูว่าเราสามารถทำนายได้หรือไม่ว่าฟักทองแบบแพ็คเกจใดจะมีราคาดีที่สุด ใครบางคนที่ซื้อฟักทองสำหรับงานฟักทองอาจต้องการข้อมูลนี้เพื่อเพิ่มประสิทธิภาพในการซื้อแพ็คเกจฟักทองสำหรับงานนั้น
|
|
|
|
|
|
## การค้นหาความสัมพันธ์
|
|
|
|
|
|
[](https://youtu.be/uoRq-lW2eQo "ML for beginners - Looking for Correlation: The Key to Linear Regression")
|
|
|
|
|
|
> 🎥 คลิกที่ภาพด้านบนเพื่อดูวิดีโอสั้นเกี่ยวกับความสัมพันธ์
|
|
|
|
|
|
จากบทเรียนก่อน คุณน่าจะเห็นว่าราคากลางในแต่ละเดือนดูเหมือนจะเป็นแบบนี้:
|
|
|
|
|
|
<img alt="Average price by month" src="../../../../translated_images/th/barchart.a833ea9194346d76.webp" width="50%"/>
|
|
|
|
|
|
ซึ่งบ่งชี้ว่าควรมีความสัมพันธ์บางอย่าง และเราสามารถลองฝึกโมเดลการถดถอยเชิงเส้นเพื่อทำนายความสัมพันธ์ระหว่าง `Month` กับ `Price` หรือระหว่าง `DayOfYear` กับ `Price` นี่คือกราฟกระจายที่แสดงความสัมพันธ์หลัง:
|
|
|
|
|
|
<img alt="Scatter plot of Price vs. Day of Year" src="../../../../translated_images/th/scatter-dayofyear.bc171c189c9fd553.webp" width="50%" />
|
|
|
|
|
|
มาลองดูว่ามีความสัมพันธ์ไหมโดยใช้ฟังก์ชัน `corr`:
|
|
|
|
|
|
```python
|
|
|
print(new_pumpkins['Month'].corr(new_pumpkins['Price']))
|
|
|
print(new_pumpkins['DayOfYear'].corr(new_pumpkins['Price']))
|
|
|
```
|
|
|
|
|
|
ดูเหมือนว่าค่าความสัมพันธ์จะต่ำเล็กน้อย คือ -0.15 ตาม `Month` และ -0.17 ตาม `DayOfMonth` แต่ดูเหมือนจะมีความสัมพันธ์ที่สำคัญอีกอย่าง เพราะดูเหมือนว่าจะมีกลุ่มราคาต่างๆ ที่สอดคล้องกับพันธุ์ฟักทองต่างกัน เพื่อยืนยันสมมติฐานนี้ มาสร้างกราฟโดยแบ่งพันธุ์ฟักทองแต่ละชนิดด้วยสีต่างกัน โดยการส่งพารามิเตอร์ `ax` ให้ฟังก์ชัน `scatter` เพื่อลากจุดทั้งหมดในกราฟเดียวกัน:
|
|
|
|
|
|
```python
|
|
|
ax=None
|
|
|
colors = ['red','blue','green','yellow']
|
|
|
for i,var in enumerate(new_pumpkins['Variety'].unique()):
|
|
|
df = new_pumpkins[new_pumpkins['Variety']==var]
|
|
|
ax = df.plot.scatter('DayOfYear','Price',ax=ax,c=colors[i],label=var)
|
|
|
```
|
|
|
|
|
|
<img alt="Scatter plot of Price vs. Day of Year" src="../../../../translated_images/th/scatter-dayofyear-color.65790faefbb9d54f.webp" width="50%" />
|
|
|
|
|
|
การสืบค้นของเราชี้ว่าพันธุ์มีผลต่อราคามากกว่าวันที่ขายจริง เราสามารถเห็นได้ชัดในกราฟแท่ง:
|
|
|
|
|
|
```python
|
|
|
new_pumpkins.groupby('Variety')['Price'].mean().plot(kind='bar')
|
|
|
```
|
|
|
|
|
|
<img alt="Bar graph of price vs variety" src="../../../../translated_images/th/price-by-variety.744a2f9925d9bcb4.webp" width="50%" />
|
|
|
|
|
|
ขอให้เรามุ่งเน้นที่พันธุ์ฟักทอง 'ชนิดพาย' เท่านั้น และดูว่าวันมีผลต่อราคาอย่างไร:
|
|
|
|
|
|
```python
|
|
|
pie_pumpkins = new_pumpkins[new_pumpkins['Variety']=='PIE TYPE']
|
|
|
pie_pumpkins.plot.scatter('DayOfYear','Price')
|
|
|
```
|
|
|
<img alt="Scatter plot of Price vs. Day of Year" src="../../../../translated_images/th/pie-pumpkins-scatter.d14f9804a53f927e.webp" width="50%" />
|
|
|
|
|
|
ถ้าเราคำนวณค่าความสัมพันธ์ระหว่าง `Price` และ `DayOfYear` ด้วยฟังก์ชัน `corr` เราจะได้ค่าประมาณ `-0.27` — ซึ่งหมายความว่าการฝึกโมเดลทำนายเป็นความคิดที่ดี
|
|
|
|
|
|
> ก่อนฝึกโมเดลการถดถอยเชิงเส้น เราควรมั่นใจว่าข้อมูลสะอาดดี การถดถอยเชิงเส้นทำงานไม่ดีเมื่อมีค่าที่ขาดหายไป ดังนั้นจึงควรลบเซลล์ที่ว่างเปล่าออก
|
|
|
|
|
|
```python
|
|
|
pie_pumpkins.dropna(inplace=True)
|
|
|
pie_pumpkins.info()
|
|
|
```
|
|
|
|
|
|
อีกทางเลือกคือเติมค่าที่ว่างเปล่าด้วยค่าเฉลี่ยจากคอลัมน์นั้น
|
|
|
|
|
|
## การถดถอยเชิงเส้นง่ายๆ
|
|
|
|
|
|
[](https://youtu.be/e4c_UP2fSjg "ML for beginners - Linear and Polynomial Regression using Scikit-learn")
|
|
|
|
|
|
> 🎥 คลิกที่ภาพด้านบนเพื่อดูวิดีโอสั้นเกี่ยวกับการถดถอยเชิงเส้นและพหุนาม
|
|
|
|
|
|
เพื่อฝึกโมเดลการถดถอยเชิงเส้นของเรา เราจะใช้ไลบรารี **Scikit-learn**
|
|
|
|
|
|
```python
|
|
|
from sklearn.linear_model import LinearRegression
|
|
|
from sklearn.metrics import mean_squared_error
|
|
|
from sklearn.model_selection import train_test_split
|
|
|
```
|
|
|
|
|
|
เราเริ่มจากแยกค่าป้อนเข้า (ลักษณะ) และผลลัพธ์ที่คาดหวัง (ป้ายกำกับ) ออกเป็นอาเรย์ numpy แยกกัน:
|
|
|
|
|
|
```python
|
|
|
X = pie_pumpkins['DayOfYear'].to_numpy().reshape(-1,1)
|
|
|
y = pie_pumpkins['Price']
|
|
|
```
|
|
|
|
|
|
> โปรดสังเกตว่าเราต้องใช้ `reshape` กับข้อมูลนำเข้าเพื่อให้แพ็คเกจ Linear Regression เข้าใจอย่างถูกต้อง โมเดลการถดถอยเชิงเส้นต้องการอาเรย์ 2 มิติเป็นอินพุต ซึ่งแต่ละแถวแทนเวกเตอร์ของลักษณะนำเข้า กรณีของเรา มีอินพุตเพียงตัวเดียวจึงต้องใช้อาเรย์รูปแบบ N×1 โดยที่ N คือขนาดชุดข้อมูล
|
|
|
|
|
|
จากนั้น เราต้องแบ่งข้อมูลออกเป็นชุดฝึกและชุดทดสอบ เพื่อให้เราสามารถตรวจสอบโมเดลของเราหลังการฝึก:
|
|
|
|
|
|
```python
|
|
|
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
|
|
|
```
|
|
|
|
|
|
สุดท้าย การฝึกโมเดลการถดถอยเชิงเส้นจริงๆ ใช้เพียงสองบรรทัดโค้ด เราสร้างอ็อบเจ็กต์ `LinearRegression` และใช้เมธอด `fit` เพื่อฟิตโมเดลกับข้อมูลของเรา:
|
|
|
|
|
|
```python
|
|
|
lin_reg = LinearRegression()
|
|
|
lin_reg.fit(X_train,y_train)
|
|
|
```
|
|
|
|
|
|
วัตถุ `LinearRegression` หลังจากการ `fit` จะเก็บค่าค่าสัมประสิทธิ์ทั้งหมดของการถดถอยไว้ ซึ่งสามารถเข้าถึงได้โดยใช้สมบัติ `.coef_` ในกรณีนี้มีเพียงค่าค่าสัมประสิทธิ์เดียว ซึ่งควรอยู่ในช่วงประมาณ `-0.017` ซึ่งหมายความว่าราคาดูเหมือนจะลดลงเล็กน้อยตามเวลา แต่อย่ามากนัก ประมาณ 2 เซนต์ต่อวัน เรายังสามารถเข้าถึงจุดตัดของการถดถอยกับแกน Y ได้โดยใช้ `lin_reg.intercept_` ซึ่งจะอยู่ที่ประมาณ `21` ในกรณีนี้ บ่งบอกถึงราคาที่ต้นปี
|
|
|
|
|
|
เพื่อดูว่ารุ่นของเรามีความแม่นยำแค่ไหน เราสามารถทำนายราคาบนชุดข้อมูลทดสอบ จากนั้นวัดความใกล้เคียงระหว่างการทำนายกับค่าที่คาดหวัง ซึ่งสามารถทำได้โดยใช้เมตริก mean square error (MSE) คือค่าเฉลี่ยของความแตกต่างกำลังสองทั้งหมดระหว่างค่าที่คาดหวังและค่าแบบทำนาย
|
|
|
|
|
|
```python
|
|
|
pred = lin_reg.predict(X_test)
|
|
|
|
|
|
mse = np.sqrt(mean_squared_error(y_test,pred))
|
|
|
print(f'Mean error: {mse:3.3} ({mse/np.mean(pred)*100:3.3}%)')
|
|
|
```
|
|
|
|
|
|
ความผิดพลาดของเราดูเหมือนจะอยู่ประมาณ 2 จุด ซึ่งอยู่ที่ประมาณ ~17% ไม่ดีมาก ตัวชี้วัดอีกอย่างของคุณภาพโมเดลคือ **coefficient of determination** ซึ่งสามารถหาค่าได้ดังนี้:
|
|
|
|
|
|
```python
|
|
|
score = lin_reg.score(X_train,y_train)
|
|
|
print('Model determination: ', score)
|
|
|
```
|
|
|
|
|
|
ถ้าค่ามีค่าเป็น 0 แปลว่าโมเดลไม่สนใจข้อมูลนำเข้าและทำงานเหมือน *ตัวทำนายเชิงเส้นที่แย่ที่สุด* ซึ่งเป็นเพียงค่าเฉลี่ยของผลลัพธ์ ค่า 1 หมายความว่าเราสามารถทำนายผลลัพธ์ได้อย่างสมบูรณ์แบบ ในกรณีของเรา ค่าสัมประสิทธิ์อยู่ที่ประมาณ 0.06 ซึ่งค่อนข้างต่ำ
|
|
|
|
|
|
เรายังสามารถวาดกราฟข้อมูลทดสอบพร้อมกับเส้นถดถอยเพื่อดูว่าการถดถอยทำงานอย่างไรในกรณีของเรา:
|
|
|
|
|
|
```python
|
|
|
plt.scatter(X_test,y_test)
|
|
|
plt.plot(X_test,pred)
|
|
|
```
|
|
|
|
|
|
<img alt="Linear regression" src="../../../../translated_images/th/linear-results.f7c3552c85b0ed1c.webp" width="50%" />
|
|
|
|
|
|
## การถดถอยแบบพหุนาม
|
|
|
|
|
|
อีกประเภทหนึ่งของการถดถอยเชิงเส้นคือ การถดถอยแบบพหุนาม (Polynomial Regression) ในขณะที่บางครั้งมีความสัมพันธ์เชิงเส้นระหว่างตัวแปร — เช่น ลูกฟักทองที่มีปริมาตรมากกว่าจะมีราคาสูงกว่า — บางครั้งความสัมพันธ์เหล่านี้ไม่สามารถพล็อตเป็นระนาบหรือตรงได้
|
|
|
|
|
|
✅ นี่คือตัวอย่างเพิ่มเติมบางส่วน [some more examples](https://online.stat.psu.edu/stat501/lesson/9/9.8) ของข้อมูลที่สามารถใช้การถดถอยแบบพหุนามได้
|
|
|
|
|
|
ลองพิจารณาความสัมพันธ์ระหว่าง Date กับ Price อีกครั้ง กราฟกระจายนี้ดูเหมือนว่าควรจะวิเคราะห์ด้วยเส้นตรงเท่านั้นหรือไม่? ราคาสามารถผันผวนได้หรือไม่? ในกรณีนี้ คุณสามารถลองใช้การถดถอยแบบพหุนามได้
|
|
|
|
|
|
✅ พหุนามคือสมการทางคณิตศาสตร์ที่อาจประกอบด้วยตัวแปรและสัมประสิทธิ์หนึ่งตัวหรือมากกว่านั้น
|
|
|
|
|
|
การถดถอยแบบพหุนามสร้างเส้นโค้งเพื่อการฟิตข้อมูลที่ไม่เชิงเส้นได้ดีขึ้น สำหรับกรณีของเรา หากเราเพิ่มตัวแปรยกกำลังสองของ `DayOfYear` ลงในข้อมูลนำเข้า เราควรจะสามารถฟิตข้อมูลได้ด้วยเส้นโค้งพาราโบลา ซึ่งจะมีค่าต่ำสุดในจุดใดจุดหนึ่งของปี
|
|
|
|
|
|
Scikit-learn มี API [pipeline](https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.make_pipeline.html?highlight=pipeline#sklearn.pipeline.make_pipeline) ที่มีประโยชน์สำหรับรวมขั้นตอนการประมวลผลข้อมูลต่าง ๆ เข้าด้วยกัน **pipeline** คือโซ่ของ **estimators** ในกรณีของเรา เราจะสร้าง pipeline ที่เพิ่มคุณลักษณะพหุนามก่อน จากนั้นจึงเทรนการถดถอย:
|
|
|
|
|
|
```python
|
|
|
from sklearn.preprocessing import PolynomialFeatures
|
|
|
from sklearn.pipeline import make_pipeline
|
|
|
|
|
|
pipeline = make_pipeline(PolynomialFeatures(2), LinearRegression())
|
|
|
|
|
|
pipeline.fit(X_train,y_train)
|
|
|
```
|
|
|
|
|
|
การใช้ `PolynomialFeatures(2)` หมายความว่าเราจะรวมพหุนามลำดับที่สองทั้งหมดจากข้อมูลนำเข้า ในกรณีของเราหมายถึงเพียง `DayOfYear`<sup>2</sup> แต่ถ้ามีตัวแปรนำเข้าสองตัว X และ Y ก็จะเพิ่ม X<sup>2</sup>, XY และ Y<sup>2</sup> เราสามารถใช้พหุนามลำดับสูงกว่านี้ได้ถ้าต้องการ
|
|
|
|
|
|
Pipeline สามารถใช้ในลักษณะเดียวกับวัตถุ `LinearRegression` เดิม เช่น เราสามารถ `fit` pipeline และจากนั้นใช้ `predict` เพื่อรับผลการทำนาย นี่คือกราฟที่แสดงข้อมูลทดสอบและเส้นโค้งประมาณค่า:
|
|
|
|
|
|
<img alt="Polynomial regression" src="../../../../translated_images/th/poly-results.ee587348f0f1f60b.webp" width="50%" />
|
|
|
|
|
|
การใช้การถดถอยแบบพหุนาม เราจะได้ค่า MSE ต่ำลงเล็กน้อยและค่า determination สูงขึ้นเล็กน้อยแต่ไม่มากนัก เราต้องพิจารณาคุณลักษณะอื่น ๆ ด้วย!
|
|
|
|
|
|
> คุณจะเห็นว่าราคาฟักทองต่ำสุดจะถูกสังเกตเห็นราว ๆ วันฮัลโลวีน คุณอธิบายสิ่งนี้ได้อย่างไร?
|
|
|
|
|
|
🎃 ยินดีด้วย คุณเพิ่งสร้างโมเดลที่ช่วยทำนายราคาของฟักทองทำพาย คุณน่าจะทำขั้นตอนนี้ซ้ำสำหรับฟักทองชนิดอื่น ๆ แต่จะยุ่งยาก มาเรียนรู้วิธีที่จะรวมชนิดฟักทองเข้ากับโมเดลของเรากัน!
|
|
|
|
|
|
## คุณลักษณะเชิงหมวดหมู่
|
|
|
|
|
|
ในโลกในอุดมคติ เราต้องการทำนายราคาในชนิดฟักทองต่าง ๆ โดยใช้โมเดลเดียวกัน อย่างไรก็ตาม คอลัมน์ `Variety` แตกต่างจากคอลัมน์อย่าง `Month` เพราะมีค่าที่ไม่ใช่ตัวเลข คอลัมน์แบบนี้เรียกว่า **เชิงหมวดหมู่ (categorical)**
|
|
|
|
|
|
[](https://youtu.be/DYGliioIAE0 "ML for beginners - Categorical Feature Predictions with Linear Regression")
|
|
|
|
|
|
> 🎥 คลิกที่ภาพด้านบนเพื่อชมวิดีโอสั้น ๆ เรื่องการใช้คุณลักษณะเชิงหมวดหมู่
|
|
|
|
|
|
นี่แสดงให้เห็นว่าราคาเฉลี่ยขึ้นอยู่กับชนิดฟักทองอย่างไร:
|
|
|
|
|
|
<img alt="Average price by variety" src="../../../../translated_images/th/price-by-variety.744a2f9925d9bcb4.webp" width="50%" />
|
|
|
|
|
|
เพื่อพิจารณาชนิดฟักทอง เราต้องแปลงเป็นตัวเลขหรือ **เข้ารหัส (encode)** ก่อน มีวิธีทำได้หลายวิธี:
|
|
|
|
|
|
* **การเข้ารหัสเชิงตัวเลขแบบง่าย** คือการสร้างตารางของชนิดที่แตกต่างกัน จากนั้นแทนที่ชื่อชนิดด้วยดัชนีในตารางนั้น วิธีนี้ไม่เหมาะสำหรับการถดถอยเชิงเส้นเพราะการถดถอยเชิงเส้นจะใช้ค่าตัวเลขจริงของดัชนีและเพิ่มเข้าไปในผลลัพธ์โดยคูณด้วยค่าสัมประสิทธิ์ ในกรณีของเรา ความสัมพันธ์ระหว่างหมายเลขดัชนีกับราคาชัดเจนว่าไม่เป็นเชิงเส้น แม้เราจะจัดเรียงดัชนีอย่างเป็นระบบ
|
|
|
* **การเข้ารหัสแบบ One-hot** คือแทนที่คอลัมน์ `Variety` ด้วย 4 คอลัมน์แยกต่างหาก หนึ่งคอลัมน์สำหรับแต่ละชนิด โดยแต่ละคอลัมน์จะเก็บค่า `1` หากแถวที่สอดคล้องมีชนิดนั้น และ `0` หากไม่ใช่ หมายความว่าจะมีค่าสัมประสิทธิ์สี่ตัวใน linear regression หนึ่งตัวสำหรับแต่ละชนิดฟักทอง ซึ่งรับผิดชอบราคาตั้งต้น (หรือเพิ่มขึ้น) สำหรับชนิดนั้น ๆ
|
|
|
|
|
|
โค้ดด้านล่างแสดงวิธีการเข้ารหัสแบบ one-hot สำหรับชนิดฟักทอง:
|
|
|
|
|
|
```python
|
|
|
pd.get_dummies(new_pumpkins['Variety'])
|
|
|
```
|
|
|
|
|
|
ID | FAIRYTALE | MINIATURE | MIXED HEIRLOOM VARIETIES | PIE TYPE
|
|
|
----|-----------|-----------|--------------------------|----------
|
|
|
70 | 0 | 0 | 0 | 1
|
|
|
71 | 0 | 0 | 0 | 1
|
|
|
... | ... | ... | ... | ...
|
|
|
1738 | 0 | 1 | 0 | 0
|
|
|
1739 | 0 | 1 | 0 | 0
|
|
|
1740 | 0 | 1 | 0 | 0
|
|
|
1741 | 0 | 1 | 0 | 0
|
|
|
1742 | 0 | 1 | 0 | 0
|
|
|
|
|
|
ในการฝึก Linear Regression โดยใช้ชนิดฟักทองแบบ one-hot encoded เป็นข้อมูลเข้า เราเพียงแค่ตั้งค่า `X` และ `y` ให้ถูกต้อง:
|
|
|
|
|
|
```python
|
|
|
X = pd.get_dummies(new_pumpkins['Variety'])
|
|
|
y = new_pumpkins['Price']
|
|
|
```
|
|
|
|
|
|
โค้ดที่เหลือเหมือนกับที่เราใช้เทรน Linear Regression ด้านบน หากคุณลองดูจะเห็นว่า mean squared error เท่ากันประมาณเดิมแต่เราได้ coefficient of determination สูงขึ้นมาก (~77%) เพื่อได้การทำนายที่แม่นยำขึ้น เราสามารถพิจารณาคุณลักษณะเชิงหมวดหมู่เพิ่ม รวมทั้งคุณลักษณะตัวเลขเช่น `Month` หรือ `DayOfYear` เพื่อรวมเป็นอาร์เรย์คุณลักษณะเดียวกัน เราสามารถใช้ `join`:
|
|
|
|
|
|
```python
|
|
|
X = pd.get_dummies(new_pumpkins['Variety']) \
|
|
|
.join(new_pumpkins['Month']) \
|
|
|
.join(pd.get_dummies(new_pumpkins['City'])) \
|
|
|
.join(pd.get_dummies(new_pumpkins['Package']))
|
|
|
y = new_pumpkins['Price']
|
|
|
```
|
|
|
|
|
|
ที่นี่เราพิจารณา `City` และชนิด `Package` ด้วยซึ่งทำให้ได้ MSE 2.84 (10%) และ coefficient of determination 0.94!
|
|
|
|
|
|
## รวมทุกอย่างเข้าด้วยกัน
|
|
|
|
|
|
เพื่อทำโมเดลที่ดีที่สุด เราสามารถใช้ข้อมูลรวมกัน (เชิงหมวดหมู่ one-hot encoded + ตัวเลข) จากตัวอย่างข้างต้นพร้อมกับการถดถอยแบบพหุนาม นี่คือโค้ดทั้งหมดเพื่อความสะดวกของคุณ:
|
|
|
|
|
|
```python
|
|
|
# ตั้งค่าข้อมูลการฝึกอบรม
|
|
|
X = pd.get_dummies(new_pumpkins['Variety']) \
|
|
|
.join(new_pumpkins['Month']) \
|
|
|
.join(pd.get_dummies(new_pumpkins['City'])) \
|
|
|
.join(pd.get_dummies(new_pumpkins['Package']))
|
|
|
y = new_pumpkins['Price']
|
|
|
|
|
|
# แบ่งข้อมูลเป็นชุดฝึกอบรมและชุดทดสอบ
|
|
|
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
|
|
|
|
|
|
# ตั้งค่าและฝึกอบรม pipeline
|
|
|
pipeline = make_pipeline(PolynomialFeatures(2), LinearRegression())
|
|
|
pipeline.fit(X_train,y_train)
|
|
|
|
|
|
# ทำนายผลลัพธ์สำหรับข้อมูลทดสอบ
|
|
|
pred = pipeline.predict(X_test)
|
|
|
|
|
|
# คำนวณ MSE และค่าความชัน
|
|
|
mse = np.sqrt(mean_squared_error(y_test,pred))
|
|
|
print(f'Mean error: {mse:3.3} ({mse/np.mean(pred)*100:3.3}%)')
|
|
|
|
|
|
score = pipeline.score(X_train,y_train)
|
|
|
print('Model determination: ', score)
|
|
|
```
|
|
|
|
|
|
สิ่งนี้ควรให้ค่าค่าสัมประสิทธิ์การกำหนด (determination coefficient) ที่ดีที่สุดเกือบ 97% และ MSE=2.23 (~8% ความผิดพลาดการทำนาย)
|
|
|
|
|
|
| Model | MSE | Determination |
|
|
|
|-------|-----|---------------|
|
|
|
| `DayOfYear` Linear | 2.77 (17.2%) | 0.07 |
|
|
|
| `DayOfYear` Polynomial | 2.73 (17.0%) | 0.08 |
|
|
|
| `Variety` Linear | 5.24 (19.7%) | 0.77 |
|
|
|
| All features Linear | 2.84 (10.5%) | 0.94 |
|
|
|
| All features Polynomial | 2.23 (8.25%) | 0.97 |
|
|
|
|
|
|
🏆 เยี่ยมมาก! คุณสร้างโมเดล Regression สี่รุ่นในบทเรียนเดียว และปรับปรุงคุณภาพโมเดลไปสู่ 97% ในส่วนสุดท้ายของบทเรียนเกี่ยวกับ Regression คุณจะได้เรียนรู้ Logistic Regression เพื่อจำแนกหมวดหมู่
|
|
|
|
|
|
---
|
|
|
## 🚀ความท้าทาย
|
|
|
|
|
|
ทดลองกับตัวแปรที่แตกต่างกันหลายตัวในโน้ตบุ๊กนี้ เพื่อดูว่าค่าความสัมพันธ์สัมพันธ์กับความแม่นยำของโมเดลอย่างไร
|
|
|
|
|
|
## [แบบทดสอบหลังบทเรียน](https://ff-quizzes.netlify.app/en/ml/)
|
|
|
|
|
|
## ทบทวน & ศึกษาเอง
|
|
|
|
|
|
ในบทเรียนนี้เราได้เรียนรู้เกี่ยวกับ Linear Regression ยังมีชนิดของ Regression สำคัญอื่น ๆ อ่านเพิ่มเติมเกี่ยวกับเทคนิค Stepwise, Ridge, Lasso และ Elasticnet หลักสูตรที่แนะนำให้ศึกษาเพิ่มเติมคือ [Stanford Statistical Learning course](https://online.stanford.edu/courses/sohs-ystatslearning-statistical-learning)
|
|
|
|
|
|
## การบ้าน
|
|
|
|
|
|
[สร้างโมเดล](assignment.md)
|
|
|
|
|
|
---
|
|
|
|
|
|
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
|
|
|
**ข้อจำกัดความรับผิด**:
|
|
|
เอกสารฉบับนี้ได้รับการแปลโดยใช้บริการแปลภาษาอัตโนมัติ [Co-op Translator](https://github.com/Azure/co-op-translator) แม้ว่าเราจะพยายามให้ความถูกต้อง โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่แม่นยำ เอกสารต้นฉบับในภาษาต้นทางถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ แนะนำให้ใช้การแปลโดยผู้เชี่ยวชาญมืออาชีพ เราจะไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความที่ผิดพลาดที่อาจเกิดขึ้นจากการใช้การแปลนี้
|
|
|
<!-- CO-OP TRANSLATOR DISCLAIMER END --> |