จำแนกแวดวงบทความสิ่งพิมพ์ 📔🔍 ด้วย Text Classification แบบเรียบง่าย

Chotanansub Sophaken
6 min readJun 16, 2022
Library books photo created by jcomp

สวัสดีครับ!🙏 ผมโชกุน😃 จากโครงการ AI Builders รุ่นที่2 ครับ

โดยในบทความนี้ผมจะมาแบ่งปันประสบการณ์การทำโปรเจคMachine Learning ที่สนใจนะครับ!

ต้องแอบเล่าก่อนว่าภายในโครงการ AI Builders ได้เปิดโอกาสให้นักเรียนมัธยมได้ลองสนุก (สีหน้าความสนุกตอนdebug😨) ไปกับการเรียนรู้ ML ในสาขาที่ตัวเองสนใจครับ โดยผมเองได้สนใจในสาขา Natural Language Processing💬 จึงได้จัดทำโปรเจคนี้ขึ้นมาครับ

ความสำคัญของการจำแนกเอกสารตามแวดวง 📝

ซึ่งการจำแนกเอกสารให้อยู่ในแวดวงต่างๆนั้นมีประโยชน์อย่างอย่างมาก ในการจัดระเบียบการเข้าถึงข้อมูล และหนึ่งในสาขาที่สามารถใช้ประโยชน์จากจุดนี้ได้เป็นอย่างดีคือ ทางสาขาภาษาศาสตร์ ที่มีการจัดทำคลังข้อมูลคำศัพท์แห่งชาติ (National Corpus ในหลายๆประเทศ)

อาทิเช่น British National Corpus (100 ล้านคำ),The Bank of English (ปัจจุบันมีมากกว่า 450 ล้านคำ),American National Corpus (เป้าหมาย 100 ล้านคำ),Czech National Corpus, Hellenic National Corpus (คลังข้อมูลภาษากรีก), National Corpus of Irish (30 ล้านคำ แล้วเสร็จในปี ค.ศ. 1999) และ ของชาติไทยเราเอง Thai National Corpus

ตัวอย่างคลังคำศัพท์แห่งชาติ (National Corpus)

แรงบันดาลใจในการจัดทำโปรเจค 💡

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

สรุปโปรเจคนี้เกี่ยวกับอะไรนะ???

โปรเจคนี้นะครับจะเป็นการเทรน classification model เพื่อจำแนกแวดวง ของเอกสารที่เป็นสื่อสิ่งพิมพ์ต่างๆ ไม่ว่าจะเป็น หนังสือ📘 วารสาร📙 บทความต่างๆ📑

ซึ่งแวดวงที่เราจะทำการจำแนกกัน มี ทั้งหมด 8 แวดวงด้วยกัน!! โดยได้อ้างอิงมาจาก Thai National Corpus ซึ่งเป็น source ในการรวบรวมdata ของเราในครั้งนี้นี่เอง!

เอ๊ะ! 🤨 ทำไมต้องเจาะจงว่า สื่อสิ่งพิมพ์ด้วยล่ะ!? 📚

📌อ้างอิงจาก โครงสร้างคลังข้อมูลภาษาไทยแห่งชาติ ซึ่งเป็นแหล่งที่เรารวบรวมข้อมูลบทความ ได้มีการจำแนกสัดส่วนของแหล่งที่มาข้อมูลไว้ดังนี้ครับ

สัดส่วนของแหล่งที่มาข้อมูล จาก โครงสร้างคลังข้อมูลภาษาไทยแห่งชาติ

🧐สังเกตได้ว่า มากกว่า 95% ของข้อมูลนั้นได้มาจากสื่อสิ่งพิมพ์ ทำให้บริบทของการร้อยเรียงภาษา และ การใช้คำศัพท์จะเป็นในลักษณะของภาษาเขียนเป็นส่วนใหญ่นั่นเอง

💡 จึงมีความเป็นไปได้ว่า โมเดลของเราอาจทำงานได้ไม่ดีเท่าที่ควร เมื่อต้องเผชิญกับ กับภาษาที่เป็นกันเอง อาทิ “จบิงๆ”, “ อุนเทอ” , “แง้นๆ” และ “ขอเซ็ตหย่อ สูดต่อ ซูดผ่อ สี่หม่อ สองห่อ ใส่ไข่” เป็นต้น (ซึ่งจริงๆสามารถ cleanได้ แต่อาจจะเสียบริบทไป)

