top of page
ค้นหา
รูปภาพนักเขียนSathit Jittanupat

Transformers.js in single HTML, (v.3) 30+ AI models included

วิธีง่ายที่สุดของการเรียนรู้ว่า AI แต่ละ model ทำงานอย่างไร เก่งแค่ไหน น่าจะเป็นการทดลองส่ง input เข้าไป แล้วสังเกต output ที่ออกมา ใช้วิธีลองผิดลองถูกไปเรื่อย ๆ เรียนรู้จากประสบการณ์ตรงทำให้เข้าใจภาพกว้างได้ดีกว่า เสมือนแนวระนาบตามเส้นแนวนอนของตัวอักษร T 


หลังจากนั้นหากสนใจด้านไหนเป็นพิเศษ ค่อยเริ่มเข้าสู่โหมดศึกษาจริงจังดำดิ่งไปสู่เส้นแนวตั้งของตัว T จึงเป็นเรื่องที่ต้องค้นคว้าจากคำอธิบายของผู้สร้าง model นั้น ว่าใช้เทคนิคอย่างไรหรือ train ด้วยตัวอย่างแบบไหน เหมือนกับดู CV ของผู้สมัครงานที่ผ่าน qualified ว่าเรียนจบสาขาวิชาไหน เพื่อประเมินว่าต้นทุนหรือความรู้พื้นฐานที่มีสามารถใช้ต่อยอดช่วยทำงานที่เราต้องการได้หรือไม่


ปัญหาอยู่ที่ AI หลายตัวยังอยู่ในระยะกำลังพัฒนา ผู้สร้างเองก็ไม่ทันได้อธิบายละเอียด เพราะงานยังไม่จบ บางอย่างยังไม่ลงตัว เหมือนทางเดินในตึกที่กำลังก่อสร้าง ไม่ได้เคลียร์ทางจนปลอดภัยสำหรับคนทั่วไป ผู้ใช้ทางก็ต้องรู้ว่าหลบหลีกอย่างไร เพียงแต่เห็นเค้าลางของความเป็นไปได้ หากเราสนใจก็ต้องหาทางทำความเข้าใจ ด้วยการอ่านจาก code หรือ project repository ของเขา โดย setup และทดสอบเอาเอง 


ข้อดีของ Transformers ที่ออกแบบมาให้เขียนโค้ดเรียกใช้งานใน browser ได้ ทำให้สะดวกต่อการทดลองเล่น AI โดยไม่ต้องออกแรงมาก เพียงส่ง input ผ่าน API ของ transformers และรอรับ output ที่เป็นผลลัพธ์มาแสดง ไม่ว่าจะเรียกใช้ model ไหนก็มีมาตรฐานการติดต่อแบบเดียวกัน 


ดังนั้นวิธีที่สะดวกสำหรับการทดสอบคือ จัดเตรียม sample สำหรับแต่ละ model ให้ทดสอบง่าย เพื่อเป็นไอเดีย แล้วหากสนใจก็สามารถทดสอบเพิ่มเติมด้วยตัวเอง หรือค้นคว้าเพิ่มเติมจาก link ของ model นั้น


สำหรับผู้ที่ต้องการทดสอบ  สามารถทดสอบได้ที่ github pages test-transformers-v3.html
source code อยู่ใน github jojosati/singleHTML 

model spec

input/output ที่แตกต่างกันของแต่ละ model ที่สามารถใช้ผ่าน Transformers ประกอบด้วย ข้อความ (text), ภาพ (image) และ เสียง (audio) 


ใน version 3 นี้ได้ปรับปรุงโค้ดให้รองรับ model ตามเงื่อนไข input/output ที่แตกต่างกันได้เท่าที่มีคู่มือแนะนำใน Hugging Face



ผมใช้วิธีกำหนด spec ของ model เพื่อบอกให้โปรแกรมรู้ว่า input/output เป็นอะไร


text translator

ใช้แปลภาษา ส่งข้อความ (text) เข้าไป แล้วได้ข้อความ (text) ออกมา ไม่ต้องระบุเงื่อนไข input/output พิเศษ


      { 
        label: 'text translator /m2m100',
        task: 'translation', 
        model: 'Xenova/m2m100_418M',
        sample: '生活就像一盒巧克力。', 
        options: { 
          src_lang: 'zh', 
          tgt_lang: 'en'
        },
      },

image classifier

