ในบทความที่แล้ว เราได้พูดถึงโมเดลที่ใช้ในการทำ 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)
        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 ต่อไปครับ


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

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

Recommended Posts