เปิดประเดิมด้วยการเก็บ Data 📥

สำหรับการเก็บ Data นั้น ผมได้มุ่งมั่นตั้งใจแบบ300% ว่าจะเก็บแบบเบิ้มๆ
โดเมนละ 5,000 บทความ รวมเป็น 40,000บทความ โดยได้รวบรวมมาจากการทำ dynamic scraping เพื่อ รวบรวมบทความจาก Thai National Corpus โดยเราจะเก็บข้อมูล 3 อย่างด้วยกัน ได้แก่

  1. รหัสเอกสาร (Document code)🧾
  2. แวดวง (Domain)🏷️
  3. ข้อความ (Texts) 📝
Web page ที่แสดงข้อมูลของแต่ละบทความ

หลังจาก Scrape เสร็จแล้ว✅
โหลด Dataframe ด้วย Pandas มาดูโฉมหน้า data ของเรากันหน่อยละกัน! 🤩

Dataframe แสดง Data ที่เราได้ scrape มา

ว้าว!!!🥳 สวยงาม!! องค์ประกอบครบตามที่เราต้องการ

มา Clean Data กันเถอะ!! 🧹

ถ้าสังเกตดีๆ แต่ละบทความจะมี serial กำกับไว้ด้วย ซึ่ง serial จะกำกับตามเอกสารต้นฉบับของบทความนั้นๆ “พูดง่ายๆก็คือ serial เดียวกัน มาจาก หนังสือเล่มเดียวกัน นั่นเอง!”

ไม่นะ…เริ่มสัมผัสได้ถึงหายนะลางๆแล้ว☠️ ลองคิดดูนะครับถ้าเรา split data ไปดื้อๆเลย หายนะแห่ง Bias 😈ได้เกิดขึ้นแน่ๆ

ถึงแม้ว่าเอกสารที่มี serial เหมือนกัน ข้อความจะแตกต่างกัน แต่ด้วยความที่ข้อความมันดันมาจากเอกสารฉบับเดียวกัน เรื่องบริบทและการใช้คำศัพท์นี่คล้อยตามกันมาอย่างกับแกะ🐑

ดังนั้นเราควรจัดกลุ่มบทความตามserial ก่อนที่จะsplit data เพื่อหลีกเลี่ยงการกระจายตัวของ serial ใน split dataset อื่นๆ

ซึ่งการจัดกลุ่มในหัวผมเป็นแบบนี้ครับ so easy มากๆ😆🥰 :

⚠️แต่ละครชีวิตของผมได้เริ่มต้นขึ้นแล้ว มีความสุขได้ไม่นาน ผมก็พึ่งตระหนักได้ว่า แต่ละ serial ดันมีจำนวนเอกสารไม่เท่ากัน😱

🤔ณ จุดนี้ ผมจึงต้องสร้างฟังก์ชันเขียนมือ มาเพื่อจัดการกับการ split data ในกรณีที่ต้องการจัดกลุ่มให้ serial ให้ไม่ไปโผล่ split dataset อื่นๆ

💡โดยหลักการทำงานคือทำการสำรองข้อมูลบางส่วน เพื่อทดแทนการเกิดเศษเหลือ หลังจากการแบ่งข้อมูลหลังการจัดกลุ่ม ท้ายที่สุดแล้วเราจะได้สัดส่วนของปริมาณ ของแต่ละ serial ในแต่ละ domain และ split data ออกมา!

แล้วModelล่ะ??? 🤖

ในโปรเจคนี้ผมได้เลือกใช้ Baseline Model 2 ตัวด้วยกัน
//มีสองโมเดลดับเบิ้ลโมเดล!!! 🤖 🤖

ได้แก่

  1. Bag of Word (BoW)
  2. Long Short Term Memory (LSTM)

แต่ช้าก่อน!🙌 ตัวละครเหล่านั้นเป็นเพียง Baseline model
และพระเอกของงานนี้เลยก็คือ….. “ WangchanBERTa” นั่นเอง!! 😎

**โดยใน blog นี้จะไม่ขอลงรายละเอียดในส่วนของ Baseline Model นะครับ แต่จะมุ่งเน้นไปที่พระเอกของโปรเจคเราแบบเน้นๆ นั่นก็คือ WangchanBERTa นั่นเอง!!