ใช้วิเคราะห์องค์ประกอบภายในรูปภาพ ต้องการ input เป็นรูปภาพ (image) โดยระบุ src: ‘image’ส่วน output ที่ได้เป็นข้อความ (text) ตามปกติ ไม่ต้องระบุเงื่อนไขพิเศษ

      { 
        label: 'image classifier',
        task: 'image-classification', 
        model: 'Xenova/vit-base-patch16-224',
        src: 'image',
        sample: 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/tiger.jpg',
        options: { topk: 3 },
      },

image upscaler

เป็น AI ที่ใช้ขยายรูปภาพ ดังนั้นจึงต้องกำหนดให้เป็น image ทั้ง input และ output

      { 
        label: 'image upscaler',
        task: 'image-to-image', 
        model: 'Xenova/swin2SR-classical-sr-x2-64',
        src: 'image',
        out: 'image',
        sample: 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/butterfly.jpg',
      },

Natural Language Processing 

src: text out: text

เป็น AI model ที่รับ input เป็น text หลังจากประมวลผลแล้วจะได้ผลลัพธ์ออกมาเป็น text


การออกแบบโปรแกรมให้รับ input เป็นข้อความ และแสดงผลลัพธ์ (output) ที่เป็นข้อความจึงทำได้ง่าย เพราะเป็นพื้นฐานที่มนุษย์ใช้ติดต่อกับคอมพิวเตอร์มาตั้งแต่แรก การทดสอบก็ง่ายเช่นกัน



Vision Processing

src: image out: text

เป็น AI model ที่รับ input เป็นรูปภาพ (image) และได้ผลลัพธ์เป็นข้อความ ใช้สำหรับแยกแยะรูปภาพ (image classification) หรือแปลงตัวอักษรในรูปภาพ (character recognition) การออกแบบให้รับ input ค่อนข้างยุ่งยากเล็กน้อย การส่งรูปภาพไปประมวลผลต้องใช้เทคนิคเล็กน้อย


สำหรับ input ที่จะส่งไปให้ AI กรณีรูปภาพในอินเตอร์เน็ต สามารถใช้ url (ขึ้นต้นด้วย https: หรือ http:) ของรูปนั้นได้เลย แต่ถ้าเป็นไฟล์รูปภาพที่อยู่ในเครื่อง จะต้องเขียนโค้ดอ่านไฟล์นั้นมาแล้วแปลงเป็น data URL (ขึ้นต้นด้วย data:)

src: image out: image

มี model พิเศษอยู่ตัวหนึ่งคือ image upscaler ที่ใช้ input เป็นรูปภาพแล้วตอบกลับมาเป็นรูปภาพ ปัญหาจึงอยู่ที่จะเอารูปภาพนั้นกลับมาแสดงได้อย่างไร หลังจากหาข้อมูลด้วยการถาม Bard AI และ Stack Overflow จึงพบว่า JavaScript ไม่รองรับการเอาข้อมูลรูปภาพนั้นมาแสดงได้อย่างง่าย ๆ จึงต้องเขียน function ขึ้นใช้เอง



ข้อมูลรูปภาพที่ได้รับมาจาก AI ผมเรียกว่าเป็น pixel data ซึ่งมีโครงสร้างดังนี้

{ // pixel data
  "width": <number>,
  "height": <number>,
  "channels": <number>,
  "data": <byteArray> [00, 255, ... ],
}

ขณะที่โครงสร้าง ImageData ที่ JavaScript ใช้ เป็นดังนี้

{ // ImageData type
  "width": <number>,
  "height": <number>,
  "colorSpace": <string>,
  "data": <byteArray> [00, 255, ... ],
}

คล้ายกัน แต่ไม่เหมือนกัน โดยเฉพาะส่วนของ data ที่เป็น byteArray


  • pixel data ใช้ค่า channels บอกจำนวน bytes ต่อ pixel (3 = RGB) หรือ (1 = gray scale)


  • ImageData มีขนาด 4 bytes ต่อ pixel เสมอ เทียบเท่ากับ RGBA (byte ที่สี่เป็นค่า Alpha ความโปร่งแสง)


เมื่อเข้าใจโครงสร้างแล้ว จึงได้ function แปลง pixel data เป็น ImageData เพื่อใช้ใน browser ดังนี้


    utils.imageFromPixel = function (pixeldata) {
      const width = pixeldata.width
      const height = pixeldata.height
      const channels = pixeldata.channels
      const imageData = new ImageData(width, height)

      for (let y = 0; y < height; y++) {
        for (let x = 0; x < width; x++) {
          const index = (y * width + x) * 4;
          const rgbindex = (y * width + x) * channels

          imageData.data[index] = pixeldata.data[rgbindex]; // Red value
          imageData.data[index + 1] = pixeldata.data[rgbindex + (1 % channels)]; // Green value
          imageData.data[index + 2] = pixeldata.data[rgbindex + (2 % channels)]; // Blue value
          imageData.data[index + 3] = 255; // Alpha value (default to opaque)
        }
      }

      return imageData
    }
