สถาบันข้อมูลขนาดใหญ่ (องค์การมหาชน)

การค้นหาตัวแทนเชิงความหมายของข้อความ: Word2Vec Word Embedding, Part II

Jul 26, 2021

ในบทความที่แล้ว เราได้พูดถึงโมเดลที่ใช้ในการทำ word embedding เพื่อแปลงคำในเอกสารให้อยู่ในรูปของเวกเตอร์ที่เป็นตัวแทนความหมายของคำ โดยเราได้พูดถึงการทำงานของโมเดลในตระกูล Word2Vec สองโมเดล ได้แก่ โมเดล CBOW และโมเดล Skip-gram สำหรับบทความนี้ เราจะมาลองดูกันต่อ ว่าเราจะสามารถนำโมเดลทั้งสองตัวนี้มาใช้งานเพื่อสร้างเวกเตอร์ของคำ และของเอกสาร  ได้อย่างไร

รูปที่ 1: โมเดล Continuous Bag of Words (CBOW) และ โมเดล Skip-gram (ที่มารูปภาพ)

การใช้งานผลลัพธ์ของโมเดลในการแปลงเวกเตอร์คำให้เป็นเวกเตอร์เชิงความหมาย

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

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

คำที่มี “ความหมาย” เหมือนหรือใกล้เคียงกันมักจะปรากฏอยู่ในบริบทที่คล้ายกัน

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

(สำหรับผู้สนใจที่มีความรู้พื้นฐานเกี่ยวกับการทำงานของ neural network )

หากพิจารณาโดยละเอียดจะเห็นว่า ทั้งโมเดล CBOW และ Skip-gram นั้นมีลักษณะของโครงสร้างที่คล้ายคลึงกัน ไม่ว่าจะเป็นลักษณะของ input/output ลักษณะของ layer และลักษณะในการฝึกฝนโมเดล โดยในระหว่างการฝึกฝน ค่าจากทุก node ใน input layer (ตัวแทนของคำที่เป็นไปได้ทุกคำ) จะถูกนำเข้าไปคำนวณในทุก node ของ hidden layer ก่อนที่ output จาก hidden layer จะถูกนำไปใช้ทำนายผล ดังนั้นการที่คำต่างกันสองคำจะให้ผลลัพธ์ที่ทำนายคล้ายกันได้นั้น ค่าของ embedded vectors ที่ได้จาก hidden layer ต้องมีค่าคล้ายคลึงกันด้วย  ฉะนั้นค่าของ embedded vector ที่พบใน hidden layer นี้จึงสามารถถูกดึงมาใช้งานเป็นตัวแทนเชิงความหมายของคำต่างๆ ได้ โดยสามารถปรับแก้และใช้งานได้อย่างสะดวกเนื่องจากจำนวน  node ใน hidden layer (ซึ่งก็คือจำนวนมิติของ embedded vector) ของ neural network นั้นสามารถถูกปรับแก้ได้ตามความต้องการของผู้สร้าง

ในหลายการใช้งานนั้น สิ่งที่เราต้องการจากโมเดลตระกูล Word2Vec นั้นไม่ใช่โมเดลการทำนายคำซึ่งถูกใช้ในขั้นตอนการฝึกฝน แต่เป็น “ความสัมพันธ์” (mapping) ระหว่าง input และ ค่าก่อนที่จะนำไปใช้ทำนายผล ซึ่งหมายถึงค่าน้ำหนัก (weight) ของตัวแปร ภายในต่างๆ ที่ใช้สำหรับแปลง word vector จาก input ให้เป็น embedded vector จาก hidden layer สำหรับใช้ทำนายผล โดยหลังจากการฝึกฝนโมเดลแล้วนั้น ค่าน้ำหนักเหล่านี้จะถูกปรับให้เหมาะสมและพร้อมที่จะนำไปใช้งาน

จากที่กล่าวมานั้น เราสามารถดึงเอาความสัมพันธ์นี้มาใช้แปลง word vector ของคำแต่ละคำ ให้เป็น embedded vector ที่มีการฝัง (encode) ความหมายของคำนั้นๆ ไว้ภายในได้ โดยการนำเอาผลลัพธ์จาก hidden layer หลังจากใส่ word vector ของคำที่ดังกล่าวมาใช้แทนคำนั้นโดยตรง (ซึ่งก็คือนำเอา neural network ที่ฝีกฝนแล้วมาใช้โดยทิ้งส่วนที่ใช้ทำนายผลออก)