ของดีต้องบอกต่อ! 🤩 — WangchanBERTa คืออะไร??

WangchanBERTa ก็คือ Pre-trained Model สำหรับภาษาไทย สุดเทพ จากสถาบันวิจัยปัญญาประดิษฐ์ประเทศไทย (Thailand Artificial Intelligence Research Institute) ที่ VISTEC นั่นเอง

ซึ่งแน่นอนว่า สามารถทำ Text Classification แบบชิลๆ ซึ่งในโปรเจคนี้เราจะมาพึ่งบารมีอันทรงอานุภาพของ WangchanBERTaกัน!!

ถ้าพร้อมแล้วเตรียม Library กันเลย 📂

📥 เริ่ม install library ที่จำเป็นกันก่อน!

!pip install torch==1.7.0
!pip -q install thai2transformers==0.1.1

📥Import library ที่จำเป็นแบบต่อเนื่อง ฉับไว!

import torchfrom sklearn.metrics import accuracy_score, precision_recall_fscore_support
from transformers import (AutoTokenizer,
AutoModelForSequenceClassification,
TrainingArguments,
Trainer)
from thai2transformers.tokenizers import(ThaiRobertaTokenizer,
ThaiWordsNewmmTokenizer,
ThaiWordsSyllableTokenizer,
FakeSefrCutTokenizer)
from thai2transformers.preprocess import process_transformers
from thai2transformers.metrics import classification_metrics

แวะมาดู Dataset อีกซักนิด 🔍

เนื่องจาก Dataset ของเราเป็นรูปแบบ Dataframe เพื่อให้ง่ายต่อการจัดการ จึงต้องทำการ Convert ให้มาอยู่ในรูปแบบ Dataset โดยใช้พลังของ dataset library

from datasets.dataset_dict import DatasetDict
from datasets import Dataset, load_dataset, load_metric
train_df = pd.read_csv("TNC_TrainSet.csv")
valid_df = pd.read_csv("TNC_ValidationSet.csv")
test_df = pd.read_csv("TNC_TestSet.csv")
trainDict = {'texts': train_df['Texts'],
'category': train_df['Category'],
'labels': train_df['Labels']}
validDict = {'texts': valid_df['Texts'],
'category': valid_df['Category'],
'labels': valid_df['Labels']}
testDict = {'texts': test_df['Texts'],
'category': test_df['Category'],
'labels': test_df['Labels']}
DATA = {'train': Dataset.from_dict(trainDict),
'validation': Dataset.from_dict(validDict),
'test': Dataset.from_dict(testDict)}
DATASET = DatasetDict(DATA)
ผลลัพธ์จากการแปลง dataframe ให้อยู่ในรูปแบบ dataset

กำหนด Hyperparameters และ Detailอื่นๆ สำหรับโมเดลเรากันก่อน!

โดยค่า Hyperparameters ในโปรเจคนี้นั้น ส่วนใหญ่ได้อ้างอิงมาจากบทเรียน ของทางโครงการ ในส่วนของแนะนำการใช้งาน WangchanBERTa ซึ่งเป็นค่าเริ่มต้นที่แนะนำสำหรับการทำ Text Classification