input: image output: imagemask

image segmenter ใช้สำหรับตรวจหาองค์ประกอบสำคัญในภาพ แล้วตอบกลับมาเป็นรูปภาพแบบพิเศษ ใช้ซ้อนกับรูปภาพต้นฉบับ แสดงขอบเขตของสิ่งที่ตรวจจับได้ 


ข้อมูลรูปภาพที่เป็น pixel mask มีโครงสร้างเหมือน pixel data ปกติ แต่ใช้ channels = 1 กลายเป็นภาพขาว-ดำ เมื่อเอาไปซ้อนกับภาพต้นฉบับ ก็จะเหลือภาพต้นฉบับเฉพาะส่วนที่ซ้อนกับสีขาว



โค้ดสำหรับสร้างภาพซ้อน ใช้วิธีแปลง pixel data เป็น ImageData เหมือนภาพปกติ แล้วเอา ImageData ของภาพทั้งสองมาทำ bitwise AND 


สีดำ ค่า mask pixel 0 ทำให้กลายสีดำตาม mask 


สีขาว ค่า mask pixel เป็น 255 เมื่อ AND แล้วทำให้ได้ค่า pixel ตามภาพต้นฉบับ


  utils.imageMask = function (img1, img2) {
    const width1 = img1.width
    const height1 = img1.height
    const width2 = img2.width
    const height2 = img2.height

    if (!img1 || !img2)
      return img1 || img2;

    const imageData = new ImageData(width1, height1)

    for (let y = 0; y < height1; y++) {
      for (let x = 0; x < width1; x++) {
        const index1 = (y * width1 + x) * 4;

        imageData.data[index1] = img1.data[index1]; // Red value
        imageData.data[index1 + 1] = img1.data[index1 + 1]; // Green value
        imageData.data[index1 + 2] = img1.data[index1 + 2]; // Blue value
        imageData.data[index1 + 3] = img1.data[index1 + 3]; // Alpha value (default to opaque)

        if (y < height2 && x < width2) {
          const index2 = (y * width2 + x) * 4;

          imageData.data[index1] &= img2.data[index2]; // Red value
          imageData.data[index1 + 1] &= img2.data[index2 + 1]; // Green value
          imageData.data[index1 + 2] &= img2.data[index2 + 2]; // Blue value
        }
      }
    }
    return imageData
  }

Audio Processing

src: audio out: text 

AI model ในกลุ่มนี้เกี่ยวข้องกับการประมวลผลเสียง แล้วให้ผลลัพธ์กลับมาเป็นข้อความ ส่วนใหญ่เกี่ยวข้องกับการแยกแยะเสียง (audio classification) หรือถอดเสียงพูดให้กลายเป็นข้อความ (transcribe / speech recognition)



เช่นเดียวกับรูปภาพ ข้อมูลเสียงที่เป็น url อยู่ในอินเตอร์เน็ตสามารถส่งไปประมวลผลได้ทันที แต่ถ้าใช้ไฟล์เสียงที่อยู่ในคอมพิวเตอร์ต้องแปลงเป็น data URL


โชคดีที่ HTML5 มี tag <audio> ให้ใช้เป็น player ได้คล้ายกับการใช้ <img> แสดงรูปภาพ 

<audio controls ng-src="{{ trustResourceUrl(expr) }}"></audio>

ติดขัดเพียง AngularJS ไม่รู้จัก tag นี้ และไม่อนุญาตให้ใช้ url โดยตรง ต้องทำให้เป็น trust resource ก่อน

    $scope.trustResourceUrl = function (url) {
      return $sce.trustAsResourceUrl(url)
    }
src: text out: audio

ตัวอย่าง AI model กลุ่มนี้ คือ text to speech ใช้อ่านข้อความนั่นเอง 



โชคดีที่ข้อมูลเสียง ที่ได้รับมาจาก AI สามารถใช้ lib wavefile มาช่วยแปลงให้เป็น data URL เพื่อใช้กับ <audio> ได้

    if (spec.out=='audio' && result.audio) {
      var wav = new wavefile.WaveFile()

      wav.fromScratch(1, result.sampling_rate, '32f', result.audio)
      $scope.result.audio = wav.toDataURI()
    }

Multimodal

src: image out: text (ไม่ต้องระบุ)

image document Q&A