รูปที่ 2: การคำนวณหาค่าของ embedded vector ของคำจากโมเดล Word2Vec ที่ผ่านการฝึกฝนแล้ว (ที่มารูปภาพ)

โดยเวกเตอร์เหล่านี้สามารถใช้งานเป็นตัวแทนเชิงความหมายของคำแต่ละคำ และสามารถนำไปใช้งานร่วมกับโมเดลทางคณิตศาสตร์อื่น ๆ หรือใช้ในการวิเคราะห์คำนวณต่อได้ครับ

การแปลงข้อความให้อยู่ในรูปแบบของเวกเตอร์ตัวแทนเอกสาร (Document embedding)

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

หมายเหตุ: ในขั้นตอนนี้ เราอาจจะเพิ่มมิติขึ้นอีกมิติหนึ่งสำหรับใช้แทนคำที่ไม่ได้อยู่ใน vocabulary แต่ อาจจะพบได้ในอนาคต โดยปกติแล้วคำเหล่านี้จะถูกเรียกรวมๆ ว่า UNK (unknown)


ตัวอย่างการประยุกต์ใช้งานเวกเตอร์ตัวแทนข้อความ

ต่อไปเราจะมาทดลองเขียนโค้ดเพื่อนำเอาโมเดลตระกูล Word2Vec นี้มาใช้งานกันครับ สำหรับส่วนนี้เราจะนำข้อมูลตัวอย่างข่าวจากคลังข้อความ BEST Corpus ที่ได้ถูกพัฒนาโดย NECTEC มาใช้งานครับ โดยขั้นตอนเบื้องต้นในการอ่าน file และการทำความสะอาดข้อความจากข้อมูลตัวอย่างชุดนี้นั้นจะคล้ายคลึงกับที่เคยได้ยกตัวอย่างในบทความเรื่องการทำ TF-IDF ซึ่งสามารถผู้สนใจสามารถเข้าไปอ่านเพิ่มเติมได้ครับ

หมายเหตุ: เนื่องจาก BEST Corpus ถูกออกแบบมาเพื่อพัฒนาโปรแกรมสำหรับตัดคำ จึงมีได้มีการคั่นคำแต่ละคำไว้ด้วยสัญลักษณ์ “|” อยู่แล้ว ผู้ใช้สามารถตัดคำได้โดยสะดวกผ่านการตรวจหาอักขระดังกล่าว

การจัดเตรียม (Preprocess) ข้อมูล

ในกรณีนี้ เราจะเริ่มต้นด้วยการอ่านไฟล์ข้อความตัวอย่างข่าวเข้ามาและทำความสะอาดข้อมูลให้มีลักษณะตรงกับที่เราต้องการใช้งาน โดยตัดคำ (แยกคำที่ต่างกันออกจากกัน) และลบคำอธิบายข้อมูล (metadata) ของแต่ละบทความ เช่น URL ที่มาของบทความและสัญลักษณ์เพื่อบ่งบอกลักษณะของคำ เช่น <NE></NE>, <AB></AB> และอื่นๆ ออก หลังจากนั้น เราก็จะทำการเตรียมข้อมูลให้เหมาะสมแก่การฝึกฝนโมเดลด้วยกรรมวิธีต่างๆ เช่น การกำจัดเครื่องหมายวรรคตอน กำจัดช่องว่าง (white space) และเปลี่ยนตัวอักษรภาษาอังกฤษให้เป็นตัวพิมพ์เล็ก

# import library ที่จำเป็น
import pandas as pd 
import numpy as np
import string
from gensim.models import Word2Vec
  
# อ่านไฟล์ข่าวที่มีอยู่เข้ามา(มีอยู่ทั้งหมด 96 ไฟล์)
texts = []
for i in range(1,97):
    f = open("BEST/BEST-TrainingSet/news/news_"+"{:05d}.txt".format(i),mode="r", encoding='utf-8')
    texts.append(f.read())
    f.close()
  
# ตัดคำและลบ URL ทิ้ง (ใช้ loop เพื่อให้ code ง่ายแก่การอ่าน)
articles = []
for text in texts:
    ar = []
    for token in text.split("|"): # แบ่งคำด้วยเครื่องหมาย "|"
        if ("www" in token.lower()):
            if(len(ar)>0):
                articles.append(ar)
            ar =[]
        else:
            ar.append(token)
    articles.append(ar)
  