#เซ็ต parameters ของเรากัน! 
class Args:
model_name = 'airesearch/wangchanberta-base-att-spm-uncased'
dataset_name_or_path = 'wisesight_sentiment'
feature_col = 'texts'
label_col = 'category'
output_dir ='/content/drive/MyDrive/models_TNC'
` batch_size = 4
warmup_percent = 0.1
learning_rate = 3e-05
num_train_epochs = 5
weight_decay = 0.01
metric_for_best_model = 'f1_micro'
seed = 4713
args = Args()

เริ่มต้น preprocessing data ของเรากัน!

ทำการpreprocess ให้กับ dataของเราด้วย thai2transformers

from thai2transformers.preprocess import process_transformers#สร้างฟังก์ชันแยก เพื่อ map ฟังก์ชันเข้ากับ dataset ของเรา
def preprocess_function(dataset):
dataset['texts'] = process_transformers(dataset['texts'])
return dataset
DATASET = DATASET.map(preprocess_function)
ใช้เวลาร่วมๆ 5นาที⌛️ ในการ preprocess 36,000 บทความ
ตัวอย่างข้อความหลังการจากการผ่านกระบวนการ Data preprocessing

Hey สหาย! อย่าลืม Encode ก่อนเทรนนะ 👾

ด้วยความที่ WangChanBERTa เป็นโมเดล BERT จากอิทธิฤทธิ์ของ Transformer จึงมีตัวละครสำคัญอย่าง Attention และการ Encode มาเกี่ยวข้อง ซึ่งในขั้นตอนนี้เราสามารถทำได้ง่ายๆ ผ่าน การใช้ Tokenizer นั่นเอง 🍁

#สร้าง tokenizer ปริมาณtokenสูงสุดไว้ที่ 416 (เยอะเกินเดี๋ยวRam ระเบิดเป็นโกโก้ครั้น) 
TOKENIZER = AutoTokenizer.from_pretrained(args.model_name, model_max_length=416)
#สร้างฟังชั่น encode เพื่อ map เข้ากับ dataset เหมือนตอนทำ preprocecssing
def encode_function(dataset):
return TOKENIZER(dataset[args.feature_col], truncation=True)
ENCODED_DATASET = DATASET.map(encode_function, batched=True)

สังเกตว่าจะมี input_ids และ attention_mask เพิ่มขึ้นมาใน dataset เสร็จสรรพ 👍

Load Model แบบฉับไว 🤖

แน่นอนว่าทาง Hugging face ก็ได้มี อีกหนึ่งแสงยานุภาพที่เรียกว่า AutoModel มาช่วยเราในส่วนนี้ได้อย่างดีเยี่ยม🤩

ตัวอย่างในที่นี้ หน้าที่ของเราแค่ใส่ parameter เป็น ชื่อโมเดล และ จำนวน labels ที่ต้องการ ทำการรันคำสั่ง เพียงเท่านี้ ท่านก็ได้Modelที่พร้อมใช้งานแบบง่ายๆ รวดเร็วทันใจวัยรุ่นกันเลยทีเดียว 😎

มาดู Argument สำหรับการเทรนซักหน่อย ⚙️

หากยังจำน้อง args 🐱 กันได้ น้องเป็นclass ที่เราสร้างมาเพื่อเก็บ Hyperparameter และ รายละเอียดต่างๆ ของ Model!

ที่นี้แหละเราจะได้ใช้น้องแบบเต็มเม็ดเต็มหน่วยกับการ ส่งต่อ argument สำหรับการเทรนนั่นเอง 👨‍🏫

#ส่วนใหญ่อ้างอิงมาจาก args อีกที
train_args = TrainingArguments(
output_dir = args.output_dir,
evaluation_strategy = "epoch",
learning_rate=args.learning_rate,
per_device_train_batch_size=args.batch_size,
per_device_eval_batch_size=args.batch_size,
num_train_epochs=args.num_train_epochs,
warmup_steps = int(len(encoded_dataset['train']) * args.num_train_epochs // args.batch_size * args.warmup_percent),
weight_decay=args.weight_decay,
load_best_model_at_end=True,
save_total_limit=1,
metric_for_best_model=args.metric_for_best_model,
seed = args.seed)

เอาล่ะ! มาเริ่มต้นเทรนกันจริงๆซักที 👨‍🏫

👨‍🍳ทำการตั้งหม้อแกง ที่ชื่อว่า trainer ขึ้นมาก่อน! ต่อด้วยทำการใส่วัตถุดิบ ที่เราละเมียดละไม จัดเตรียมมาจากกระบวนการก่อนหน้านี้ทั้งหมด ไม่ว่าจะเป็น

  • Model 🤖
  • Argument สำหรับการเทรน ⚙️
  • Dataset ส่วนของการ train และ validate 📃
  • Tokenizer ✂️
trainer = Trainer(model,
train_args,
train_dataset=encoded_dataset['train'],
eval_dataset=encoded_dataset['validation'],
tokenizer=tokenizer,
compute_metrics=classification_metrics)

ต่อจากนั้นเราจะทำการเรียกใช้ เมทธอด train() เพื่อเริ่มต้นการเทรน
เอาล่ะ!! ถ้าพร้อมกันแล้ว! พิมพ์ trainer.train() แล้ว กด shift-enter ได้เลย!
สู่ความเวิ้งว้างอันไกลโพ้น~~~~ 🚀🚀🚀

มาแล้ว Modelที่หนูอยากได้!!! 🧸

นี่เป็นครั้งแรกที่รอมาเนิ่นนาน~~~ 🥺
เทรนเสร็จสิ้นเป็นเรียบร้อย👨‍💻
ใช้เวลาไปทั้งสิ้น….. 3 ชม.ครึ่ง!!! ⌛️ โอ้จอร์จมันหนักหน่วงมาก

เนื่องจากเราใช้ pre-trained model สุดเทพอยู่แล้ว เทรนแค่ 5 Epoch จึงเหลือเฝือ!!

ผลลัพธ์การทดสอบบน Testset 📈

หลังจากลองทดสอบบน testset พบว่า f1-score อยู่ที่ 71% ซึ่งอยุ่ในเกณฑ์ที่พอใช้ได้ แต่สำหรับการนำไปใช้งานจริงนั้น ยังคงต้องพัฒนาประสิทธิภาพให้สูงมากกว่านี้ 🧐

เปรียบเทียบกับ Baseline Model เป็นยังไงบ้าง?

จากการเปรียบเทียบค่า f1-score ปรากฏว่า WangchanBERTa นั้นมงลงไปแบบสวยๆ
ด้วยค่า f1-score 0.71 ในขณะที่ LSTM และ BoW นั้นได้คะแนนอยู่ที่ 0.61 และ 0.64 ตามลำดับ

แผนภูมิแสดงผลการประเมินประสิทธิภาพโมเดล เปรียบเทียบกับ Baseline Model

แต่ช้าก่อน! ถ้าสังเกตแผนภูมิเปรียบเทียบในแต่ละclass ของเรา สังเกตว่ามีบางแวดวงอย่างเช่น ประวัติศาสตร์ที่ค่อนข้างได้คะแนนต่ำ ว่าแต่อืม.. เกิดอะไรขึ้นกันนะ?

พักชมสิ่งที่น่าสนใจสักครู่ครับ

😰ย..ยะ..แย่ แล้วล่ะ ถ้าเราระบุปัญหาไม่ได้ เราก็คงพัฒนาโมเดลต่อไม่ได้แล้ว
ขอโทษนะ Wangchan คุง…. 💔

ยังหรอก มันยังไม่จบเท่านี้ คงถึงเวลาใช้ไม้ตายแล้วสินะ…
นักรบ stack overflow เอ๋ย… จงตื่นขึ้นมา!!!

//ทันใดนั้นเอง นักรบ stack overflow จึงได้ปรากฏตัวขึ้น พร้อมกับข้อความสั้นๆ

“Error Analysis for Machine Learning Classification Models

อ…อะไรนะ!? Error Analysis!!!! ขอบคุณ stack overflow warrior!

ด้วยพลังแห่ง Error Analysis⚠️

เราสามารถวิเคราะห์ข้อผิดพลาด (Error Analysis) ได้โดยการทำ Confusion matrix ซึ่งจะช่วยทำให้เราเห็นว่า โมเดลของเราทายข้อมูลในแต่ละclass ผิดถูกมากน้อยแค่ไหน และ ที่ทายผิดดันทายเป็นclassไหนซะเยอะ

🔎ซึ่งเมื่อเราลองพิจรณาดูแล้ว Domain ที่ทายผิด มักจะเป็นdomain ที่ใกล้เคียง อาทิ ประวัติศาสตร์ กับ สังคมศาสตร์

🤔เราสามารถวิเคราะห์ต่อได้อีก จากการนำบทความที่โมเดลทายผิดออกมาอ่านดู เพื่อวิเคระห์ถึงสาเหตุและปัจจัยที่ทำให้โมเดลทายข้อมูลส่วนนี้ผิด

ตัวอย่างบทความที่โมเดลทายผิด ⚠️

Title: ความร่วมมือของประเทศในภูมิภาคเอเชียตะวันออกเฉียงใต้ ในการก่อตั้งองค์การส่วนภูมิภาค 1945–1985
True Label: ประวัติศาสตร์
Predicted Label:
สังคมศาสตร์

ในปี ค.ศ.1948 คณะกรรมการการต่อต้านการรุกรานได้ก่อตัวขึ้นเพื่อที่จะวางแผนป้องกันประเทศออสเตรเลีย นิวซีแลนด์และมาลายา คณะกรรมการทั้ง 3 ประเทศนี้ ได้ประชุมกัน เพื่อวางแผนการป้องกันทางการทหาร โดยการกำหนดให้มีการฝึกซ้อมทหารเป็นระยะๆ ในปี ค.ศ.1957 ANZAM ถูกพิจารณาให้ทำหน้าที่ช่วยเหลือองค์การ SEATO Southeast Asia Treaty Organization ในส่วนที่เกี่ยวกับนิวซีแลนด์ ออสเตรเลียและมาลายา จึงได้เปลี่ยนชื่อองค์การใหม่เป็น AMDA The AngloMalayan Defense Agreement ในปี ค.ศ.1966 นาย ลี กวน ยู ได้เสนอแนะให้ AMDA ขยายวงความร่วมมือให้กว้างออกไป ดังนั้น ค.ศ.1968 รัฐมนตรีของประเทศออสเตรเลีย มาเลเซีย นิวซีแลนด์ สิงคโปร์และอังกฤษ ได้ประชุมกันที่กัวลาลัมเปอร์ในปี ค.ศ.1968 และที่ลอนดอน ในปี ค.ศ.1969 เพื่อร่วมกันจัดตั้งข้อตกลงร่วมกันระหว่างห้าชาติ The Five Power Defense AgreementFPDA และในปี ค.ศ.1971 ก็ได้ลงนามในสนธิสัญญาการจัดตั้ง

🔎สังเกตได้ว่าถึงแม้นหัวข้อในภาพรวมจะอยู่ในแวดวงประวัติศาสตร์ แต่ในบริบทที่เกิดขึ้นในเนื้อความนั้น ค่อนข้างคาบเกี่ยวไปในแวดวงสังคมศาสตร์ จึงทำให้อาจเกิดความสับสนของโมเดลเกิดขึ้น

Deploy Model ให้โลกรับรู้!

โดยผมได้ ทำหน้าเว็บ และ deploy โมเดล โดยใช้ Streamlit ครับ
โดยหน้าเว้บที่หรูหราแบบนี้แท้จริงทำได้ไม่ยากเลยครับ ด้วยคำสั่งแสนเรียบง่ายที่ทาง Streamlit ออกแบบมาให้เป็นมิตรกับคนที่ไม่ใช่สาย Web Development มากๆ

หน้าตาผลลัพธ์จากการDeploy บน Streamlit Cloud

มาลองทดสอบด้วยข้อความของเราเองกัน!

ลองใส่บทความที่เราสนใจ (ป่าว! บทความที่เราอยากแกล้งโมเดลต่างหาก55 🤣)
ลงไปในช่องกรอกข้อความ แล้วกดรันได้เลย!!! Let’s go!

ผลลัพธ์ออกมาใช้ได้เลย😍 (แหง่สิ! บทความออกจะชัดเจนซะขนาดนั้น!!!)

⚠️ทั้งนี้ขึ้นอยู่กับคลุมเครือ หรือ ความกำกวม ของบทความด้วยนะครับว่ามีการเล่าถึงในประเด็นที่หลากหลายไหม ซึ่งในส่วนนี้เองโมเดลอาจจะทายในส่วนของโดเมนที่ชัดเจนที่สุดในข้อความ ซึ่งบางทีอาจจะไม่ตรงกับแวดวงหลักของบทความนั้นนั่นเอง

ส่งท้าย 🍂

ก็จบไปแล้วนะครับสำหรับการทำ Text Classification สำหรับการแยก domain ในบทความสื่อสิ่งพิมพ์ โดยโปรเจคนี้จะไม่เกิดขึ้นครับ หากขาดการสนับสนุนจากทางโครงการAI Builders นับเป็นอีกหนึ่งโครงการที่มอบความรู้ตลอดจนประสบการณ์ในการสร้างสรรค์ โปรเจค Machine Learning ของผมเอง

และสุดท้ายนี้ขอขอบคุณ🙏 ทุกท่านที่ได้อ่าน Blog ของผมมาจนถึง ณ จุดนี้นะครับ หวังเป็นอย่างยิ่งว่าประสบการณ์ที่ผมได้ถ่ายทอดออกมาในครั้งนี้ จะเกิดประโยชน์กับทุกท่านไม่มากก็น้อยนะครับ หากมีข้อผิดพลาดประการใดต้องขออภัยใน ณ ที่นี้ ครับ

Credit 📌

--

--