Month: August 2021

  • [บันทึกกันลืม] วิธีทำให้ jupyter notebook สามารถ export to PDF ได้

    บน OS ต้องติดตั้ง

    apt-get install -y texlive-xetex texlive-fonts-recommended texlive-latex-recommended pandoc

    แค่นั้น

  • วิธีรัน Jupyter Notebook, ปิด browser แล้วระบบส่ง LINE บอกพร้อมภาพ เมื่อเสร็จแล้ว ค่อยกลับมาดูผล

    ปัจจุบัน งานด้าน Data Science ก็มักจะใช้ Jupyter Notebook เพราะสะดวกในการทดลอง ทดสอบ ทำทีละบรรทัด ดูผล ปรับแต่งไปได้เรื่อย ๆ แถมสามารถซื้อ Server ส่วนกลาง ลงทุน GPU แล้วใช้พร้อม ๆ กันหลาย ๆ คนทั้งทีมก็ได้

    ปัญหาอยู่ตรงที่ การสร้าง Model มักจะใช้เวลานาน (มาก) แล้ว Jupyter มันเป็น Web-based จะปิด Browser ก็ได้ แต่หลายคนคงเคยเจอว่า พอกลับมาเปิด URL เดิม ก็ไม่เห็นผลที่รันแล้ว

    จริง ๆ แล้วคือ Jupyter Notebook นั้น ทำงานต่อไป จนเสร็จแล้วแหล่ะ แต่ เว็บ Browser น่าจะไม่สามารถต่อ Session ได้ (หวังว่าจะนึกภาพออก) ที่สำคัญ มันรันนานมาก เสร็จเมื่อไหร่ก็ไม่รู้ แล้วจะรู้ได้อย่างไรว่าเสร็จ เสร็จแล้วผลเป็นอย่างไร

    ในบทความนี้ จะนำเสนอวิธีการที่ทำให้

    1. สั่งรันงานที่ใช้เวลานาน (ขอยกตัวอย่าง 100 วินาที) แล้วปิด Browser ไปทำอย่างอื่นต่อได้เลย
    2. เมื่อระบบทำงานเสร็จ จะแจ้ง LINE Notify พร้อมแนบภาพ Graph ผลลัพธ์ ส่งมาด้วย
    3. พอกลับมาเปิด 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()

    ก็จะแสดงผลสิ่งที่ดำเนินการไป ระหว่างนั้นได้ครับ

    หวังว่าจะเป็นประโยชน์ครับ

  • [บันทึกกันลืม] วิธีตั้งค่า DBeaver ให้สามารถใช้ Memory ได้สูงขึ้น

    พอดีใช้ MacBook RAM 16 GB และใช้งาน DBeaver เป็น Database Tool รุ่น Community ดีอ่ะ มันฟรี Run บน Java ทำให้ใช้งาน Cross platform ได้

    ส่วนคนในสถานศึกษา สามารถใช้งานรุ่น Pro ได้นะ ใช้ Email ของมหาวิทยาลัยไปขอ Academic Licence ได้ ใช้งานได้เหมือนรุ่น Enterprise แต่ก็ต้องขอใช้ปีต่อปี ข้อดีคือ มีพวก Visual Query Builder, Support NoSQL และ ติดต่อกับพวก Big Data ได้ ลองใช้งานดู ถ้าถูกใจใช้ถาวร ก็ซื้อเค้าเถอะ ดีจริง ๆ ดีกว่าไปใช้ขอ Crack เสี่ยงภัยมาก

    แต่ส่วนตัว ใช้รุ่น Community Edition ก็รู้สึกเพียงพอแล้ว ใช้ต่อไป

    มีปัญหาอยู่นิดเดียวคือ ค่า Default ของการใช้ Java Virtual Machine เนี่ย มันตั้ง configuration มาให้ใช้แค่ 1 GB ทำให้เวลาเขียน Query ที่บางทีต้อง Fetch ข้อมูลมาไว้ใน Local Memory บ้าง ก็จะขึ้น Error

    java.lang.OutOfMemoryError: Java heap space ”

    (RAM 16 GB นะโว้ย เต็มไรกัน)

    ซึ่งไปลองค้นหามา พบว่า เราสามารถตั้งค่าได้ โดยแก้ไขไฟล์ dbeaver.ini

    สำหรับคนใช้ MacOS ทำงี้นะครับ

    ไปที่ Finder > Application หาคำว่า DBeaver
    คลิกที่เมนู Show Package Contents
    Contents > Eclipse > dbeaver.ini
    ใช้ Editor ตามใจปรารถนา แก้ตรง -Xmx1024m เป็น สัก 1/4 หรือ 1/2 ของ RAM ก็ดี มากไป เครื่อง Hang ได้ ผมตั้งไว้ 4GB ก็แก้เป็น -Xmx4096m แล้ว Save

    ก็เท่านี้ ปิด เปิดใหม่ คราวนี้ เปิด Database เขียน Query ได้ตามสะดวกครับ

  • วิธี Word Wrap ใน Jupyter Notebook / Jupiter Lab

    มีคำถามมา หาคำตอบเจอ คิดว่าเป็นประโยชน์​เลยบันทึกไว้

    ปัญหาของคนใช้ Jupyter Notebook / Jupyter Lab คือ ถ้ามีโค๊ดยาว ๆ จะไม่ขึ้นบันทัดใหม่ให้ จริง ๆ ต้องบอกว่า ไม่ Word Wrap ตามภาพที่ 1

    ภาพที่ 1: Jupyter Notebook / Jupyter Lab ไม่ Word Wrap

    ไปค้นหามา พบข้อมูลจาก Alex Ioannides ตอบที่ https://stackoverflow.com/questions/48202340/enable-word-wrap-in-jupyterlab-code-editor

    เค้าแนะนำให้เอาแก้ไขโดยใส่สิ่งนี้ใน Settings

    {
       "codeCellConfig": {
          "lineWrap": "wordWrapColumn",
          "wordWrapColumn": 80
       }
    }

    แต่มันอยู่ตรงไหนหล่ะ

    มันอยู่ตรงนี้นะ Settings > Advanced Settings Editor

    แล้วก็คลิกที่ Notebook

    จากนั้นเอาโค๊ดข้างต้นไปแปะที่ User Preferences แล้วกดปุ่ม Save ด้านขวามือบน (รูปแผ่น Disk)

    ผล

    หวังว่าจะเป็นประโยชน์นะครับ