def perform_removal(word):
    # กำจัด marker <NE>, </NE>, <AB>, </AB>
    for pair in (('<NE>', ''), ('</NE>', ''),('<AB>', ''), ('</AB>',''),('<POEM>',''), ('</POEM>','')):
        word =word.replace(*pair)
    # กำจัดช่องว่างก่อน/หลังคำ
    word = word.strip()
    # เปลี่ยนภาษาอังกฤษเป็นตัวอักษรตัวเล็ก
    word = word.lower()
    # กำจัดเครื่องหมายวรรคตอน 
    word = word.translate(str.maketrans('','', string.punctuation))
    # แปลงตัวเลขโดดๆ เป็น tag
    if(word.isdigit()):
        return "<number>"
    else:
        return word 
  
docs = []
for article in articles:
    doc = list(map(perform_removal,article))
    doc = list(filter(lambda word: (word!=''),doc))
    docs.append(doc)

สังเกตได้ว่าขั้นตอนของการเตรียมข้อมูลด้านบนจะแตกต่างจากที่เราทำในบทความเรื่องของ TF-IDF เล็กน้อย โดยในกรณีนี้เราได้ทำการเก็บคำที่ไม่มีนัยสำคัญ (stop words) ไว้และทำการแปลงตัวเลขทั้งหมด ให้เป็นสัญลักษณ์ (token) <number> สาเหตุที่เราเลือกเตรียมข้อมูลในลักษณะนี้ เนื่องจากเราต้องการให้โครงสร้างของบริบทของคำต่างๆ อยู่อย่างครบสมบูรณ์ แต่เนื่องจากตัวเลขนั้นมีความเป็นไปได้ที่หลากหลายมากเราจึงตัดสินใจแทนความเป็นตัวเลขให้เป็นสัญลักษณ์แทน อย่างไรก็ดี ผู้พัฒนาโมเดลอาจเลือกเตรียมข้อมูลในรูปแบบอื่นได้ (เช่น ลบคำและตัวเลขเหล่านี้ หรือแปลงคำ/ตัวเลขให้เป็นสัญลักษณ์ที่มีความหมายมากกว่านี้ เช่น การทำ Name Entity Recognition หรืออื่นๆ) ถ้าหากเห็นว่าสามารถอธิบายบริบทของคำหรือใช้ฝึกฝนแล้วให้ผลที่ดีกว่า

print(docs[1]) 
['ตรวจ', 'แนว', 'รบ', 'อาหาร', 'ปลอด', 'ภัย', 'หลัง', 'ผ่าน', 'วิกฤต', 'ไข้', 'หวัด', 'นก', 'อาหาร', 'ถือ', 'เป็น', 'สิ่ง', 'ที่', 'จำเป็น', 'ต่อ', 'มนุษย์', 'และ', 'อาหาร', 'ที่', 'ปลอด', 'ภัย', 'เท่า', 'นั้น', 'จึง', 'จะ', 'ให้', 'คุณค่า', 'ต่อ', 'ร่างกาย', 'เพื่อ', 'ให้', 'ผู้', 'บริโภค', 'ได้', 'รับ', 'อาหาร', 'ที่', 'ปลอด', 'ภัย', 'จึง', 'ต้อง', 'มี', 'ระบบ', 'ดูแล', 'ควบคุม', 'และ', 'ตรวจสอบ', 'คุณภาพ', 'ทุก', 'ขั้นตอน',
 ...
 ] 

การฝึกฝนโมเดลตระกูล Word2Vec

การฝึกฝนโมเดลตระกูล Word2Vec ในตัวอย่างนี้ เราจะใช้งาน library ที่มีชื่อว่า gensim โดยเราสามารถเรียกใช้คำสั่งเพื่อสร้าง และ train โมเดลได้ดังต่อไปนี้

# สร้างและ train Word2Vec model
model = Word2Vec(sentences=docs, vector_size=100, window=5, min_count=5, workers=4, sg=0, epochs=5) 

