ความหมายที่ลึกซึ้งยิ่งขึ้น: การสร้างแบบจำลองหัวข้อใน Python
เผยแพร่แล้ว: 2022-03-11คอมพิวเตอร์และโปรเซสเซอร์ที่จ่ายไฟถูกสร้างขึ้นเพื่อทำงานกับตัวเลข ในทางตรงกันข้าม ภาษาของอีเมลและโพสต์ในโซเชียลมีเดียในชีวิตประจำวันมีโครงสร้างหลวมๆ ที่ไม่เกี่ยวข้องกับการคำนวณ
นั่นคือที่มาของการประมวลผลภาษาธรรมชาติ (NLP) NLP เป็นสาขาหนึ่งของวิทยาการคอมพิวเตอร์ที่ทับซ้อนกับภาษาศาสตร์โดยใช้เทคนิคการคำนวณ (คือปัญญาประดิษฐ์) เพื่อวิเคราะห์ภาษาธรรมชาติและคำพูด การสร้างแบบจำลองหัวข้อมุ่งเน้นไปที่การทำความเข้าใจว่าหัวข้อใดเกี่ยวกับข้อความที่กำหนด การสร้างแบบจำลองหัวข้อช่วยให้นักพัฒนาใช้คุณลักษณะที่เป็นประโยชน์ เช่น การตรวจจับข่าวด่วนบนโซเชียลมีเดีย การแนะนำข้อความส่วนบุคคล การตรวจจับผู้ใช้ปลอม และการกำหนดลักษณะการไหลของข้อมูล
นักพัฒนาสามารถเกลี้ยกล่อมคอมพิวเตอร์ที่เน้นการคำนวณให้เข้าใจการสื่อสารของมนุษย์ในระดับความซับซ้อนเหล่านั้นได้อย่างไร
ถุงคำ
เพื่อตอบคำถามนั้น เราต้องสามารถอธิบายข้อความทางคณิตศาสตร์ได้ เราจะเริ่มบทช่วยสอนเกี่ยวกับการสร้างโมเดลหัวข้อด้วย Python ด้วยวิธีที่ง่ายที่สุด: กระเป๋าคำ
วิธีการนี้แสดงข้อความเป็นชุดคำ ตัวอย่างเช่น ประโยค This is an example สามารถอธิบายเป็นชุดของคำโดยใช้ความถี่ที่คำเหล่านั้นปรากฏขึ้น:
{"an": 1, "example": 1, "is": 1, "this": 1}สังเกตว่าวิธีนี้ละเว้นการเรียงลำดับคำอย่างไร ยกตัวอย่างเหล่านี้:
- “ฉันชอบ Star Wars แต่ฉันไม่ชอบ Harry Potter”
- “ฉันชอบแฮร์รี่ พอตเตอร์ แต่ฉันไม่ชอบสตาร์ วอร์ส”
ความรู้สึกเหล่านี้แสดงด้วยคำเดียวกัน แต่มีความหมายตรงกันข้าม อย่างไรก็ตาม เพื่อวัตถุประสงค์ในการวิเคราะห์หัวข้อของตำรา ความแตกต่างเหล่านี้ไม่สำคัญ ในทั้งสองกรณี เรากำลังพูดถึงรสนิยมของ Harry Potter และ Star Wars โดยไม่คำนึงถึงรสนิยมเหล่านั้น ดังนั้น ลำดับคำจึงไม่มีสาระสำคัญ
เมื่อเรามีข้อความหลายฉบับและพยายามทำความเข้าใจความแตกต่างระหว่างข้อความเหล่านั้น เราจำเป็นต้องมีการแทนค่าทางคณิตศาสตร์สำหรับคลังข้อมูลทั้งหมดของเราที่พิจารณาแต่ละข้อความแยกจากกัน สำหรับสิ่งนี้ เราสามารถใช้เมทริกซ์ ซึ่งแต่ละคอลัมน์แสดงถึงคำหรือคำศัพท์ และแต่ละแถวแสดงถึงข้อความ การแสดงคลังข้อมูลที่เป็นไปได้ประกอบด้วยการสังเกตในแต่ละเซลล์ถึงความถี่ที่ใช้คำที่กำหนด (คอลัมน์) ในข้อความ (แถว)
ในตัวอย่างของเรา คลังข้อมูลประกอบด้วยสองประโยค (แถวเมทริกซ์ของเรา):
["I like Harry Potter", "I like Star Wars"]เราเรียงคำในคลังนี้ตามลำดับที่เราพบ: I , like , Harry , Potter , Star , Wars . ซึ่งสอดคล้องกับคอลัมน์เมทริกซ์ของเรา
ค่าในเมทริกซ์แสดงจำนวนครั้งที่มีการใช้คำที่กำหนดในแต่ละวลี:
[[1,1,1,1,0,0], [1,1,0,0,1,1]] โปรดทราบว่าขนาดของเมทริกซ์ถูกกำหนดโดยการคูณจำนวนข้อความด้วยจำนวนคำต่าง ๆ ที่ปรากฏในข้อความอย่างน้อยหนึ่งข้อความ หลังมักจะมีขนาดใหญ่โดยไม่จำเป็นและสามารถลดลงได้ ตัวอย่างเช่น เมทริกซ์อาจมีสองคอลัมน์สำหรับกริยาผัน เช่น "เล่น" และ "เล่นแล้ว" ไม่ว่าความหมายจะคล้ายกันก็ตาม
แต่คอลัมน์ที่อธิบายแนวคิดใหม่อาจหายไป ตัวอย่างเช่น "ดนตรีคลาสสิก" และ "ดนตรี" ต่างก็มีความหมายเฉพาะตัว แต่เมื่อรวมกันแล้ว - "ดนตรีคลาสสิก" ก็มีความหมายอีกอย่างหนึ่ง
เนื่องจากปัญหาเหล่านี้ จึงจำเป็นต้องประมวลผลข้อความล่วงหน้าเพื่อให้ได้ผลลัพธ์ที่ดี
โมเดลการประมวลผลล่วงหน้าและการจัดกลุ่มหัวข้อ
เพื่อผลลัพธ์ที่ดีที่สุด จำเป็นต้องใช้เทคนิคการประมวลผลล่วงหน้าหลายอย่าง ต่อไปนี้คือบางส่วนที่ใช้บ่อยที่สุด:
- ตัวพิมพ์เล็ก ทำให้คำทั้งหมดเป็นตัวพิมพ์เล็ก ทำให้คำทั้งหมดเป็นตัวพิมพ์เล็ก ความหมายของคำไม่เปลี่ยนแปลงโดยไม่คำนึงถึงตำแหน่งในประโยค
- n -กรัม พิจารณาทุกกลุ่มของ n คำในแถวเป็นคำใหม่ เรียกว่า n-grams ด้วยวิธีนี้ กรณีเช่น "ทำเนียบขาว" จะถูกนำมาพิจารณาและเพิ่มในรายการคำศัพท์
- ต้นกำเนิด ระบุคำนำหน้าและส่วนต่อท้ายของคำเพื่อแยกคำออกจากรากศัพท์ ด้วยวิธีนี้ คำว่า "เล่น" "เล่น" หรือ "ผู้เล่น" จะถูกแทนด้วยคำว่า "เล่น" Stemming อาจมีประโยชน์ในการลดจำนวนคำในรายการคำศัพท์ในขณะที่ยังคงความหมายไว้ แต่การประมวลผลล่วงหน้าจะช้าลงอย่างมาก เนื่องจากต้องใช้กับแต่ละคำในคลังข้อมูล
- หยุดคำ. อย่าพิจารณากลุ่มคำที่ขาดความหมายหรืออรรถประโยชน์ ซึ่งรวมถึงบทความและคำบุพบท แต่อาจรวมถึงคำที่ไม่เป็นประโยชน์สำหรับกรณีศึกษาของเราโดยเฉพาะ เช่น กริยาทั่วไปบางคำ
- ความถี่เทอม–ความถี่เอกสารผกผัน (tf–idf) ใช้สัมประสิทธิ์ของ tf–idf แทนการสังเกตความถี่ของแต่ละคำภายในแต่ละเซลล์ของเมทริกซ์ ประกอบด้วยตัวเลขสองตัวคูณ:
- tf—ความถี่ของคำหรือคำที่กำหนดในข้อความ และ
- idf—ลอการิทึมของจำนวนเอกสารทั้งหมดหารด้วยจำนวนเอกสารที่มีคำที่กำหนด
tf–idf คือการวัดความถี่ที่ใช้คำในคลังข้อมูล เพื่อให้สามารถแบ่งคำออกเป็นกลุ่มๆ ได้ สิ่งสำคัญคือต้องเข้าใจว่าไม่เฉพาะคำที่ปรากฏในแต่ละข้อความเท่านั้น แต่ยังต้องเข้าใจด้วยว่าคำใดปรากฏในข้อความเดียวบ่อยครั้งแต่ไม่ใช่ในคำอื่นๆ เลย
รูปภาพต่อไปนี้แสดงตัวอย่างง่ายๆ ของเทคนิคการประมวลผลล่วงหน้าเหล่านี้ ซึ่งมีการแก้ไขข้อความต้นฉบับของคลังข้อมูลเพื่อสร้างรายการคำที่เกี่ยวข้องและจัดการได้
ตอนนี้เราจะสาธิตวิธีการใช้เทคนิคเหล่านี้ใน Python เมื่อเราให้คลังข้อมูลของเราแสดงทางคณิตศาสตร์แล้ว เราจำเป็นต้องระบุหัวข้อที่กำลังสนทนาโดยใช้อัลกอริธึมการเรียนรู้ของเครื่องที่ไม่ได้รับการดูแล ในกรณีนี้ "unsupervised" หมายความว่าอัลกอริทึมไม่มีป้ายกำกับหัวข้อที่กำหนดไว้ล่วงหน้า เช่น "นิยายวิทยาศาสตร์" เพื่อนำไปใช้กับผลลัพธ์