เป็น AI model ที่ผสมระหว่าง Vision Processing อ่านข้อความจากรูปภาพ กับ NLP วิเคราะห์ความหมายข้อความนั้น เพื่อตอบคำถาม

 

ความซับซ้อนเป็นเรื่องภายในของผู้สร้าง model แต่การเขียนโปรแกรมเพื่อเรียกใช้งาน ทำเหมือนกับ model อื่นข้างต้น



image captioner

ใช้ Vision Processing แยกแยะองค์ประกอบของภาพ แล้วใช้ NLP สร้างข้อความอธิบายรูปภาพนั้น



src: image|audio + choices out: text (ไม่ต้องระบุ)

zero-shot model

ใช้สำหรับวิเคราะห์ input ที่ได้รับ เพื่อให้ค่าความน่าจะเป็น (score) ตาม choices ที่ระบุมา



ซน! 

unlisted model

แล้วยังมี model อื่นทำได้เหมือนกันอีกไหม ?

ก่อนที่จะส่งโค้ด v3 ไปไว้ใน gist ผมตื่นมาตอนเช้าพร้อมกับความคิดว่า น่าจะทำให้สามารถใส่ชื่อ model ที่ยังไม่มีใน list ได้ด้วย เพื่อจะได้ทดสอบแบบเร็ว ๆ ในเมื่อ input กับ output ทั้งหลายก็มีมาตรฐานคล้าย ๆ กันอยู่แล้ว


อาจจะเป็น model ที่เพิ่งปรับปรุงออกมาใหม่ หรือเป็น model ที่ผู้สร้างไม่ได้เขียนอธิบายเอาไว้ 


  • เริ่มจากไล่ดูรายชื่อ model ทั้งหมดของ task ที่ใช้กับ Transformer.js ได้ (จากเพจของ Hugging Face) เช่น task: fill-task




  • พบว่ามี model ที่อยู่ในหมวด fill-mask อีกหลายตัว จึงทดลองใช้ model Xenova/wangchanberta-base-att-spm-uncased (สังหรณ์ว่าตั้งชื่อโดยนักพัฒนาไทย) สังเกตว่าไม่มีคู่มือ แนะนำการเรียกใช้งานใด ๆ เลย นอกจากข้อความมาตรฐานตาม template เราจึงทดลองเอาแค่ชื่อ model ไปใช้ทดสอบ



  • ผลการทดสอบลองใส่ input หลาย ๆ แบบ พบว่า model นี้ต้องใช้ตัวอักษร lowercase เท่านั้น และใช้สัญญลักษณ์ <mask> จึงสามารถตอบกลับมาได้ตามภาพ เดาได้ว่าเป็น model ที่ train ด้วยข้อมูลที่มีภาษาไทยด้วย เพราะได้ผลลัพธ์เป็นคำไทยออกมา



สรุป

ผมเริ่มเข้าสู่แวดวง AI ในแง่มุมของการเขียนโปรแกรมเพื่อเรียกใช้ พยายามมองหาช่องทางในการประยุกต์ใช้ ซึ่งก็ยังไม่อะไรที่เป็นเป้าหมายชัดเจน ความรู้สึกแรกที่ได้ลองสำรวจบรรดา big name เช่น OpenAI, Google และ Microsoft มีอาการเหมือนเข้ามาในงานที่มีคนมากมาย แต่ไม่เห็นใครที่คุ้นเคยเลย คนในนั้นพูดคุยกันด้วยคำศัพท์ที่ฟังไม่เข้าใจ


pipeline

เริ่มแรกจากการทดลองเขียนโปรแกรมติดต่อกับ PaLM API แต่เนื่องจากเป็น LM (Language Model) ใช้ข้อความ text เป็น input/output เหมือนกับใช้ ChatGPT และ Bard พอไม่มีโจทย์หลังจากเขียนโปรแกรมติดต่อได้แล้ว เลยยังคิดไม่ออกว่าจะทดสอบอะไรต่อ


พอมาเจอ Hugging Face แล้วได้ลองเขียนโค้ดผ่าน Transformer.js ทำให้เห็นชิ้นส่วนเล็ก ๆ ที่เป็น AI เฉพาะทาง สามารถเอามาประกอบกันให้กลายเป็น model ใหญ่ขึ้นได้ 