โดยค่าต่างๆ ของโมเดลนั้นมีความหมายดังต่อไปนี้

  • sentences เป็นข้อมูลที่เราใช้เพื่อ train โมเดล โดยจะอยู่ในลักษณะของ list ของ list ของ tokens (ในกรณีนี้คือ list ที่มี list หลายอันอยู่ด้านใน และข้อมูลภายใน list ด้านในคือคำแต่ละคำของข้อความ/เอกสาร
    หมายเหตุ: ถึงแม้ว่าชื่อของ input นี้จะเรียกว่า sentences แต่ข้อมูลที่เราเลือกจะใส่ในแต่ละอันในกรณีนี้จะเป็นข้อมูลของเอกสารทั้งเอกสาร การทำเช่นนี้จะช่วยให้เราจะสามารถหาความสัมพันธ์ระหว่างประโยคได้ด้วย
  • size เป็นจำนวนมิติของ embedding layer (ขนาดของ embedded  vector) ที่เราต้องการ
  • window คือระยะทางสูงสุดจากคำที่กำลังใช้ฝึกฝน (จำนวนคำ) ที่นับว่าคำที่เจอเป็นบริบทของคำที่กำลังใช้ฝึกฝนอยู่
  • min_count คือ จำนวนการปรากฏขั้นต่ำของคำที่จะนำมาใช้ในการ train โมเดล (คำที่มีจำนวนครั้งการปรากฏรวมกันในเอกสารทั้งหมดต่ำกว่าค่าที่กำหนดนี้จะไม่ถูกนำมาใช้ train โมเดล เพราะถือว่าปรากฏน้อยเกินกว่าที่จะนำไปใช้ train ได้อย่างมีนัยสำคัญ)
  • worker คือจำนวนของ (computer) threads ที่จะใช้ในการ train
  • sg คือการตั้งค่าว่าจะ train ด้วย Word2Vec ตระกูล Skip-gram หรือไม่ (0 คือ train ด้วย CBOW, 1 คือ train ด้วย Skip-gram โดยปกติแล้ว Skip-gram จะใช้เวลา train ที่นานกว่า)
  • epochs คือการกำหนดจำนวนรอบที่โมเดลจะ train จากข้อมูลที่กำหนดให้

เมื่อรันคำสั่งด้านบนเสร็จสิ้น เราก็จะสามารถนำเอาผลลัพธ์ที่ได้ไปใช้หา embedded vector ได้

อย่างไรก็ดี หนึ่งในข้อได้เปรียบที่สำคัญของการใช้งานโมเดลที่สร้างจาก Neural Network คือการทำ Transfer Learning ซึ่งช่วยให้เราสามารถนำเอาโมเดลที่ผ่านการ train โดยผู้อื่นมา ปรับปรุงหรือ train เพิ่มเติมด้วยข้อมูลของเราเองให้มีประสิทธิภาพสูงขึ้นได้ ดังนั้นในกรณีนี้ แทนที่เราจะ train โมเดลจากจุดเริ่มต้นด้วยคำสั่งด้านบน เราจะทดลองใช้โมเดล pretrained ของ Word2Vec จาก Thai National Corpus ซึ่งเปิดให้สามารถดาวน์โหลดมาใช้งานได้ฟรี

# load pretrained model
model = Word2Vec.load("TNCc5model.bin") 

หลังจากทำการโหลด pretrained โมเดลเข้ามาแล้ว เราสามารถสำรวจได้ว่าการฝึกฝนที่ pretrained โมเดลได้ทำไว้นั้นมี การตั้งค่าอย่างไรบ้างตามตัวอย่างโค้ดด้านล่าง

# see current settings
print(model.__dict__) 
{
 …
  'sg': 0,
  …,
  'window': 5,
  …
  'vector_size': 100,
  'workers': 3,
  'epochs': 5,
  ….
 }
# ตรวจสอบค่า min_count ของโมเดล pretrained
print(model.vocabulary.min_count)
5

เราจะเห็นได้ว่าโมเดลนี้ถูก train มาด้วย CBOW โดยมี embedded vector ขนาด 100 และขนาด window ของบริบทเป็น 5

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

# หา vocabulary ของชุดข้อมูล BEST ทั้งหมดจากเอกสารของเรา
best_vocabs = set()
for doc in docs:
    best_vocabs=best_vocabs.union(set(doc))

# จำนวนคำใน vocabulary ของโมเดล pretrained
print(len(model.wv.vocab))
31078
# update vocabulary ของโมเดล 
model.build_vocab(docs,update=True)

# จำนวนคำใน vocabulary ของหลังจากที่ update ด้วย vocabulary ของข้อมูลของเรา
print(len(model.wv.vocab))
33984

หลังจากทำการปรับแล้ว เราจึงสามารถทำการ train model ต่อด้วย ข้อมูลของเราได้

# train โมเดล
 model.train(sentences=docs,total_examples=len(docs),epochs=300)

หลังจากที่ทำการ train model เสร็จเรียบร้อยแล้ว เราสามารถทดสอบดูได้ว่า  คำที่มีความหมายใกล้เคียงกันนั้น ตัว embedded vector จะมีค่าที่คล้ายคลึงกัน

# ค้นหาคำต่างๆ ที่มีความหมายใกล้เคียงกับคำว่า “หนังสือ” มากที่สุดจากคำใน vocabulary
print(model.wv.most_similar("หนังสือ"))
[
 ('จดหมาย', 0.5849639177322388),
 ('เอกสาร', 0.5030813217163086),
 ('ใบลา', 0.48142826557159424),
 ('ข้อความ', 0.4574117660522461),
…
]

นอกจากนี้เราจะสามารถทำการนำ โมเดลที่เราได้รับมาใช้หาตัวแทนของทั้งเอกสารได้ โดยในที่นี้เราจะใช้วิธีการเฉลี่ยค่าของ embedded vector ของแต่ละคำในเอกสารดังที่ได้อธิบายไว้ในช่วงต้น

def average_embedding(l):
    acc=np.zeros(model.vector_size)
    wv_keys = model.wv.vocab.keys()
    if(len(l)>0):
        count=0
        for w in l:
            # ถ้าหากคำปรากฏในเอกสารทั้งหมดน้อยการ min_count จะไม่ถูก train และไม่มี embedded vector 
            if(w in wv_keys): 
                acc+=model.wv.get_vector(w)
                count+=1
        if count>0:
            acc/=count
    return acc

# คำนวณเวกเตอร์ตัวแทนของเอกสารทั้งหมด
doc_vectors = [average_embedding(doc) for doc in docs]

หมายเหตุ: ถ้าหากเราทราบว่าเราต้องการทำ document embedding ตั้งแต่ต้นแล้ว เราอาจเลือกใช้โมเดลชื่อ Doc2vec ของ  gensim ซึ่งเป็นการสร้างโมเดลเพื่อใช้หา embedding ของเอกสารโดยตรงเลยก็ได้เช่นกัน สำหรับการทำงานโดยละเอียดของ Doc2vec นั้น ผู้อ่านก็สามารถอ่านรายละเอียด ได้จากเอกสารการใช้งาน Doc2vec ของ gensim  หรือจากผลงานตีพิมพ์ที่เกี่ยวข้อง

เมื่อได้ตัวแทนของเอกสารแล้ว เราจะลองนำตัวแทนเอกสารทั้งหมดมาค้นหาระดับความคล้ายคลึงระหว่างกันและกันโดยใช้ cosine similarity เป็นเกณฑ์ในการวัด

from sklearn.metrics.pairwise import cosine_similarity

similarity = cosine_similarity(doc_vectors)

# เรียง index ของเอกสารตามค่าความเหมือน (similarity) ของเอกสารจากมากไปน้อย
# เนื่องจาก argsort จะเรียงค่าจากน้อยไปมากเราจึงนำ -1 มาคูณค่าของระดับความเหมือนแทน
most_similar_docs=np.argsort(-1*similarity)

# deleting index แรก ซึ่งคือเอกสารตัวเอง (เพราะจะมี cosine similarity สูงที่สุด)
most_similar_docs = np.delete(most_similar_docs, 0, axis=1)

เมื่อทำการคำนวณความคล้ายคลึงเสร็จแล้ว เราจะมาลองเลือกเอกสาร (ข่าว) สักอันมาดูกันครับว่าเอกสารที่คล้ายกันที่สุดกับเอกสารนั้นคืออะไร

# เลือกเอกสารมาเพื่อทดลองสัก 1 อัน ในที่นี้เลือกเอกสารหมายเลข 100
article_num = 100

# ค้นหาเอกสารที่คล้ายคลึงกับเอกสารหมายเลข 100 มากที่สุด
sim_article_num = most_similar_docs[article_num][0]

เมื่อเอาแต่ละเอกสารปรับให้อยู่ในรูปที่สามารถอ่านได้ง่าย และลองพิจารณาดู เราจะพบว่าเอกสารหมายเลข 100 นั้นมีเนื้อหาเกี่ยวกับการที่รัฐบาลเจรจาเรื่องปัญหาชายแดนภาคใต้

article1 = ''.join(articles[article_num])
# ลบ tag ทิ้งให้อ่านง่ายขึ้น
for pair in (('<NE>', ''), ('</NE>', ''),('<AB>', ''), ('</AB>',''),('<POEM>',''), ('</POEM>','')):
        article1 =article1.replace(*pair)
print(article1)
นายกฯชี้ไวพจน์ตัวแทนไทยเจรจากลุ่มป่วนชายแดนใต้
บิ๊กแอ้ดเผยไวพจน์เป็นตัวแทนฝ่ายไทยร่วมเจรจามหาเธร์ฯ และกลุ่มก่อความไม่สงบระบุยังไม่ลงพื้นที่จนกว่าจะปรับแนวทางการจัดองค์กรเสร็จด้านอดีต ผอ.สำนักจุฬาราชมนตรีเสนอผู้นำศาสนาร่วมหารือแกนนำผู้ก่อความไม่สงบแนะ"ดาโต๊ะนิเดร์ วาบา"เครดิตสูงเพื่อนสนิทดร.วันการ์เดแกนนำ
(11ต.ค.) เวลา14.15 น.พล.อ.สุรยุทธ์ จุลานนท์นายกรัฐมนตรีให้สัมภาษณ์ภายหลังเป็นประธานฝ่ายฆราวาสโครงการทอดกฐินปลอดเหล้าตามแนวคิดเศรษฐกิจพอเพียงถึงปัญหาความไม่สงบใน3จังหวัดชายแดนภาคใต้กรณีที่นายมหาเธร์ โมฮัมหมัดอดีตนา
... 

และเมื่อพิจารณาเอกสารหมายที่มีระดับความคล้ายคลึงเหมือนกับเอกสารหมายเลข 100 มากที่สุดนั้น ก็พบว่าเป็นข่าวที่มีเนื้อหาเกี่ยวข้องกับการเจรจากับผู้ก่อการร้ายภาคใต้เหมือนกันครับ

เอ็นจีโอคุยโจรใต้หยุดก่อเหตุ14วัน 
อดีต กอส.เผย รัฐส่งคนคุยกับแกนนำโจรใต้แล้วผ่านกลุ่มเอ็นจีโอ ชี้ส่งสัญญาณให้หยุดก่อเหตุ 14 วัน เพื่อตรวจสอบว่าเป็นกลุ่มไหน นักวิชาการสำนักจุฬาราชมนตรี ย้ำศึกษารายละเอียดทางออกรับเงื่อนไขนิรโทษกรรม เขตปกครองพิเศษ และใช้กฎหมายอิสลาม 
เชื่อหลังเจรจาความรุนแรงไม่มีทางยุติอย่างถาวร บัญญัติย้ำมีข้อสรุปเรื่อง ศอ.บต.แล้วแต่ยังไม่พูด คนร้ายวางระเบิดชุดคุ้มครองพระ กลางเมืองสุไหงโก-ลก พระเจ็บเล็กน้อยอีกราย เตรียมตั้งรองปลัดอีก 1 ดูแลความยุติธรรม 3 จังหวัดชายแดนใต้ 

เป็นอย่างไรกันบ้างครับ สำหรับการคำนวณเพื่อหาเวกเตอร์ที่จะใช้เป็นตัวแทนของความหมายของข้อความต่างๆ และตัวอย่างการประยุกต์ใช้งาน บทความนี้อาจจะยาวสักหน่อยแต่ว่าเมื่อเราได้เวกเตอร์ตัวแทนนี้มาแล้ว เรายังสามารถนำเอาไปประยุกต์ใช้งานในด้านอื่นๆ นอกจากที่ได้ยกตัวอย่างไว้ เช่น นำไปใช้แยกแยะประเภทเอกสาร (document classification) หรือนำไปใช้ประมวลผลอื่นๆ ได้คล้ายกับข้อมูลเชิงปริมาณทั่วไปเลยครับเลยครับ สำหรับตัวอย่างการใช้งานในด้านต่างๆ หรือการประยุกต์ของข้อมูลประเภทอื่นๆ ผู้อ่านสามารถติดตามได้ในบทความของ bigdata.go.th ต่อไปครับ


ข้อมูลที่เกี่ยวข้องและข้อมูลเพิ่มเติม

เนื้อหาโดย ปฏิภาณ ประเสริฐสม
ตรวจทานและปรับปรุงโดย พีรดล สามะศิริ

Patipan Prasertsom

Project Manager and Senior Data Scientist at Government Big Data Institute (GBDi)

Peeradon Samasiri, PhD

Project Manager and Senior Data Scientist at Government Big Data Institute (GBDi)