ในการจัดกลุ่มคลังข้อมูลของเรา เราสามารถเลือกจากอัลกอริธึมได้หลายแบบ รวมถึง non-negative matrix factorization (NMF), sparse major component analysis (sparse PCA) และ latent dirichlet allocation (LDA) เราจะเน้นที่ LDA เนื่องจากมีการใช้กันอย่างแพร่หลายโดยชุมชนวิทยาศาสตร์เนื่องจากมีผลดีในด้านโซเชียลมีเดีย วิทยาศาสตร์การแพทย์ รัฐศาสตร์ และวิศวกรรมซอฟต์แวร์
LDA เป็นแบบจำลองสำหรับการสลายตัวของหัวข้อแบบไม่มีผู้ดูแล: จัดกลุ่มข้อความตามคำที่มีอยู่และความน่าจะเป็นของคำที่อยู่ในหัวข้อใดหัวข้อหนึ่ง อัลกอริธึม LDA ส่งออกการแจกแจงคำในหัวข้อ ด้วยข้อมูลนี้ เราสามารถกำหนดหัวข้อหลักตามคำที่น่าจะเกี่ยวข้องกับพวกเขามากที่สุด เมื่อเราระบุหัวข้อหลักและคำที่เกี่ยวข้องแล้ว เราจะทราบได้ว่าหัวข้อหรือหัวข้อใดที่ใช้กับแต่ละข้อความ
พิจารณาคลังข้อมูลต่อไปนี้ที่ประกอบด้วยประโยคสั้นๆ ห้าประโยค (ทั้งหมดนำมาจากหัวข้อข่าว ของ New York Times ):
corpus = [ "Rafael Nadal Joins Roger Federer in Missing US Open", "Rafael Nadal Is Out of the Australian Open", "Biden Announces Virus Measures", "Biden's Virus Plans Meet Reality", "Where Biden's Virus Plan Stands"]อัลกอริทึมควรระบุหัวข้อที่เกี่ยวข้องกับการเมืองและโคโรนาไวรัสอย่างชัดเจน และอีกหัวข้อหนึ่งที่เกี่ยวข้องกับนาดาลและเทนนิส
การใช้กลยุทธ์ใน Python
เพื่อตรวจหาหัวข้อ เราต้องนำเข้าไลบรารีที่จำเป็น Python มีไลบรารี่ที่มีประโยชน์สำหรับ NLP และการเรียนรู้ของเครื่อง รวมถึง NLTK และ Scikit-learn (sklearn)
from sklearn.feature_extraction.text import CountVectorizer from sklearn.feature_extraction.text import TfidfTransformer from sklearn.decomposition import LatentDirichletAllocation as LDA from nltk.corpus import stopwords การใช้ CountVectorizer() เราสร้างเมทริกซ์ที่แสดงถึงความถี่ของคำของแต่ละข้อความโดยใช้ CountVectorizer() โปรดทราบว่า CountVectorizer อนุญาตให้ประมวลผลล่วงหน้าหากคุณรวมพารามิเตอร์ เช่น stop_words เพื่อรวมคำหยุด ngram_range เพื่อรวม n -grams หรือ lowercase=True เพื่อแปลงอักขระทั้งหมดเป็นตัวพิมพ์เล็ก
count_vect = CountVectorizer(stop_words=stopwords.words('english'), lowercase=True) x_counts = count_vect.fit_transform(corpus) x_counts.todense() matrix([[0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0], [1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1]], dtype=int64) เพื่อกำหนดคำศัพท์ของคลังข้อมูลของเรา เราสามารถใช้แอตทริบิวต์ .get_feature_names() :
count_vect.get_feature_names() ['announces', 'australian', 'biden', 'federer', 'joins', 'measures', 'meet', 'missing', 'nadal', 'open', 'plan', 'plans', 'rafael', 'reality', 'roger', 'stands', 'virus']จากนั้น เราทำการคำนวณ tf–idf ด้วยฟังก์ชัน sklearn:
tfidf_transformer = TfidfTransformer() x_tfidf = tfidf_transformer.fit_transform(x_counts)เพื่อดำเนินการสลาย LDA เราต้องกำหนดจำนวนหัวข้อ ในกรณีง่ายๆ นี้ เรารู้ว่ามีสองหัวข้อหรือ "มิติข้อมูล" แต่ในกรณีทั่วไป นี่คือไฮเปอร์พารามิเตอร์ที่ต้องการการปรับแต่ง ซึ่งสามารถทำได้โดยใช้อัลกอริธึม เช่น การค้นหาแบบสุ่มหรือการค้นหากริด:
dimension = 2 lda = LDA(n_components = dimension) lda_array = lda.fit_transform(x_tfidf) lda_array array([[0.8516198 , 0.1483802 ], [0.82359501, 0.17640499], [0.18072751, 0.81927249], [0.1695452 , 0.8304548 ], [0.18072805, 0.81927195]])LDA เป็นวิธีความน่าจะเป็น ที่นี่ เราจะเห็นความน่าจะเป็นของหัวข้อข่าวแต่ละหัวข้อจากห้าหัวข้อที่เป็นของแต่ละหัวข้อในสองหัวข้อ เราจะเห็นว่าสองข้อความแรกมีความเป็นไปได้สูงที่จะเป็นของหัวข้อแรกและอีกสามข้อความถัดไปในหัวข้อที่สอง ตามที่คาดไว้
สุดท้าย หากเราต้องการทำความเข้าใจว่าสองหัวข้อนี้เกี่ยวกับอะไร เราจะเห็นคำที่สำคัญที่สุดในแต่ละหัวข้อ:
components = [lda.components_[i] for i in range(len(lda.components_))] features = count_vect.get_feature_names() important_words = [sorted(features, key = lambda x: components[j][features.index(x)], reverse = True)[:3] for j in range(len(components))] important_words [['open', 'nadal', 'rafael'], ['virus', 'biden', 'measures']]ตามที่คาดไว้ LDA กำหนดคำที่เกี่ยวข้องกับการแข่งขันเทนนิสและนาดาลอย่างถูกต้องในหัวข้อแรกและคำที่เกี่ยวข้องกับ Biden และไวรัสในหัวข้อที่สอง
การวิเคราะห์ขนาดใหญ่และกรณีการใช้งานจริง
การวิเคราะห์ขนาดใหญ่ของการสร้างแบบจำลองหัวข้อสามารถดูได้ในบทความนี้ ฉันศึกษาหัวข้อข่าวหลักระหว่างการเลือกตั้งประธานาธิบดีสหรัฐฯ ปี 2016 และสังเกตหัวข้อที่สื่อมวลชนบางฉบับ เช่น New York Times และ Fox News รวมอยู่ในการรายงานข่าว เช่น การทุจริตและการย้ายถิ่นฐาน ในบทความนี้ ฉันยังวิเคราะห์ความสัมพันธ์และสาเหตุระหว่างเนื้อหาสื่อมวลชนกับผลการเลือกตั้งด้วย
การสร้างแบบจำลองหัวข้อยังใช้กันอย่างแพร่หลายนอกภาคการศึกษาเพื่อค้นหารูปแบบเฉพาะที่ซ่อนอยู่ในชุดข้อความขนาดใหญ่ ตัวอย่างเช่น สามารถใช้ในระบบแนะนำหรือกำหนดสิ่งที่ลูกค้า/ผู้ใช้กำลังพูดถึงในแบบสำรวจ ในรูปแบบคำติชม หรือบนโซเชียลมีเดีย
บล็อก Toptal Engineering ขอขอบคุณ Juan Manuel Ortiz de Zarate สำหรับการตรวจสอบตัวอย่างโค้ดที่นำเสนอในบทความนี้
การอ่านที่แนะนำเกี่ยวกับการสร้างแบบจำลองหัวข้อ
ปรับปรุงการสร้างแบบจำลองหัวข้อใน Twitter
อัลบานีส เฟเดริโก และเอสเตบัน ฟอยเออร์สไตน์ “การสร้างแบบจำลองหัวข้อที่ได้รับการปรับปรุงใน Twitter ผ่านการรวมกลุ่มของชุมชน” (20 ธันวาคม 2564): arXiv:2201.00690 [cs.IR]
วิเคราะห์ทวิตเตอร์เพื่อสาธารณสุข
พอล ไมเคิล และมาร์ค เดรดซ์ “คุณคือสิ่งที่คุณทวีต: การวิเคราะห์ Twitter เพื่อการสาธารณสุข” 3 สิงหาคม 2564
การจำแนกทิศทางทางการเมืองบน Twitter
โคเฮน ราวีฟ และดีเร็ก รูธส์ “จำแนกการปฐมนิเทศทางการเมือง on Twitter: “ไม่ง่ายเลย!” 3 สิงหาคม 2564
การใช้แบบจำลองหัวข้อเชิงสัมพันธ์เพื่อจับภาพข้อต่อ
Gethers, Malcolm และ Denis Poshyvanyk “การใช้แบบจำลองหัวข้อเชิงสัมพันธ์เพื่อจับการจับคู่ระหว่างคลาสต่างๆ ในระบบซอฟต์แวร์เชิงวัตถุ” 25 ตุลาคม 2553