ตัวอย่างเช่น หากต้องการแปลงเสียงที่พูดภาษาไทยเป็นเสียงพูดภาษาอังกฤษ จะต้องใช้ AI หลาย model มาต่อเป็น pipeline ผลลัพธ์จากขั้นตอนหนึ่งจะส่งต่อไปเป็นอินพุทสำหรับขั้นตอนต่อไป


  • auto-speech-recognition เริ่มต้นจากเสียงพูดภาษาไทย แปลงเป็นข้อความภาษาไทย 

  • text-translation จากข้อความภาษาไทย แปลเป็นข้อความภาษาอังกฤษ

  • text-to-speech จากข้อความภาษาอังกฤษ แปลงเป็นเสียงพูด


..และแบคทีเรียก็มีบทบาทหลักเช่นเคยในการวิวัฒน์แบบซิมไบโอซิส เมื่อแบคทีเรียขนาดเล็กบางชนิดผนวกรวมกับเซลล์ที่ใหญ่กว่าอย่างเกื้อกูลกัน และยังอยู่ในเซลล์เหล่านั้นเรื่อยมาในฐานะเป็นองค์ประกอบของเซลล์ ผลที่เกิดขึ้นตามมาก็คือก้าวขนาดยักษ์ในวิวัฒนาการ นั้นคือการก่อเกิดของเซลล์พืชและสัตว์ซึ่งสืบพันธุ์ด้วยเพศ และในที่สุดก็วิวัฒน์ขึ้นเป็นสิ่งมีชีวิตต่างๆ ที่เห็นกันอยู่ในสิ่งแวดล้อมของเรา ..เมื่ออะตอมคาร์บอน ออกซิเจน และไฮโดรเจน เกาะเกี่ยวกันแบบหนึ่งเพื่อสร้างน้ำตาล สารประกอบที่ได้จะมีรสหวาน ความหวานนั้นไม่ใช่อยู่ใน C หรือ O หรือ H แต่อยู่ในแบบแผนที่ผุดบังเกิดจากปฏิสัมพันธ์ของอะตอมเหล่านั้น มันเป็นคุณสมบัติที่ผุดบังเกิดขึ้นมา และถ้าจะพูดให้ชัดขึ้นอีก ความหวานก็ไม่ใช่คุณสมบัติการเกาะเกี่ยวทางเคมี แต่เป็นประสบการณ์ของประสาทสัมผัสของเรา ที่เกิดขึ้นเมื่อโมเลกุลน้ำตาลทำปฏิกิริยากับปรากฏการณ์ทางเคมีในต่อมรับรส ซึ่งส่งผลให้เซลล์ประสาทชุดหนึ่งส่งสัญญาณแบบหนึ่งขึ้นมา ประสบการณ์ของความหวานจึงผุดบังเกิดขึ้นจากกิจกรรมของระบบประสาท โยงใยที่ซ้อนเร้น / (2002) Fritjof Capraวิศิษฐ์ — ณัฐฬส วังวิญญู และสว่างพงศ์ศิริพัฒน์ แปล

สเปคคอมพิวเตอร์ 

ปกติผมสลับใช้โน้ตบุ๊คหลายเครื่อง มีสเปคของ CPU/memory แตกต่างกัน หากนั่งทำงานข้างนอกจะใช้เครื่องที่น้ำหนักเบา (Pentium M/4GB) หากอยู่บ้านก็ใช้ 2 เครื่อง (i5 gen8/8GB) หรือ (i5 gen10/16GB) 


ทุกเครื่องสามารถเรียกใช้โปรแกรมทดสอบผ่าน browser ได้ เพียงแต่ช้าเร็วต่างกันค่อนข้างชัดเจน และเครื่องที่ memory น้อย บางครั้งไม่สามารถทดสอบหลาย model ต่อเนื่องกันได้ ต้องสั่ง refresh browser ก่อน


เมื่อคืนนี้เองที่ผมเพิ่งสังเกตว่า ทุกครั้งที่สั่งให้ประมวลผลเสียงพัดลมโน้ตบุ๊คดังขึ้นชัดเจนท่ามกลางความเงียบ จึงคิดว่าหากจะไปให้ไกลกว่านี้ ก็ต้องใช้พลัง CPU และ memory อย่างที่นักพัฒนา AI หลายคนบอกจริง ๆ ที่สำคัญอาจจะไม่สามารถทำแค่ลองเล่นสนุกๆ แบบนี้อีกแล้ว เป็นสิ่งที่ยังตอบตัวเองไม่ได้ หากจะเลือกไปตามเส้นแนวตั้งของตัว T 


“ทำไปทำไม” และ “ต้องแลกกับอะไร” เวลา สุขภาพ หรือความสัมพันธ์?


2023–12–10


ดู 1 ครั้ง0 ความคิดเห็น

โพสต์ล่าสุด

ดูทั้งหมด

Comments


Post: Blog2_Post
bottom of page