ปัจจุบัน งานด้าน Data Science ก็มักจะใช้ Jupyter Notebook เพราะสะดวกในการทดลอง ทดสอบ ทำทีละบรรทัด ดูผล ปรับแต่งไปได้เรื่อย ๆ แถมสามารถซื้อ Server ส่วนกลาง ลงทุน GPU แล้วใช้พร้อม ๆ กันหลาย ๆ คนทั้งทีมก็ได้
ปัญหาอยู่ตรงที่ การสร้าง Model มักจะใช้เวลานาน (มาก) แล้ว Jupyter มันเป็น Web-based จะปิด Browser ก็ได้ แต่หลายคนคงเคยเจอว่า พอกลับมาเปิด URL เดิม ก็ไม่เห็นผลที่รันแล้ว
จริง ๆ แล้วคือ Jupyter Notebook นั้น ทำงานต่อไป จนเสร็จแล้วแหล่ะ แต่ เว็บ Browser น่าจะไม่สามารถต่อ Session ได้ (หวังว่าจะนึกภาพออก) ที่สำคัญ มันรันนานมาก เสร็จเมื่อไหร่ก็ไม่รู้ แล้วจะรู้ได้อย่างไรว่าเสร็จ เสร็จแล้วผลเป็นอย่างไร
ในบทความนี้ จะนำเสนอวิธีการที่ทำให้
- สั่งรันงานที่ใช้เวลานาน (ขอยกตัวอย่าง 100 วินาที) แล้วปิด Browser ไปทำอย่างอื่นต่อได้เลย
- เมื่อระบบทำงานเสร็จ จะแจ้ง LINE Notify พร้อมแนบภาพ Graph ผลลัพธ์ ส่งมาด้วย
- พอกลับมาเปิด Browser กลับมาใน Jupyter Notebook เดิม สามารถดูผลการรันอื่น ๆ ได้อีกครั้งเหมือนกับไม่ได้ปิด Browser
เริ่มต้นจาก Import
import sys
from IPython.display import clear_output
import logging
import sys
import requests
import datetime,time,pytz
import random
Function ในการส่ง LINE Notify
เป็นส่วนของ LINE TOKEN และ function “jobdone” ไว้ส่ง LINE Notify สามารถกำหนดข้อความ และกำหนดภาพที่จะแนบได้
LINE_TOKEN="YOUR-LINE-TOKEN"
def jobdone(LINE_TOKEN, message="Done!", img=None):
notify_url = 'https://notify-api.line.me/api/notify'
header={
'Authorization': "Bearer " + LINE_TOKEN
}
data=({
'message': message
})
files = {'imageFile': open(img, 'rb')} if img else None
session = requests.Session()
response = session.post(
notify_url,
headers=header,
files=files,
data=data
).json()
if files:
files['imageFile'].close()
Function สำหรับ Plot
รับข้อมูล และ สร้างภาพเพื่อประกอบการส่ง Line
import matplotlib.pyplot as plt
def plot_something(data, resultfilename):
fig, ax = plt.subplots()
ax.plot(data)
ax.grid()
fig.savefig(resultfilename)
plt.show()
ส่วนที่ใช้เวลานาน
%%capture capture_output
resultfilename="result.png"
start_time=time.time()
data=[]
for i in range(100):
data.append(random.random()*100)
time.sleep(1)
plot_something(data, resultfilename)
duration=time.time()-start_time
now=datetime.datetime.now(pytz.timezone('Asia/Bangkok')).strftime("%Y-%m-%d %H:%M:%S")
jobdone(LINE_TOKEN, f'{now} เสร็จแล้วนะโว้ย [{duration:.2f} sec.]', img=resultfilename)
ตรงนี้ต้องอธิบายเพิ่ม
ใน Jupyter จะมีสิ่งที่เรียกว่า “magic cell” ในที่นี้คือ
%%capture capture_output
โดยที่ %%capture คือคำสั่งที่จะเก็บผลลัพธ์ทุกอย่าง ที่ส่งออกจาก stdout, stderr รวมถึงภาพด้วย ในคำสั่งข้างต้น จะส่งออกไปยัง capture_output ซึ่งจะนำไปใช้ในภายหลัง
ต่อมา จะจำลองการทำงานที่ยาวนาน คือ random ค่าระหว่าง 1-100 เอาไปใส่ใน array “data” จากนั้น ก็ sleep 1 วินาที รวมแล้ว ขั้นตอนนี้จะทำงาน 100 วินาที หรือ 1 นาที 40 วินาที (ในการทำงานจริง ยาวนานกว่านั้นมาก ๆ)
เมื่อเสร็จแล้ว plot_something จะเอาข้อมูล data ไป plot แล้วแสดงผล และ save เป็นไฟล์ตามที่กำหนด คือ result.png
คำสั่งต่อมา เป็นการแสดง วันเวลาปัจจุบัน โดยแสดงเป็น Timezone ของไทย
สุดท้าย function jobdone กำหนดข้อความ และภาพที่จะส่ง
Let’s go!
รอไป 1 นาที 40 วินาที ก็จะได้ LINE Notify (อ่านขั้นตอนการได้มาซึ่ง LINE Token ได้จาก วิธีแจ้งเตือนจาก Google Forms เข้า LINE )
กลับมาใน Jupyter Notebook
ใน cell ใหม่ ใช้คำสั่ง
capture_output()
ก็จะแสดงผลสิ่งที่ดำเนินการไป ระหว่างนั้นได้ครับ
หวังว่าจะเป็นประโยชน์ครับ