ชุดเครื่องมือภาษาธรรมชาติ - คู่มือฉบับย่อ
Natural Language Processing (NLP) คืออะไร?
วิธีการสื่อสารด้วยความช่วยเหลือที่มนุษย์สามารถพูดอ่านเขียนได้คือภาษา กล่าวอีกนัยหนึ่งคือมนุษย์เราสามารถคิดวางแผนตัดสินใจด้วยภาษาธรรมชาติของเรา คำถามใหญ่คือในยุคของปัญญาประดิษฐ์แมชชีนเลิร์นนิงและการเรียนรู้เชิงลึกมนุษย์สามารถสื่อสารด้วยภาษาธรรมชาติกับคอมพิวเตอร์ / เครื่องจักรได้หรือไม่? การพัฒนาแอปพลิเคชัน NLP ถือเป็นความท้าทายอย่างมากสำหรับเราเนื่องจากคอมพิวเตอร์ต้องการข้อมูลที่มีโครงสร้าง แต่ในทางกลับกันคำพูดของมนุษย์ไม่มีโครงสร้างและมักมีความคลุมเครือ
ภาษาธรรมชาติเป็นสาขาย่อยของวิทยาการคอมพิวเตอร์โดยเฉพาะอย่างยิ่งของ AI ซึ่งช่วยให้คอมพิวเตอร์ / เครื่องจักรสามารถเข้าใจประมวลผลและจัดการกับภาษาของมนุษย์ได้ พูดง่ายๆว่า NLP เป็นวิธีหนึ่งของเครื่องจักรในการวิเคราะห์ทำความเข้าใจและรับความหมายจากภาษาธรรมชาติของมนุษย์เช่นภาษาฮินดีอังกฤษฝรั่งเศสดัตช์เป็นต้น
มันทำงานอย่างไร?
ก่อนที่จะดำน้ำลึกลงไปในการทำงานของ NLP เราต้องเข้าใจว่ามนุษย์ใช้ภาษาอย่างไร ทุกๆวันมนุษย์เราใช้คำศัพท์เป็นร้อยเป็นพันคำและมนุษย์คนอื่น ๆ ก็ตีความและตอบตามนั้น มันเป็นการสื่อสารง่ายๆสำหรับมนุษย์ไม่ใช่เหรอ? แต่เรารู้ว่าคำต่างๆมีความลึกซึ้งมากกว่านั้นมากและเราได้บริบทมาจากสิ่งที่เราพูดและวิธีที่เราพูดเสมอ นั่นเป็นเหตุผลที่เราสามารถพูดได้แทนที่จะมุ่งเน้นไปที่การมอดูเลตเสียง NLP จะใช้รูปแบบบริบท
ให้เราเข้าใจด้วยตัวอย่าง -
Man is to woman as king is to what?
We can interpret it easily and answer as follows:
Man relates to king, so woman can relate to queen.
Hence the answer is Queen.
มนุษย์รู้ได้อย่างไรว่าคำว่าอะไรหมายถึงอะไร? คำตอบสำหรับคำถามนี้คือเราเรียนรู้ผ่านประสบการณ์ของเรา แต่เครื่องจักร / คอมพิวเตอร์เรียนรู้เหมือนกันได้อย่างไร?
ให้เราเข้าใจด้วยขั้นตอนง่ายๆดังต่อไปนี้ -
อันดับแรกเราต้องป้อนข้อมูลให้เครื่องจักรเพียงพอเพื่อให้เครื่องจักรสามารถเรียนรู้จากประสบการณ์ได้
จากนั้นเครื่องจะสร้างเวกเตอร์คำโดยใช้อัลกอริทึมการเรียนรู้เชิงลึกจากข้อมูลที่เราป้อนก่อนหน้านี้และจากข้อมูลรอบข้าง
จากนั้นด้วยการดำเนินการเกี่ยวกับพีชคณิตอย่างง่ายบนเวกเตอร์คำเหล่านี้เครื่องจักรจะสามารถให้คำตอบในฐานะมนุษย์ได้
ส่วนประกอบของ NLP
แผนภาพต่อไปนี้แสดงถึงส่วนประกอบของการประมวลผลภาษาธรรมชาติ (NLP) -
การประมวลผลทางสัณฐานวิทยา
การประมวลผลทางสัณฐานวิทยาเป็นองค์ประกอบแรกของ NLP ซึ่งรวมถึงการแบ่งส่วนของการป้อนภาษาออกเป็นชุดของโทเค็นที่สอดคล้องกับย่อหน้าประโยคและคำ ตัวอย่างเช่นคำเช่น“everyday” สามารถแบ่งออกเป็นโทเค็นสองคำย่อยเป็น “every-day”.
การวิเคราะห์ไวยากรณ์
การวิเคราะห์ไวยากรณ์ซึ่งเป็นองค์ประกอบที่สองเป็นองค์ประกอบที่สำคัญที่สุดอย่างหนึ่งของ NLP วัตถุประสงค์ของส่วนประกอบนี้มีดังนี้ -
เพื่อตรวจสอบว่าประโยคนั้นมีรูปแบบที่ดีหรือไม่
เพื่อแยกเป็นโครงสร้างที่แสดงความสัมพันธ์ทางวากยสัมพันธ์ระหว่างคำต่างๆ
เช่นประโยคเช่น “The school goes to the student” จะถูกปฏิเสธโดยตัววิเคราะห์ไวยากรณ์
การวิเคราะห์ความหมาย
การวิเคราะห์ความหมายเป็นองค์ประกอบที่สามของ NLP ซึ่งใช้เพื่อตรวจสอบความหมายของข้อความ รวมถึงการวาดความหมายที่แน่นอนหรือเราสามารถพูดความหมายตามพจนานุกรมจากข้อความ เช่นประโยคเช่น“ ไอศครีมร้อน” จะถูกทิ้งโดยเครื่องวิเคราะห์ความหมาย
การวิเคราะห์เชิงปฏิบัติ
การวิเคราะห์เชิงปฏิบัติเป็นองค์ประกอบที่สี่ของ NLP รวมถึงการปรับวัตถุจริงหรือเหตุการณ์ที่มีอยู่ในแต่ละบริบทด้วยการอ้างอิงวัตถุที่ได้รับจากส่วนประกอบก่อนหน้านี้เช่นการวิเคราะห์ความหมาย เช่นประโยคเช่น“Put the fruits in the basket on the table” สามารถมีการตีความเชิงความหมายได้สองแบบดังนั้นตัววิเคราะห์เชิงปฏิบัติจะเลือกระหว่างความเป็นไปได้ทั้งสองนี้
ตัวอย่างแอปพลิเคชัน NLP
NLP ซึ่งเป็นเทคโนโลยีใหม่เกิดขึ้นจาก AI ในรูปแบบต่างๆที่เราเคยเห็นในปัจจุบัน สำหรับแอปพลิเคชันด้านความรู้ความเข้าใจที่เพิ่มมากขึ้นในปัจจุบันและอนาคตการใช้ NLP ในการสร้างอินเทอร์เฟซแบบโต้ตอบระหว่างมนุษย์และเครื่องจักรจะยังคงเป็นสิ่งสำคัญอันดับต้น ๆ ต่อไปนี้เป็นแอพพลิเคชั่นที่มีประโยชน์มากของ NLP
การแปลด้วยเครื่อง
การแปลด้วยเครื่อง (MT) เป็นหนึ่งในแอปพลิเคชันที่สำคัญที่สุดของการประมวลผลภาษาธรรมชาติ MT เป็นกระบวนการแปลภาษาต้นฉบับหนึ่งหรือข้อความเป็นภาษาอื่น ระบบแปลด้วยเครื่องสามารถเป็นได้ทั้งสองภาษาหรือหลายภาษา
การต่อสู้กับสแปม
เนื่องจากมีอีเมลที่ไม่ต้องการเพิ่มขึ้นอย่างมากตัวกรองสแปมจึงมีความสำคัญเนื่องจากเป็นด่านแรกในการป้องกันปัญหานี้ ด้วยการพิจารณาประเด็นเท็จบวกและลบเท็จเป็นประเด็นหลักฟังก์ชันการทำงานของ NLP สามารถใช้เพื่อพัฒนาระบบกรองสแปมได้
N-gram modeling, Word Stemming และ Bayesian คือโมเดล NLP ที่มีอยู่ซึ่งสามารถใช้สำหรับการกรองสแปมได้
การดึงข้อมูลและการค้นหาเว็บ
เครื่องมือค้นหาส่วนใหญ่เช่น Google, Yahoo, Bing, WolframAlpha เป็นต้นใช้เทคโนโลยีการแปลด้วยเครื่อง (MT) บนโมเดลการเรียนรู้เชิงลึกของ NLP แบบจำลองการเรียนรู้เชิงลึกดังกล่าวช่วยให้อัลกอริทึมสามารถอ่านข้อความบนหน้าเว็บแปลความหมายและแปลเป็นภาษาอื่นได้
สรุปข้อความอัตโนมัติ
การสรุปข้อความอัตโนมัติเป็นเทคนิคที่สร้างการสรุปเอกสารข้อความขนาดยาวที่สั้นและถูกต้อง ดังนั้นจึงช่วยให้เราได้รับข้อมูลที่เกี่ยวข้องโดยใช้เวลาน้อยลง ในยุคดิจิทัลนี้เราต้องการการสรุปข้อความอัตโนมัติอย่างมากเนื่องจากเรามีข้อมูลมากมายทางอินเทอร์เน็ตซึ่งจะไม่หยุดนิ่ง NLP และฟังก์ชันการทำงานมีบทบาทสำคัญในการพัฒนาการสรุปข้อความอัตโนมัติ
การแก้ไขไวยากรณ์
การแก้ไขการสะกดคำและการแก้ไขไวยากรณ์เป็นคุณสมบัติที่มีประโยชน์มากของซอฟต์แวร์ประมวลผลคำเช่น Microsoft Word การประมวลผลภาษาธรรมชาติ (NLP) ใช้กันอย่างแพร่หลายเพื่อจุดประสงค์นี้
ถาม - ตอบ
การตอบคำถามซึ่งเป็นอีกหนึ่งแอปพลิเคชันหลักของการประมวลผลภาษาธรรมชาติ (NLP) มุ่งเน้นไปที่ระบบการสร้างซึ่งจะตอบคำถามที่โพสต์โดยผู้ใช้โดยอัตโนมัติในภาษาธรรมชาติของพวกเขา
การวิเคราะห์ความเชื่อมั่น
การวิเคราะห์ความรู้สึกเป็นหนึ่งในแอปพลิเคชันที่สำคัญอื่น ๆ ของการประมวลผลภาษาธรรมชาติ (NLP) ตามความหมายของชื่อการวิเคราะห์ความรู้สึกใช้เพื่อ -
ระบุความรู้สึกในหลาย ๆ โพสต์และ
ระบุความรู้สึกที่ไม่ได้แสดงออกอย่างชัดเจน
บริษัท อีคอมเมิร์ซออนไลน์เช่น Amazon, ebay ฯลฯ กำลังใช้การวิเคราะห์ความรู้สึกเพื่อระบุความคิดเห็นและความรู้สึกของลูกค้าทางออนไลน์ ซึ่งจะช่วยให้เข้าใจว่าลูกค้าคิดอย่างไรเกี่ยวกับผลิตภัณฑ์และบริการของตน
เครื่องมือพูด
เอ็นจิ้นการพูดเช่น Siri, Google Voice, Alexa สร้างขึ้นบน NLP เพื่อให้เราสามารถสื่อสารกับพวกเขาด้วยภาษาธรรมชาติของเรา
การนำ NLP ไปใช้
ในการสร้างแอปพลิเคชันดังกล่าวข้างต้นเราจำเป็นต้องมีชุดทักษะเฉพาะพร้อมกับความเข้าใจภาษาและเครื่องมือที่ดีในการประมวลผลภาษาอย่างมีประสิทธิภาพ เพื่อให้บรรลุเป้าหมายนี้เรามีเครื่องมือโอเพนซอร์สมากมาย บางส่วนเป็นแบบโอเพ่นซอร์สในขณะที่องค์กรอื่นได้รับการพัฒนาโดยองค์กรเพื่อสร้างแอปพลิเคชัน NLP ของตนเอง ต่อไปนี้เป็นรายการเครื่องมือ NLP -
ชุดเครื่องมือภาษาธรรมชาติ (NLTK)
Mallet
GATE
เปิด NLP
UIMA
Genism
ชุดเครื่องมือสแตนฟอร์ด
เครื่องมือเหล่านี้ส่วนใหญ่เขียนด้วยภาษาจาวา
ชุดเครื่องมือภาษาธรรมชาติ (NLTK)
ในบรรดาเครื่องมือ NLP ที่กล่าวมาข้างต้น NLTK ให้คะแนนสูงมากเมื่อพูดถึงความสะดวกในการใช้งานและคำอธิบายของแนวคิด เส้นโค้งการเรียนรู้ของ Python นั้นเร็วมากและ NLTK เขียนด้วย Python ดังนั้น NLTK จึงมีชุดการเรียนรู้ที่ดีมากเช่นกัน NLTK ได้รวมงานส่วนใหญ่ไว้ด้วยกันเช่น tokenization, stemming, Lemmatization, Punctuation, Character Count และ Word count มีความสง่างามและใช้งานง่าย
ในการติดตั้ง NLTK เราต้องติดตั้ง Python บนคอมพิวเตอร์ของเรา คุณสามารถไปที่ลิงค์www.python.org/downloadsและเลือกเวอร์ชันล่าสุดสำหรับระบบปฏิบัติการของคุณเช่น Windows, Mac และ Linux / Unix สำหรับการกวดวิชาพื้นฐานเกี่ยวกับงูหลามคุณสามารถดูการเชื่อมโยงwww.tutorialspoint.com/python3/index.htm
ตอนนี้เมื่อคุณติดตั้ง Python ในระบบคอมพิวเตอร์แล้วให้เราเข้าใจว่าเราจะติดตั้ง NLTK ได้อย่างไร
การติดตั้ง NLTK
เราสามารถติดตั้ง NLTK บน OS ต่างๆได้ดังนี้ -
บน Windows
ในการติดตั้ง NLTK บน Windows OS ให้ทำตามขั้นตอนด้านล่าง -
ขั้นแรกให้เปิดพรอมต์คำสั่งของ Windows และไปที่ตำแหน่งของไฟล์ pip โฟลเดอร์
จากนั้นป้อนคำสั่งต่อไปนี้เพื่อติดตั้ง NLTK -
pip3 install nltk
ตอนนี้เปิด PythonShell จาก Windows Start Menu และพิมพ์คำสั่งต่อไปนี้เพื่อตรวจสอบการติดตั้งของ NLTK -
Import nltk
หากคุณไม่พบข้อผิดพลาดแสดงว่าคุณติดตั้ง NLTK บน Windows OS ของคุณเรียบร้อยแล้วโดยใช้ Python3
บน Mac / Linux
ในการติดตั้ง NLTK บน Mac / Linux OS ให้เขียนคำสั่งต่อไปนี้ -
sudo pip install -U nltk
หากคุณไม่ได้ติดตั้ง pip บนคอมพิวเตอร์ของคุณให้ปฏิบัติตามคำแนะนำด้านล่างเพื่อติดตั้งครั้งแรก pip -
ขั้นแรกให้อัพเดตดัชนีแพ็คเกจโดยทำตามคำสั่งต่อไปนี้ -
sudo apt update
ตอนนี้พิมพ์คำสั่งต่อไปนี้เพื่อติดตั้ง pip สำหรับ python 3 -
sudo apt install python3-pip
ผ่าน Anaconda
ในการติดตั้ง NLTK ผ่าน Anaconda ให้ทำตามขั้นตอนด้านล่าง -
ขั้นแรกในการติดตั้ง Anaconda ให้ไปที่ลิงค์www.anaconda.com/distribution/#download-sectionจากนั้นเลือกเวอร์ชันของ Python ที่คุณต้องการติดตั้ง
เมื่อคุณมี Anaconda ในระบบคอมพิวเตอร์ของคุณแล้วให้ไปที่พรอมต์คำสั่งและเขียนคำสั่งต่อไปนี้ -
conda install -c anaconda nltk
คุณต้องตรวจสอบผลลัพธ์และป้อน 'ใช่' NLTK จะถูกดาวน์โหลดและติดตั้งในแพ็คเกจ Anaconda ของคุณ
กำลังดาวน์โหลดชุดข้อมูลและแพ็คเกจของ NLTK
ตอนนี้เราติดตั้ง NLTK ในคอมพิวเตอร์แล้ว แต่ในการใช้งานเราจำเป็นต้องดาวน์โหลดชุดข้อมูล (คลังข้อมูล) ที่มีอยู่ในนั้น ชุดข้อมูลที่สำคัญบางส่วนมีอยู่stpwords, guntenberg, framenet_v15 และอื่น ๆ
ด้วยความช่วยเหลือของคำสั่งต่อไปนี้เราสามารถดาวน์โหลดชุดข้อมูล NLTK ทั้งหมด -
import nltk
nltk.download()
คุณจะได้รับหน้าต่างดาวน์โหลด NLTK ต่อไปนี้
ตอนนี้คลิกที่ปุ่มดาวน์โหลดเพื่อดาวน์โหลดชุดข้อมูล
วิธีเรียกใช้สคริปต์ NLTK
ต่อไปนี้เป็นตัวอย่างที่เราใช้อัลกอริทึม Porter Stemmer โดยใช้ PorterStemmerคลาส nltk ด้วยตัวอย่างนี้คุณจะสามารถเข้าใจวิธีเรียกใช้สคริปต์ NLTK
ขั้นแรกเราต้องนำเข้าชุดเครื่องมือภาษาธรรมชาติ (nltk)
import nltk
ตอนนี้นำเข้าไฟล์ PorterStemmer คลาสเพื่อใช้อัลกอริทึม Porter Stemmer
from nltk.stem import PorterStemmer
จากนั้นสร้างอินสแตนซ์ของคลาส Porter Stemmer ดังนี้ -
word_stemmer = PorterStemmer()
ตอนนี้ป้อนคำที่คุณต้องการกำเนิด -
word_stemmer.stem('writing')
เอาต์พุต
'write'
word_stemmer.stem('eating')
เอาต์พุต
'eat'
Tokenizing คืออะไร?
อาจนิยามได้ว่าเป็นกระบวนการแบ่งข้อความออกเป็นส่วนย่อย ๆ เช่นประโยคและคำ ส่วนเล็ก ๆ เหล่านี้เรียกว่าโทเค็น ตัวอย่างเช่นคำเป็นโทเค็นในประโยคและประโยคเป็นโทเค็นในย่อหน้า
ดังที่เราทราบว่า NLP ใช้ในการสร้างแอปพลิเคชันเช่นการวิเคราะห์ความรู้สึกระบบ QA การแปลภาษาแชทบอทอัจฉริยะระบบเสียง ฯลฯ ดังนั้นในการสร้างสิ่งเหล่านี้จึงจำเป็นอย่างยิ่งที่จะต้องเข้าใจรูปแบบในข้อความ โทเค็นที่กล่าวถึงข้างต้นมีประโยชน์มากในการค้นหาและทำความเข้าใจรูปแบบเหล่านี้ เราสามารถพิจารณาโทเค็นเป็นขั้นตอนพื้นฐานสำหรับสูตรอาหารอื่น ๆ เช่นการกำหนดต้นกำเนิดและการทำให้เป็นคำนาม
แพ็คเกจ NLTK
nltk.tokenize เป็นแพ็คเกจที่จัดเตรียมโดยโมดูล NLTK เพื่อให้บรรลุกระบวนการโทเค็น
การแปลงประโยคเป็นคำ
การแยกประโยคออกเป็นคำหรือการสร้างรายการคำจากสตริงเป็นส่วนสำคัญของทุกกิจกรรมการประมวลผลข้อความ ให้เราเข้าใจด้วยความช่วยเหลือของฟังก์ชัน / โมดูลต่างๆที่จัดเตรียมโดยnltk.tokenize แพ็คเกจ
word_tokenize โมดูล
word_tokenizeโมดูลใช้สำหรับการสร้างโทเค็นคำพื้นฐาน ตัวอย่างต่อไปนี้จะใช้โมดูลนี้เพื่อแบ่งประโยคออกเป็นคำ
ตัวอย่าง
import nltk
from nltk.tokenize import word_tokenize
word_tokenize('Tutorialspoint.com provides high quality technical tutorials for free.')
เอาต์พุต
['Tutorialspoint.com', 'provides', 'high', 'quality', 'technical', 'tutorials', 'for', 'free', '.']
TreebankWordTokenizer คลาส
word_tokenize โมดูลที่ใช้ข้างต้นเป็นฟังก์ชัน wrapper ที่เรียกใช้ฟังก์ชัน tokenize () เป็นอินสแตนซ์ของ TreebankWordTokenizerชั้นเรียน. มันจะให้ผลลัพธ์เดียวกันกับที่เราได้รับในขณะที่ใช้โมดูล word_tokenize () เพื่อแยกประโยคออกเป็นคำ ให้เราดูตัวอย่างเดียวกันที่นำไปใช้ข้างต้น -
ตัวอย่าง
ขั้นแรกเราต้องนำเข้าชุดเครื่องมือภาษาธรรมชาติ (nltk)
import nltk
ตอนนี้นำเข้าไฟล์ TreebankWordTokenizer คลาสเพื่อใช้อัลกอริทึม word tokenizer -
from nltk.tokenize import TreebankWordTokenizer
จากนั้นสร้างอินสแตนซ์ของคลาส TreebankWordTokenizer ดังนี้ -
Tokenizer_wrd = TreebankWordTokenizer()
ตอนนี้ป้อนประโยคที่คุณต้องการแปลงเป็นโทเค็น -
Tokenizer_wrd.tokenize(
'Tutorialspoint.com provides high quality technical tutorials for free.'
)
เอาต์พุต
[
'Tutorialspoint.com', 'provides', 'high', 'quality',
'technical', 'tutorials', 'for', 'free', '.'
]
ตัวอย่างการใช้งานที่สมบูรณ์
ให้เราดูตัวอย่างการใช้งานที่สมบูรณ์ด้านล่าง
import nltk
from nltk.tokenize import TreebankWordTokenizer
tokenizer_wrd = TreebankWordTokenizer()
tokenizer_wrd.tokenize('Tutorialspoint.com provides high quality technical
tutorials for free.')
เอาต์พุต
[
'Tutorialspoint.com', 'provides', 'high', 'quality',
'technical', 'tutorials','for', 'free', '.'
]
หลักการที่สำคัญที่สุดของโทเค็นไนเซอร์คือการแยกการหดตัว ตัวอย่างเช่นถ้าเราใช้ word_tokenize () โมดูลเพื่อจุดประสงค์นี้จะให้ผลลัพธ์ดังนี้ -
ตัวอย่าง
import nltk
from nltk.tokenize import word_tokenize
word_tokenize('won’t')
เอาต์พุต
['wo', "n't"]]
การประชุมแบบนี้โดย TreebankWordTokenizerเป็นที่ยอมรับไม่ได้ นั่นเป็นเหตุผลที่เรามี tokenizers คำสองทางเลือก ได้แก่PunktWordTokenizer และ WordPunctTokenizer.
คลาส WordPunktTokenizer
โทเค็นคำอื่นที่แยกเครื่องหมายวรรคตอนทั้งหมดออกเป็นโทเค็นแยกกัน ให้เราเข้าใจด้วยตัวอย่างง่ายๆดังต่อไปนี้ -
ตัวอย่าง
from nltk.tokenize import WordPunctTokenizer
tokenizer = WordPunctTokenizer()
tokenizer.tokenize(" I can't allow you to go home early")
เอาต์พุต
['I', 'can', "'", 't', 'allow', 'you', 'to', 'go', 'home', 'early']
การแปลงข้อความเป็นประโยค
ในส่วนนี้เราจะแยกข้อความ / ย่อหน้าออกเป็นประโยค NLTK ให้sent_tokenize โมดูลสำหรับวัตถุประสงค์นี้
ทำไมจึงจำเป็น?
คำถามที่ชัดเจนที่อยู่ในใจเราก็คือเมื่อเรามี word tokenizer แล้วทำไมเราถึงต้องใช้ tokenizer ประโยคหรือทำไมเราต้อง tokenize ข้อความเป็นประโยค สมมติว่าเราต้องนับจำนวนคำเฉลี่ยในประโยคเราจะทำได้อย่างไร? เพื่อให้งานนี้สำเร็จเราต้องใช้ทั้งการสร้างประโยคและโทเค็นคำ
ให้เราเข้าใจความแตกต่างระหว่างโทเค็นประโยคและคำด้วยความช่วยเหลือของตัวอย่างง่ายๆดังต่อไปนี้ -
ตัวอย่าง
import nltk
from nltk.tokenize import sent_tokenize
text = "Let us understand the difference between sentence & word tokenizer.
It is going to be a simple example."
sent_tokenize(text)
เอาต์พุต
[
"Let us understand the difference between sentence & word tokenizer.",
'It is going to be a simple example.'
]
โทเค็นประโยคโดยใช้นิพจน์ทั่วไป
หากคุณรู้สึกว่าเอาต์พุตของโทเค็นคำไม่เป็นที่ยอมรับและต้องการควบคุมวิธีการโทเค็นข้อความโดยสมบูรณ์เรามีนิพจน์ทั่วไปที่สามารถใช้ได้ในขณะที่ทำโทเค็นประโยค NLTK ให้RegexpTokenizer ชั้นเรียนเพื่อให้บรรลุสิ่งนี้
ให้เราเข้าใจแนวคิดด้วยความช่วยเหลือจากสองตัวอย่างด้านล่าง
ในตัวอย่างแรกเราจะใช้นิพจน์ทั่วไปสำหรับการจับคู่โทเค็นที่เป็นตัวเลขและตัวอักษรบวกกับเครื่องหมายคำพูดเดี่ยวเพื่อที่เราจะไม่แยกการหดตัวเช่น “won’t”.
ตัวอย่าง 1
import nltk
from nltk.tokenize import RegexpTokenizer
tokenizer = RegexpTokenizer("[\w']+")
tokenizer.tokenize("won't is a contraction.")
tokenizer.tokenize("can't is a contraction.")
เอาต์พุต
["won't", 'is', 'a', 'contraction']
["can't", 'is', 'a', 'contraction']
ในตัวอย่างแรกเราจะใช้นิพจน์ทั่วไปเพื่อสร้างโทเค็นบนช่องว่าง
ตัวอย่าง 2
import nltk
from nltk.tokenize import RegexpTokenizer
tokenizer = RegexpTokenizer('/s+' , gaps = True)
tokenizer.tokenize("won't is a contraction.")
เอาต์พุต
["won't", 'is', 'a', 'contraction']
จากผลลัพธ์ด้านบนเราจะเห็นว่าเครื่องหมายวรรคตอนยังคงอยู่ในโทเค็น พารามิเตอร์ช่องว่าง = True หมายถึงรูปแบบกำลังจะระบุช่องว่างที่จะใช้โทเค็น ในทางกลับกันถ้าเราจะใช้พารามิเตอร์ gaps = False รูปแบบจะถูกใช้เพื่อระบุโทเค็นซึ่งสามารถเห็นได้ในตัวอย่างต่อไปนี้ -
import nltk
from nltk.tokenize import RegexpTokenizer
tokenizer = RegexpTokenizer('/s+' , gaps = False)
tokenizer.tokenize("won't is a contraction.")
เอาต์พุต
[ ]
มันจะทำให้เราได้ผลลัพธ์ที่ว่างเปล่า
ทำไมต้องฝึกโทเค็นเซอร์ประโยคของตัวเอง?
นี่เป็นคำถามที่สำคัญมากว่าถ้าเรามี tokenizer ประโยคเริ่มต้นของ NLTK แล้วทำไมเราต้องฝึกโทเค็นเซอร์ประโยค คำตอบสำหรับคำถามนี้อยู่ที่คุณภาพของโทเค็นไนเซอร์ประโยคเริ่มต้นของ NLTK โทเค็นไนเซอร์เริ่มต้นของ NLTK นั้นเป็นโทเค็นไนเซอร์ที่ใช้งานทั่วไป แม้ว่าจะใช้งานได้ดี แต่อาจไม่ใช่ทางเลือกที่ดีสำหรับข้อความที่ไม่เป็นมาตรฐานบางทีอาจเป็นข้อความของเราหรือสำหรับข้อความที่มีการจัดรูปแบบเฉพาะ ในการสร้างโทเค็นข้อความดังกล่าวและได้ผลลัพธ์ที่ดีที่สุดเราควรฝึกโทเค็นประโยคของเราเอง
ตัวอย่างการใช้งาน
สำหรับตัวอย่างนี้เราจะใช้ webtext corpus ไฟล์ข้อความที่เราจะใช้จากคลังข้อมูลนี้มีข้อความที่จัดรูปแบบเป็นกล่องโต้ตอบที่แสดงด้านล่าง -
Guy: How old are you?
Hipster girl: You know, I never answer that question. Because to me, it's about
how mature you are, you know? I mean, a fourteen year old could be more mature
than a twenty-five year old, right? I'm sorry, I just never answer that question.
Guy: But, uh, you're older than eighteen, right?
Hipster girl: Oh, yeah.
เราได้บันทึกไฟล์ข้อความนี้ด้วยชื่อ training_tokenizer NLTK มีคลาสชื่อPunktSentenceTokenizerด้วยความช่วยเหลือซึ่งเราสามารถฝึกอบรมข้อความดิบเพื่อสร้างโทเค็นประโยคที่กำหนดเองได้ เราสามารถรับข้อความดิบได้โดยการอ่านในไฟล์หรือจากคลังข้อมูล NLTK โดยใช้ไฟล์raw() วิธี.
ให้เราดูตัวอย่างด้านล่างเพื่อรับข้อมูลเชิงลึกมากขึ้น -
ก่อนอื่นให้นำเข้า PunktSentenceTokenizer คลาสจาก nltk.tokenize แพ็คเกจ -
from nltk.tokenize import PunktSentenceTokenizer
ตอนนี้นำเข้า webtext คลังข้อมูลจาก nltk.corpus แพ็คเกจ
from nltk.corpus import webtext
ถัดไปโดยใช้ raw() วิธีรับข้อความดิบจาก training_tokenizer.txt ไฟล์ดังนี้ -
text = webtext.raw('C://Users/Leekha/training_tokenizer.txt')
ตอนนี้สร้างอินสแตนซ์ของ PunktSentenceTokenizer และพิมพ์ประโยคโทเค็นจากไฟล์ข้อความดังนี้ -
sent_tokenizer = PunktSentenceTokenizer(text)
sents_1 = sent_tokenizer.tokenize(text)
print(sents_1[0])
เอาต์พุต
White guy: So, do you have any plans for this evening?
print(sents_1[1])
Output:
Asian girl: Yeah, being angry!
print(sents_1[670])
Output:
Guy: A hundred bucks?
print(sents_1[675])
Output:
Girl: But you already have a Big Mac...
ตัวอย่างการใช้งานที่สมบูรณ์
from nltk.tokenize import PunktSentenceTokenizer
from nltk.corpus import webtext
text = webtext.raw('C://Users/Leekha/training_tokenizer.txt')
sent_tokenizer = PunktSentenceTokenizer(text)
sents_1 = sent_tokenizer.tokenize(text)
print(sents_1[0])
เอาต์พุต
White guy: So, do you have any plans for this evening?
เพื่อให้เข้าใจความแตกต่างระหว่างโทเค็นเริ่มต้นประโยคของ NLTK กับโทเค็นเซอร์ประโยคที่ได้รับการฝึกฝนของเราเองให้เราโทเค็นไฟล์เดียวกันด้วยโทเค็นเริ่มต้นประโยคเช่น sent_tokenize ()
from nltk.tokenize import sent_tokenize
from nltk.corpus import webtext
text = webtext.raw('C://Users/Leekha/training_tokenizer.txt')
sents_2 = sent_tokenize(text)
print(sents_2[0])
Output:
White guy: So, do you have any plans for this evening?
print(sents_2[675])
Output:
Hobo: Y'know what I'd do if I was rich?
ด้วยความช่วยเหลือของความแตกต่างในผลลัพธ์เราสามารถเข้าใจแนวคิดว่าเหตุใดจึงมีประโยชน์ในการฝึกโทเค็นเซอร์ประโยคของเราเอง
คำหยุดคืออะไร?
คำทั่วไปบางคำที่มีอยู่ในข้อความ แต่ไม่มีส่วนในความหมายของประโยค คำดังกล่าวไม่สำคัญเลยสำหรับวัตถุประสงค์ในการดึงข้อมูลหรือการประมวลผลภาษาธรรมชาติ คำหยุดที่พบบ่อยที่สุดคือ "the" และ "a"
คลังข้อมูลคำหยุด NLTK
อันที่จริงชุดเครื่องมือภาษาธรรมชาติมาพร้อมกับคลังคำหยุดที่มีรายการคำสำหรับหลายภาษา ให้เราเข้าใจการใช้งานด้วยความช่วยเหลือของตัวอย่างต่อไปนี้ -
ขั้นแรกให้นำเข้าคำหยุด copus จากแพ็คเกจnltk.corpus -
from nltk.corpus import stopwords
ตอนนี้เราจะใช้คำหยุดจากภาษาอังกฤษ
english_stops = set(stopwords.words('english'))
words = ['I', 'am', 'a', 'writer']
[word for word in words if word not in english_stops]
เอาต์พุต
['I', 'writer']
ตัวอย่างการใช้งานที่สมบูรณ์
from nltk.corpus import stopwords
english_stops = set(stopwords.words('english'))
words = ['I', 'am', 'a', 'writer']
[word for word in words if word not in english_stops]
เอาต์พุต
['I', 'writer']
ค้นหารายการภาษาที่รองรับทั้งหมด
ด้วยความช่วยเหลือของการทำตามสคริปต์ Python เรายังสามารถค้นหารายการภาษาทั้งหมดที่สนับสนุนโดยคลังคำหยุด NLTK -
from nltk.corpus import stopwords
stopwords.fileids()
เอาต์พุต
[
'arabic', 'azerbaijani', 'danish', 'dutch', 'english', 'finnish', 'french',
'german', 'greek', 'hungarian', 'indonesian', 'italian', 'kazakh', 'nepali',
'norwegian', 'portuguese', 'romanian', 'russian', 'slovene', 'spanish',
'swedish', 'tajik', 'turkish'
]
Wordnet คืออะไร?
Wordnet เป็นฐานข้อมูลคำศัพท์ภาษาอังกฤษขนาดใหญ่ซึ่งสร้างขึ้นโดย Princeton เป็นส่วนหนึ่งของคลังข้อมูล NLTK คำนามคำกริยาคำคุณศัพท์และคำวิเศษณ์ทั้งหมดถูกจัดกลุ่มออกเป็นชุดของ synsets นั่นคือคำพ้องความหมายทางปัญญา synsets แต่ละชุดแสดงความหมายที่แตกต่างกัน ต่อไปนี้เป็นกรณีการใช้งานบางส่วนของ Wordnet -
- สามารถใช้เพื่อค้นหาคำจำกัดความของคำ
- เราสามารถค้นหาคำพ้องความหมายและคำตรงข้ามของคำ
- สามารถสำรวจความสัมพันธ์ของคำและความคล้ายคลึงกันได้โดยใช้ Wordnet
- การเปลี่ยนความรู้สึกของคำสำหรับคำเหล่านั้นที่มีการใช้งานและคำจำกัดความที่หลากหลาย
วิธีการนำเข้า Wordnet
Wordnet สามารถนำเข้าได้ด้วยความช่วยเหลือของคำสั่งต่อไปนี้ -
from nltk.corpus import wordnet
สำหรับคำสั่งที่กะทัดรัดมากขึ้นให้ใช้สิ่งต่อไปนี้ -
from nltk.corpus import wordnet as wn
อินสแตนซ์ Synset
Synset คือการจัดกลุ่มคำพ้องความหมายที่แสดงแนวคิดเดียวกัน เมื่อคุณใช้ Wordnet เพื่อค้นหาคำคุณจะได้รับรายการอินสแตนซ์ Synset
wordnet.synsets (คำ)
ในการรับรายการ Synsets เราสามารถค้นหาคำใดก็ได้ใน Wordnet โดยใช้ wordnet.synsets(word). ตัวอย่างเช่นในสูตร Python ถัดไปเราจะค้นหา Synset สำหรับ 'สุนัข' พร้อมกับคุณสมบัติและวิธีการบางอย่างของ Synset -
ตัวอย่าง
ขั้นแรกให้นำเข้า wordnet ดังนี้ -
from nltk.corpus import wordnet as wn
ตอนนี้ระบุคำที่คุณต้องการค้นหา Synset สำหรับ -
syn = wn.synsets('dog')[0]
ที่นี่เราใช้เมธอด name () เพื่อรับชื่อเฉพาะสำหรับ synset ซึ่งสามารถใช้เพื่อรับ Synset ได้โดยตรง -
syn.name()
Output:
'dog.n.01'
ต่อไปเราจะใช้วิธีการ definition () ซึ่งจะให้คำจำกัดความของคำว่า -
syn.definition()
Output:
'a member of the genus Canis (probably descended from the common wolf) that has
been domesticated by man since prehistoric times; occurs in many breeds'
อีกวิธีหนึ่งคือตัวอย่าง () ซึ่งจะให้ตัวอย่างที่เกี่ยวข้องกับคำว่า -
syn.examples()
Output:
['the dog barked all night']
ตัวอย่างการใช้งานที่สมบูรณ์
from nltk.corpus import wordnet as wn
syn = wn.synsets('dog')[0]
syn.name()
syn.definition()
syn.examples()
รับ Hypernyms
Synsets จัดอยู่ในโครงสร้างมรดกเช่นเดียวกับโครงสร้างที่ Hypernyms แสดงถึงคำที่เป็นนามธรรมมากขึ้นในขณะที่ Hyponymsแสดงถึงคำที่เฉพาะเจาะจงมากขึ้น สิ่งที่สำคัญอย่างหนึ่งคือต้นไม้นี้สามารถโยงไปถึงรูตไฮเปอร์นีม ให้เราเข้าใจแนวคิดด้วยความช่วยเหลือของตัวอย่างต่อไปนี้ -
from nltk.corpus import wordnet as wn
syn = wn.synsets('dog')[0]
syn.hypernyms()
เอาต์พุต
[Synset('canine.n.02'), Synset('domestic_animal.n.01')]
ที่นี่เราจะเห็นว่าสุนัขและสัตว์ในบ้านเป็นไฮเปอร์ไนมส์ของ 'สุนัข'
ตอนนี้เราสามารถหาคำนามของ 'dog' ได้ดังนี้ -
syn.hypernyms()[0].hyponyms()
เอาต์พุต
[
Synset('bitch.n.04'),
Synset('dog.n.01'),
Synset('fox.n.01'),
Synset('hyena.n.01'),
Synset('jackal.n.01'),
Synset('wild_dog.n.01'),
Synset('wolf.n.01')
]
จากผลลัพธ์ข้างต้นเราจะเห็นว่า 'dog' เป็นเพียงหนึ่งในหลาย ๆ คำพ้องความหมายของ 'domestic_animals'
ในการค้นหารากของสิ่งเหล่านี้เราสามารถใช้คำสั่งต่อไปนี้ -
syn.root_hypernyms()
เอาต์พุต
[Synset('entity.n.01')]
จากผลลัพธ์ด้านบนเราจะเห็นว่ามันมีเพียงรูทเดียว
ตัวอย่างการใช้งานที่สมบูรณ์
from nltk.corpus import wordnet as wn
syn = wn.synsets('dog')[0]
syn.hypernyms()
syn.hypernyms()[0].hyponyms()
syn.root_hypernyms()
เอาต์พุต
[Synset('entity.n.01')]
Lemmas ใน Wordnet
ในภาษาศาสตร์รูปแบบที่บัญญัติหรือรูปแบบทางสัณฐานวิทยาของคำเรียกว่าคำนาม หากต้องการค้นหาคำพ้องความหมายและคำตรงข้ามของคำเรายังสามารถค้นหาคำศัพท์ใน WordNet ให้เราดูว่า
การค้นหาคำพ้องความหมาย
โดยใช้เมธอด lemma () เราสามารถค้นหาจำนวนคำพ้องความหมายของ Synset ให้เราใช้วิธีนี้กับ synset 'dog' -
ตัวอย่าง
from nltk.corpus import wordnet as wn
syn = wn.synsets('dog')[0]
lemmas = syn.lemmas()
len(lemmas)
เอาต์พุต
3
ผลลัพธ์ข้างต้นแสดงให้เห็นว่า 'dog' มีคำศัพท์สามตัว
ได้รับชื่อของ lemma ตัวแรกดังนี้ -
lemmas[0].name()
Output:
'dog'
ได้รับชื่อของ lemma ที่สองดังนี้ -
lemmas[1].name()
Output:
'domestic_dog'
ได้รับชื่อของคำศัพท์ที่สามดังนี้ -
lemmas[2].name()
Output:
'Canis_familiaris'
จริงๆแล้ว Synset หมายถึงกลุ่มของคำศัพท์ที่มีความหมายคล้าย ๆ กันในขณะที่ lemma แสดงถึงรูปแบบคำที่แตกต่างกัน
การค้นหาคำตรงข้าม
ใน WordNet คำนามบางตัวมีคำตรงข้ามด้วย ตัวอย่างเช่นคำว่า 'good' มีคำพ้องความหมายทั้งหมด 27 คำในจำนวนนี้มีคำพ้องความหมาย 5 คำที่มีคำตรงข้าม ให้เราหาคำตรงข้าม (เมื่อคำว่า 'ดี' ใช้เป็นคำนามและเมื่อคำว่า 'ดี' ใช้เป็นคำคุณศัพท์)
ตัวอย่าง 1
from nltk.corpus import wordnet as wn
syn1 = wn.synset('good.n.02')
antonym1 = syn1.lemmas()[0].antonyms()[0]
antonym1.name()
เอาต์พุต
'evil'
antonym1.synset().definition()
เอาต์พุต
'the quality of being morally wrong in principle or practice'
ตัวอย่างข้างต้นแสดงให้เห็นว่าคำว่า 'ดี' เมื่อใช้เป็นคำนามมีคำตรงข้ามตัวแรก 'evil'
ตัวอย่าง 2
from nltk.corpus import wordnet as wn
syn2 = wn.synset('good.a.01')
antonym2 = syn2.lemmas()[0].antonyms()[0]
antonym2.name()
เอาต์พุต
'bad'
antonym2.synset().definition()
เอาต์พุต
'having undesirable or negative qualities’
ตัวอย่างข้างต้นแสดงให้เห็นว่าคำว่า 'ดี' เมื่อใช้เป็นคำคุณศัพท์มีคำตรงข้ามตัวแรก 'bad'
Stemming คืออะไร?
Stemming เป็นเทคนิคที่ใช้ในการแยกรูปแบบฐานของคำโดยการลบคำติดออกจากคำเหล่านั้น มันก็เหมือนกับการตัดกิ่งก้านของต้นไม้ไปที่ลำต้นของมัน ตัวอย่างเช่นก้านของคำeating, eats, eaten คือ eat.
เครื่องมือค้นหาใช้ Stemming เพื่อสร้างดัชนีคำ นั่นเป็นเหตุผลที่แทนที่จะจัดเก็บคำทุกรูปแบบเครื่องมือค้นหาสามารถจัดเก็บเฉพาะลำต้นได้ ด้วยวิธีนี้ Stemming จะลดขนาดของดัชนีและเพิ่มความแม่นยำในการดึงข้อมูล
อัลกอริธึม Stemming ต่างๆ
ใน NLTK stemmerI, ที่มี stem()วิธีการอินเทอร์เฟซมีต้นกำเนิดทั้งหมดที่เราจะกล่าวถึงต่อไป ให้เราเข้าใจด้วยแผนภาพต่อไปนี้
ขั้นตอนวิธีการสกัดกั้น Porter
เป็นหนึ่งในอัลกอริธึมการแยกคำที่ใช้กันทั่วไปซึ่งได้รับการออกแบบมาเพื่อลบและแทนที่คำต่อท้ายของคำภาษาอังกฤษที่รู้จักกันดี
ชั้น PorterStemmer
NLTK มี PorterStemmerคลาสด้วยความช่วยเหลือซึ่งเราสามารถใช้อัลกอริธึม Porter Stemmer สำหรับคำที่เราต้องการเรียกได้อย่างง่ายดาย คลาสนี้รู้จักรูปแบบคำปกติและคำต่อท้ายหลายแบบด้วยความช่วยเหลือซึ่งสามารถเปลี่ยนคำที่ป้อนให้เป็นคำสุดท้ายได้ ลำต้นที่เกิดมักเป็นคำสั้น ๆ ที่มีความหมายรากเดียวกัน ให้เราดูตัวอย่าง -
ขั้นแรกเราต้องนำเข้าชุดเครื่องมือภาษาธรรมชาติ (nltk)
import nltk
ตอนนี้นำเข้าไฟล์ PorterStemmer คลาสเพื่อใช้อัลกอริทึม Porter Stemmer
from nltk.stem import PorterStemmer
จากนั้นสร้างอินสแตนซ์ของคลาส Porter Stemmer ดังนี้ -
word_stemmer = PorterStemmer()
ตอนนี้ป้อนคำที่คุณต้องการกำเนิด
word_stemmer.stem('writing')
เอาต์พุต
'write'
word_stemmer.stem('eating')
เอาต์พุต
'eat'
ตัวอย่างการใช้งานที่สมบูรณ์
import nltk
from nltk.stem import PorterStemmer
word_stemmer = PorterStemmer()
word_stemmer.stem('writing')
เอาต์พุต
'write'
อัลกอริทึมของ Lancaster Stemming
ได้รับการพัฒนาที่มหาวิทยาลัย Lancaster และเป็นอีกหนึ่งอัลกอริธึมการหยุดชะงักที่พบบ่อยมาก
คลาส LancasterStemmer
NLTK มี LancasterStemmerคลาสด้วยความช่วยเหลือซึ่งเราสามารถใช้อัลกอริทึม Lancaster Stemmer สำหรับคำที่เราต้องการเรียกได้อย่างง่ายดาย ให้เราดูตัวอย่าง -
ขั้นแรกเราต้องนำเข้าชุดเครื่องมือภาษาธรรมชาติ (nltk)
import nltk
ตอนนี้นำเข้าไฟล์ LancasterStemmer คลาสเพื่อใช้อัลกอริทึม Lancaster Stemmer
from nltk.stem import LancasterStemmer
จากนั้นสร้างอินสแตนซ์ของ LancasterStemmer ชั้นเรียนดังนี้ -
Lanc_stemmer = LancasterStemmer()
ตอนนี้ป้อนคำที่คุณต้องการกำเนิด
Lanc_stemmer.stem('eats')
เอาต์พุต
'eat'
ตัวอย่างการใช้งานที่สมบูรณ์
import nltk
from nltk.stem import LancatserStemmer
Lanc_stemmer = LancasterStemmer()
Lanc_stemmer.stem('eats')
เอาต์พุต
'eat'
อัลกอริธึมการหยุดนิพจน์ทั่วไป
ด้วยความช่วยเหลือของอัลกอริธึมการตัดคำนี้เราสามารถสร้างสเต็มเมอร์ของเราเองได้
คลาส RegexpStemmer
NLTK มี RegexpStemmerคลาสด้วยความช่วยเหลือซึ่งเราสามารถใช้อัลกอริทึม Regular Expression Stemmer ได้อย่างง่ายดาย โดยทั่วไปจะใช้นิพจน์ทั่วไปเดียวและลบคำนำหน้าหรือคำต่อท้ายที่ตรงกับนิพจน์ ให้เราดูตัวอย่าง -
ขั้นแรกเราต้องนำเข้าชุดเครื่องมือภาษาธรรมชาติ (nltk)
import nltk
ตอนนี้นำเข้าไฟล์ RegexpStemmer คลาสเพื่อใช้อัลกอริทึม Regular Expression Stemmer
from nltk.stem import RegexpStemmer
จากนั้นสร้างอินสแตนซ์ของ RegexpStemmer คลาสและระบุคำต่อท้ายหรือคำนำหน้าที่คุณต้องการลบออกจากคำดังนี้ -
Reg_stemmer = RegexpStemmer(‘ing’)
ตอนนี้ป้อนคำที่คุณต้องการกำเนิด
Reg_stemmer.stem('eating')
เอาต์พุต
'eat'
Reg_stemmer.stem('ingeat')
เอาต์พุต
'eat'
Reg_stemmer.stem('eats')
เอาต์พุต
'eat'
ตัวอย่างการใช้งานที่สมบูรณ์
import nltk
from nltk.stem import RegexpStemmer
Reg_stemmer = RegexpStemmer()
Reg_stemmer.stem('ingeat')
เอาต์พุต
'eat'
อัลกอริธึมการสกัดกั้นสโนว์บอล
เป็นอีกหนึ่งอัลกอริธึมการตัดต้นกำเนิดที่มีประโยชน์มาก
สโนว์บอลคลาส Stemmer
NLTK มี SnowballStemmerคลาสด้วยความช่วยเหลือซึ่งเราสามารถใช้อัลกอริทึม Snowball Stemmer ได้อย่างง่ายดาย รองรับ 15 ภาษาที่ไม่ใช่ภาษาอังกฤษ ในการใช้คลาสนึ่งนี้เราต้องสร้างอินสแตนซ์ด้วยชื่อภาษาที่เราใช้แล้วเรียกเมธอด stem () ให้เราดูตัวอย่าง -
ขั้นแรกเราต้องนำเข้าชุดเครื่องมือภาษาธรรมชาติ (nltk)
import nltk
ตอนนี้นำเข้าไฟล์ SnowballStemmer คลาสเพื่อใช้อัลกอริทึม Snowball Stemmer
from nltk.stem import SnowballStemmer
ให้เราดูภาษาที่รองรับ -
SnowballStemmer.languages
เอาต์พุต
(
'arabic',
'danish',
'dutch',
'english',
'finnish',
'french',
'german',
'hungarian',
'italian',
'norwegian',
'porter',
'portuguese',
'romanian',
'russian',
'spanish',
'swedish'
)
จากนั้นสร้างอินสแตนซ์ของคลาส SnowballStemmer ด้วยภาษาที่คุณต้องการใช้ ที่นี่เรากำลังสร้างตัวตั้งต้นสำหรับภาษา "ฝรั่งเศส"
French_stemmer = SnowballStemmer(‘french’)
ตอนนี้เรียกใช้วิธี stem () และป้อนคำที่คุณต้องการตั้งต้น
French_stemmer.stem (‘Bonjoura’)
เอาต์พุต
'bonjour'
ตัวอย่างการใช้งานที่สมบูรณ์
import nltk
from nltk.stem import SnowballStemmer
French_stemmer = SnowballStemmer(‘french’)
French_stemmer.stem (‘Bonjoura’)
เอาต์พุต
'bonjour'
Lemmatization คืออะไร?
เทคนิค Lemmatization ก็เหมือนกับการ Stemming ผลลัพธ์ที่เราจะได้รับหลังจากการทำให้เป็นตัวอักษรเรียกว่า 'เลมมา' ซึ่งเป็นคำรากมากกว่ารากซึ่งเป็นผลลัพธ์ของการสร้างคำ หลังจากสร้างคำศัพท์แล้วเราจะได้คำที่ถูกต้องซึ่งหมายถึงสิ่งเดียวกัน
NLTK ให้ WordNetLemmatizer คลาสซึ่งเป็นกระดาษห่อบาง ๆ รอบ ๆ wordnetคลังข้อมูล คลาสนี้ใช้morphy() ฟังก์ชันไปที่ WordNet CorpusReaderชั้นเรียนเพื่อค้นหาคำหลัก ให้เราเข้าใจด้วยตัวอย่าง -
ตัวอย่าง
ขั้นแรกเราต้องนำเข้าชุดเครื่องมือภาษาธรรมชาติ (nltk)
import nltk
ตอนนี้นำเข้าไฟล์ WordNetLemmatizer คลาสเพื่อใช้เทคนิคการทำให้เป็นตัวอักษร
from nltk.stem import WordNetLemmatizer
จากนั้นสร้างอินสแตนซ์ของ WordNetLemmatizer ชั้นเรียน.
lemmatizer = WordNetLemmatizer()
ตอนนี้เรียกเมธอด lemmatize () และป้อนคำที่คุณต้องการค้นหา lemma
lemmatizer.lemmatize('eating')
เอาต์พุต
'eating'
lemmatizer.lemmatize('books')
เอาต์พุต
'book'
ตัวอย่างการใช้งานที่สมบูรณ์
import nltk
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
lemmatizer.lemmatize('books')
เอาต์พุต
'book'
ความแตกต่างระหว่าง Stemming & Lemmatization
ให้เราเข้าใจความแตกต่างระหว่าง Stemming และ Lemmatization ด้วยความช่วยเหลือของตัวอย่างต่อไปนี้ -
import nltk
from nltk.stem import PorterStemmer
word_stemmer = PorterStemmer()
word_stemmer.stem('believes')
เอาต์พุต
believ
import nltk
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
lemmatizer.lemmatize(' believes ')
เอาต์พุต
believ
ผลลัพธ์ของทั้งสองโปรแกรมจะบอกความแตกต่างที่สำคัญระหว่างการสะกดคำและการทำให้เป็นตัวอักษร PorterStemmerคลาสตัด 'es' ออกจากคำ ในทางกลับกัน,WordNetLemmatizerชั้นเรียนค้นหาคำที่ถูกต้อง ในคำง่ายๆเทคนิคการสร้างคำจะดูที่รูปแบบของคำเท่านั้นในขณะที่เทคนิคการสร้างคำอธิบายจะดูที่ความหมายของคำ หมายความว่าหลังจากใช้คำนามเราจะได้คำที่ถูกต้องเสมอ
การสะกดคำและการทำให้เป็นตัวอักษรถือได้ว่าเป็นการบีบอัดภาษาศาสตร์ชนิดหนึ่ง ในทำนองเดียวกันการแทนที่คำอาจถือได้ว่าเป็นการทำให้ข้อความเป็นมาตรฐานหรือการแก้ไขข้อผิดพลาด
แต่ทำไมเราต้องเปลี่ยนคำ? สมมติว่าถ้าเราพูดถึงโทเค็นมันมีปัญหาเกี่ยวกับการหดตัว (เช่นทำไม่ได้จะไม่ ฯลฯ ) ดังนั้นเพื่อจัดการกับปัญหาดังกล่าวเราจำเป็นต้องเปลี่ยนคำ ตัวอย่างเช่นเราสามารถแทนที่การหดตัวด้วยรูปแบบที่ขยายได้
การแทนที่คำโดยใช้นิพจน์ทั่วไป
ขั้นแรกเราจะแทนที่คำที่ตรงกับนิพจน์ทั่วไป แต่สำหรับสิ่งนี้เราต้องมีความเข้าใจพื้นฐานเกี่ยวกับนิพจน์ทั่วไปรวมถึงโมดูล python re ในตัวอย่างด้านล่างเราจะแทนที่การหดตัวด้วยรูปแบบขยาย (เช่น "ไม่สามารถ" จะถูกแทนที่ด้วย "ไม่สามารถ") โดยใช้นิพจน์ทั่วไป
ตัวอย่าง
ขั้นแรกอิมพอร์ตแพ็กเกจที่จำเป็นอีกครั้งเพื่อทำงานกับนิพจน์ทั่วไป
import re
from nltk.corpus import wordnet
จากนั้นกำหนดรูปแบบการแทนที่ที่คุณเลือกดังนี้ -
R_patterns = [
(r'won\'t', 'will not'),
(r'can\'t', 'cannot'),
(r'i\'m', 'i am'),
r'(\w+)\'ll', '\g<1> will'),
(r'(\w+)n\'t', '\g<1> not'),
(r'(\w+)\'ve', '\g<1> have'),
(r'(\w+)\'s', '\g<1> is'),
(r'(\w+)\'re', '\g<1> are'),
]
ตอนนี้สร้างคลาสที่สามารถใช้แทนคำได้ -
class REReplacer(object):
def __init__(self, pattern = R_patterns):
self.pattern = [(re.compile(regex), repl) for (regex, repl) in patterns]
def replace(self, text):
s = text
for (pattern, repl) in self.pattern:
s = re.sub(pattern, repl, s)
return s
บันทึกโปรแกรม python นี้ (พูดว่า repRE.py) และเรียกใช้จากพรอมต์คำสั่ง python หลังจากเรียกใช้แล้วให้นำเข้าคลาส REReplacer เมื่อคุณต้องการแทนที่คำ ให้เราดูว่า
from repRE import REReplacer
rep_word = REReplacer()
rep_word.replace("I won't do it")
Output:
'I will not do it'
rep_word.replace("I can’t do it")
Output:
'I cannot do it'
ตัวอย่างการใช้งานที่สมบูรณ์
import re
from nltk.corpus import wordnet
R_patterns = [
(r'won\'t', 'will not'),
(r'can\'t', 'cannot'),
(r'i\'m', 'i am'),
r'(\w+)\'ll', '\g<1> will'),
(r'(\w+)n\'t', '\g<1> not'),
(r'(\w+)\'ve', '\g<1> have'),
(r'(\w+)\'s', '\g<1> is'),
(r'(\w+)\'re', '\g<1> are'),
]
class REReplacer(object):
def __init__(self, patterns=R_patterns):
self.patterns = [(re.compile(regex), repl) for (regex, repl) in patterns]
def replace(self, text):
s = text
for (pattern, repl) in self.patterns:
s = re.sub(pattern, repl, s)
return s
เมื่อคุณบันทึกโปรแกรมข้างต้นและเรียกใช้แล้วคุณสามารถนำเข้าคลาสและใช้งานได้ดังนี้ -
from replacerRE import REReplacer
rep_word = REReplacer()
rep_word.replace("I won't do it")
เอาต์พุต
'I will not do it'
แทนที่ก่อนการประมวลผลข้อความ
แนวทางปฏิบัติทั่วไปอย่างหนึ่งในขณะที่ทำงานกับการประมวลผลภาษาธรรมชาติ (NLP) คือการล้างข้อความก่อนประมวลผลข้อความ ในประเด็นนี้เราสามารถใช้ไฟล์REReplacer คลาสที่สร้างขึ้นข้างต้นในตัวอย่างก่อนหน้านี้เป็นขั้นตอนเบื้องต้นก่อนการประมวลผลข้อความเช่นโทเค็น
ตัวอย่าง
from nltk.tokenize import word_tokenize
from replacerRE import REReplacer
rep_word = REReplacer()
word_tokenize("I won't be able to do this now")
Output:
['I', 'wo', "n't", 'be', 'able', 'to', 'do', 'this', 'now']
word_tokenize(rep_word.replace("I won't be able to do this now"))
Output:
['I', 'will', 'not', 'be', 'able', 'to', 'do', 'this', 'now']
ในสูตร Python ข้างต้นเราสามารถเข้าใจความแตกต่างระหว่างผลลัพธ์ของโทเค็นไนเซอร์คำที่ไม่มีและโดยใช้การแทนที่นิพจน์ทั่วไป
การลบอักขระที่ซ้ำกัน
เราใช้ไวยากรณ์ในภาษาประจำวันอย่างเคร่งครัดหรือไม่? ไม่เราไม่ใช่. ตัวอย่างเช่นบางครั้งเราเขียนว่า 'Hiiiiiiiiiiii Mohan' เพื่อเน้นคำว่า 'Hi' แต่ระบบคอมพิวเตอร์ไม่ทราบว่า 'Hiiiiiiiiiiii' เป็นรูปแบบของคำว่า“ Hi” ในตัวอย่างด้านล่างเราจะสร้างคลาสชื่อrep_word_removal ซึ่งสามารถใช้สำหรับลบคำที่ซ้ำกัน
ตัวอย่าง
ขั้นแรกอิมพอร์ตแพ็กเกจที่จำเป็นอีกครั้งเพื่อทำงานกับนิพจน์ทั่วไป
import re
from nltk.corpus import wordnet
ตอนนี้สร้างคลาสที่สามารถใช้สำหรับลบคำที่ซ้ำกัน -
class Rep_word_removal(object):
def __init__(self):
self.repeat_regexp = re.compile(r'(\w*)(\w)\2(\w*)')
self.repl = r'\1\2\3'
def replace(self, word):
if wordnet.synsets(word):
return word
repl_word = self.repeat_regexp.sub(self.repl, word)
if repl_word != word:
return self.replace(repl_word)
else:
return repl_word
บันทึกโปรแกรม python นี้ (เช่น removerepeat.py) และเรียกใช้จากพรอมต์คำสั่ง python หลังจากเรียกใช้แล้วให้นำเข้าRep_word_removalคลาสเมื่อคุณต้องการลบคำที่ซ้ำกัน ให้เราดูว่า?
from removalrepeat import Rep_word_removal
rep_word = Rep_word_removal()
rep_word.replace ("Hiiiiiiiiiiiiiiiiiiiii")
Output:
'Hi'
rep_word.replace("Hellooooooooooooooo")
Output:
'Hello'
ตัวอย่างการใช้งานที่สมบูรณ์
import re
from nltk.corpus import wordnet
class Rep_word_removal(object):
def __init__(self):
self.repeat_regexp = re.compile(r'(\w*)(\w)\2(\w*)')
self.repl = r'\1\2\3'
def replace(self, word):
if wordnet.synsets(word):
return word
replace_word = self.repeat_regexp.sub(self.repl, word)
if replace_word != word:
return self.replace(replace_word)
else:
return replace_word
เมื่อคุณบันทึกโปรแกรมข้างต้นและเรียกใช้แล้วคุณสามารถนำเข้าคลาสและใช้งานได้ดังนี้ -
from removalrepeat import Rep_word_removal
rep_word = Rep_word_removal()
rep_word.replace ("Hiiiiiiiiiiiiiiiiiiiii")
เอาต์พุต
'Hi'
การแทนที่คำด้วยคำพ้องความหมายทั่วไป
ในขณะที่ทำงานกับ NLP โดยเฉพาะอย่างยิ่งในกรณีของการวิเคราะห์ความถี่และการจัดทำดัชนีข้อความการบีบอัดคำศัพท์จะเป็นประโยชน์เสมอโดยไม่สูญเสียความหมายเนื่องจากช่วยประหยัดหน่วยความจำได้มาก เพื่อให้บรรลุเป้าหมายนี้เราต้องกำหนดการแมปคำกับคำพ้องความหมาย ในตัวอย่างด้านล่างเราจะสร้างคลาสชื่อword_syn_replacer ซึ่งสามารถใช้สำหรับแทนที่คำด้วยคำพ้องความหมายทั่วไป
ตัวอย่าง
ขั้นแรกให้นำเข้าแพ็คเกจที่จำเป็น re เพื่อทำงานกับนิพจน์ทั่วไป
import re
from nltk.corpus import wordnet
จากนั้นสร้างคลาสที่ใช้การแมปแทนที่คำ -
class word_syn_replacer(object):
def __init__(self, word_map):
self.word_map = word_map
def replace(self, word):
return self.word_map.get(word, word)
บันทึกโปรแกรม python นี้ (พูดว่า replacesyn.py) และเรียกใช้จากพรอมต์คำสั่ง python หลังจากเรียกใช้แล้วให้นำเข้าword_syn_replacerคลาสเมื่อคุณต้องการแทนที่คำด้วยคำพ้องความหมายทั่วไป ให้เราดูว่า
from replacesyn import word_syn_replacer
rep_syn = word_syn_replacer ({‘bday’: ‘birthday’)
rep_syn.replace(‘bday’)
เอาต์พุต
'birthday'
ตัวอย่างการใช้งานที่สมบูรณ์
import re
from nltk.corpus import wordnet
class word_syn_replacer(object):
def __init__(self, word_map):
self.word_map = word_map
def replace(self, word):
return self.word_map.get(word, word)
เมื่อคุณบันทึกโปรแกรมข้างต้นและเรียกใช้แล้วคุณสามารถนำเข้าคลาสและใช้งานได้ดังนี้ -
from replacesyn import word_syn_replacer
rep_syn = word_syn_replacer ({‘bday’: ‘birthday’)
rep_syn.replace(‘bday’)
เอาต์พุต
'birthday'
ข้อเสียของวิธีการข้างต้นคือเราควรต้องฮาร์ดโค้ดคำพ้องความหมายในพจนานุกรม Python เรามีทางเลือกที่ดีกว่าสองทางในรูปแบบไฟล์ CSV และ YAML เราสามารถบันทึกคำศัพท์พ้องของเราในไฟล์ที่กล่าวถึงข้างต้นและสามารถสร้างword_mapพจนานุกรมจากพวกเขา ให้เราเข้าใจแนวคิดด้วยความช่วยเหลือของตัวอย่าง
ใช้ไฟล์ CSV
ในการใช้ไฟล์ CSV เพื่อจุดประสงค์นี้ไฟล์ควรมีสองคอลัมน์คอลัมน์แรกประกอบด้วยคำและคอลัมน์ที่สองประกอบด้วยคำพ้องความหมายที่ใช้แทนที่ ให้เราบันทึกไฟล์นี้เป็นไฟล์syn.csv. ในตัวอย่างด้านล่างเราจะสร้างคลาสชื่อ CSVword_syn_replacer ซึ่งจะขยายออกไป word_syn_replacer ใน replacesyn.py ไฟล์และจะใช้ในการสร้างไฟล์ word_map พจนานุกรมจาก syn.csv ไฟล์.
ตัวอย่าง
ขั้นแรกให้นำเข้าแพ็คเกจที่จำเป็น
import csv
จากนั้นสร้างคลาสที่ใช้การแมปแทนที่คำ -
class CSVword_syn_replacer(word_syn_replacer):
def __init__(self, fname):
word_map = {}
for line in csv.reader(open(fname)):
word, syn = line
word_map[word] = syn
super(Csvword_syn_replacer, self).__init__(word_map)
หลังจากเรียกใช้แล้วให้นำเข้า CSVword_syn_replacerคลาสเมื่อคุณต้องการแทนที่คำด้วยคำพ้องความหมายทั่วไป ให้เราดูว่า?
from replacesyn import CSVword_syn_replacer
rep_syn = CSVword_syn_replacer (‘syn.csv’)
rep_syn.replace(‘bday’)
เอาต์พุต
'birthday'
ตัวอย่างการใช้งานที่สมบูรณ์
import csv
class CSVword_syn_replacer(word_syn_replacer):
def __init__(self, fname):
word_map = {}
for line in csv.reader(open(fname)):
word, syn = line
word_map[word] = syn
super(Csvword_syn_replacer, self).__init__(word_map)
เมื่อคุณบันทึกโปรแกรมข้างต้นและเรียกใช้แล้วคุณสามารถนำเข้าคลาสและใช้งานได้ดังนี้ -
from replacesyn import CSVword_syn_replacer
rep_syn = CSVword_syn_replacer (‘syn.csv’)
rep_syn.replace(‘bday’)
เอาต์พุต
'birthday'
ใช้ไฟล์ YAML
เนื่องจากเราใช้ไฟล์ CSV แล้วเรายังสามารถใช้ไฟล์ YAML เพื่อจุดประสงค์นี้ได้ (เราต้องติดตั้ง PyYAML) ให้เราบันทึกไฟล์เป็นsyn.yaml. ในตัวอย่างด้านล่างเราจะสร้างคลาสชื่อ YAMLword_syn_replacer ซึ่งจะขยายออกไป word_syn_replacer ใน replacesyn.py ไฟล์และจะใช้ในการสร้างไฟล์ word_map พจนานุกรมจาก syn.yaml ไฟล์.
ตัวอย่าง
ขั้นแรกให้นำเข้าแพ็คเกจที่จำเป็น
import yaml
จากนั้นสร้างคลาสที่ใช้การแมปแทนที่คำ -
class YAMLword_syn_replacer(word_syn_replacer):
def __init__(self, fname):
word_map = yaml.load(open(fname))
super(YamlWordReplacer, self).__init__(word_map)
หลังจากเรียกใช้แล้วให้นำเข้า YAMLword_syn_replacerคลาสเมื่อคุณต้องการแทนที่คำด้วยคำพ้องความหมายทั่วไป ให้เราดูว่า?
from replacesyn import YAMLword_syn_replacer
rep_syn = YAMLword_syn_replacer (‘syn.yaml’)
rep_syn.replace(‘bday’)
เอาต์พุต
'birthday'
ตัวอย่างการใช้งานที่สมบูรณ์
import yaml
class YAMLword_syn_replacer(word_syn_replacer):
def __init__(self, fname):
word_map = yaml.load(open(fname))
super(YamlWordReplacer, self).__init__(word_map)
เมื่อคุณบันทึกโปรแกรมข้างต้นและเรียกใช้แล้วคุณสามารถนำเข้าคลาสและใช้งานได้ดังนี้ -
from replacesyn import YAMLword_syn_replacer
rep_syn = YAMLword_syn_replacer (‘syn.yaml’)
rep_syn.replace(‘bday’)
เอาต์พุต
'birthday'
การแทนที่คำตรงข้าม
อย่างที่เราทราบกันดีว่าคำตรงข้ามเป็นคำที่มีความหมายตรงกันข้ามกับคำอื่นและคำตรงข้ามกับการแทนที่คำพ้องความหมายเรียกว่าการแทนที่คำตรงข้าม ในส่วนนี้เราจะจัดการกับการแทนที่คำตรงข้ามนั่นคือการแทนที่คำด้วยคำตรงข้ามที่ไม่ชัดเจนโดยใช้ WordNet ในตัวอย่างด้านล่างเราจะสร้างคลาสชื่อword_antonym_replacer ซึ่งมีสองวิธีวิธีหนึ่งสำหรับการแทนที่คำและวิธีอื่น ๆ สำหรับการลบคำปฏิเสธ
ตัวอย่าง
ขั้นแรกให้นำเข้าแพ็คเกจที่จำเป็น
from nltk.corpus import wordnet
จากนั้นสร้างคลาสชื่อ word_antonym_replacer -
class word_antonym_replacer(object):
def replace(self, word, pos=None):
antonyms = set()
for syn in wordnet.synsets(word, pos=pos):
for lemma in syn.lemmas():
for antonym in lemma.antonyms():
antonyms.add(antonym.name())
if len(antonyms) == 1:
return antonyms.pop()
else:
return None
def replace_negations(self, sent):
i, l = 0, len(sent)
words = []
while i < l:
word = sent[i]
if word == 'not' and i+1 < l:
ant = self.replace(sent[i+1])
if ant:
words.append(ant)
i += 2
continue
words.append(word)
i += 1
return words
บันทึกโปรแกรม python นี้ (พูดว่า replaceantonym.py) และเรียกใช้จากพรอมต์คำสั่ง python หลังจากเรียกใช้แล้วให้นำเข้าword_antonym_replacerคลาสเมื่อคุณต้องการแทนที่คำด้วยคำตรงข้ามที่ไม่ชัดเจน ให้เราดูว่า
from replacerantonym import word_antonym_replacer
rep_antonym = word_antonym_replacer ()
rep_antonym.replace(‘uglify’)
เอาต์พุต
['beautify'']
sentence = ["Let us", 'not', 'uglify', 'our', 'country']
rep_antonym.replace _negations(sentence)
เอาต์พุต
["Let us", 'beautify', 'our', 'country']
ตัวอย่างการใช้งานที่สมบูรณ์
nltk.corpus import wordnet
class word_antonym_replacer(object):
def replace(self, word, pos=None):
antonyms = set()
for syn in wordnet.synsets(word, pos=pos):
for lemma in syn.lemmas():
for antonym in lemma.antonyms():
antonyms.add(antonym.name())
if len(antonyms) == 1:
return antonyms.pop()
else:
return None
def replace_negations(self, sent):
i, l = 0, len(sent)
words = []
while i < l:
word = sent[i]
if word == 'not' and i+1 < l:
ant = self.replace(sent[i+1])
if ant:
words.append(ant)
i += 2
continue
words.append(word)
i += 1
return words
เมื่อคุณบันทึกโปรแกรมข้างต้นและเรียกใช้แล้วคุณสามารถนำเข้าคลาสและใช้งานได้ดังนี้ -
from replacerantonym import word_antonym_replacer
rep_antonym = word_antonym_replacer ()
rep_antonym.replace(‘uglify’)
sentence = ["Let us", 'not', 'uglify', 'our', 'country']
rep_antonym.replace _negations(sentence)
เอาต์พุต
["Let us", 'beautify', 'our', 'country']
คลังข้อมูลคืออะไร?
คลังข้อมูลคือคอลเล็กชันขนาดใหญ่ในรูปแบบโครงสร้างของข้อความที่เครื่องอ่านได้ซึ่งผลิตขึ้นในสภาพแวดล้อมที่มีการสื่อสารตามธรรมชาติ คำว่า Corpora เป็นพหูพจน์ของ Corpus คอร์ปัสสามารถหาได้หลายวิธีดังนี้ -
- จากข้อความที่เดิมเป็นอิเล็กทรอนิกส์
- จากการถอดเสียงภาษาพูด
- ตั้งแต่การรู้จำอักขระด้วยแสงเป็นต้น
ความเป็นตัวแทนของคอร์ปัส, ความสมดุลของคอร์ปัส, การสุ่มตัวอย่าง, ขนาดคอร์ปัสเป็นองค์ประกอบที่มีบทบาทสำคัญในการออกแบบคอร์ปัส คลังข้อมูลยอดนิยมสำหรับงาน NLP ได้แก่ TreeBank, PropBank, VarbNet และ WordNet
จะสร้างคลังข้อมูลแบบกำหนดเองได้อย่างไร?
ขณะดาวน์โหลด NLTK เราได้ติดตั้งแพ็คเกจข้อมูล NLTK ด้วย ดังนั้นเราจึงติดตั้งแพ็คเกจข้อมูล NLTK บนคอมพิวเตอร์ของเราแล้ว ถ้าเราพูดถึง Windows เราจะถือว่าแพ็คเกจข้อมูลนี้ติดตั้งที่C:\natural_language_toolkit_data และถ้าเราพูดถึง Linux, Unix และ Mac OS X เราจะถือว่าแพ็คเกจข้อมูลนี้ติดตั้งที่ /usr/share/natural_language_toolkit_data.
ในสูตร Python ต่อไปนี้เราจะสร้างองค์กรที่กำหนดเองซึ่งต้องอยู่ในเส้นทางใดเส้นทางหนึ่งที่กำหนดโดย NLTK เป็นเช่นนั้นเพราะ NLTK สามารถพบได้ เพื่อหลีกเลี่ยงความขัดแย้งกับแพ็คเกจข้อมูล NLTK อย่างเป็นทางการให้เราสร้างไดเร็กทอรี natural_language_toolkit_data ที่กำหนดเองในโฮมไดเร็กทอรีของเรา
import os, os.path
path = os.path.expanduser('~/natural_language_toolkit_data')
if not os.path.exists(path):
os.mkdir(path)
os.path.exists(path)
เอาต์พุต
True
ตอนนี้ให้เราตรวจสอบว่าเรามีไดเร็กทอรี natural_language_toolkit_data ในโฮมไดเร็กทอรีของเราหรือไม่ -
import nltk.data
path in nltk.data.path
เอาต์พุต
True
ในขณะที่เรามีเอาต์พุต True หมายความว่าเรามี nltk_data ไดเร็กทอรีในโฮมไดเร็กทอรีของเรา
ตอนนี้เราจะสร้างไฟล์ wordlist ชื่อ wordfile.txt และวางไว้ในโฟลเดอร์ชื่อ corpus in nltk_data ไดเรกทอรี (~/nltk_data/corpus/wordfile.txt) และจะโหลดโดยใช้ nltk.data.load -
import nltk.data
nltk.data.load(‘corpus/wordfile.txt’, format = ‘raw’)
เอาต์พุต
b’tutorialspoint\n’
ผู้อ่าน Corpus
NLTK มีคลาส CorpusReader ที่หลากหลาย เราจะพูดถึงมันในสูตรหลามต่อไปนี้
การสร้างคลังคำศัพท์
NLTK มี WordListCorpusReaderคลาสที่ให้การเข้าถึงไฟล์ที่มีรายการคำ สำหรับสูตร Python ต่อไปนี้เราต้องสร้างไฟล์ wordlist ซึ่งอาจเป็นไฟล์ CSV หรือไฟล์ข้อความปกติ ตัวอย่างเช่นเราได้สร้างไฟล์ชื่อ 'list' ที่มีข้อมูลต่อไปนี้ -
tutorialspoint
Online
Free
Tutorials
ตอนนี้ให้เราสร้างตัวอย่างไฟล์ WordListCorpusReader คลาสสร้างรายการคำจากไฟล์ที่เราสร้างขึ้น ‘list’.
from nltk.corpus.reader import WordListCorpusReader
reader_corpus = WordListCorpusReader('.', ['list'])
reader_corpus.words()
เอาต์พุต
['tutorialspoint', 'Online', 'Free', 'Tutorials']
การสร้างคลังคำที่ติดแท็ก POS
NLTK มี TaggedCorpusReaderชั้นเรียนด้วยความช่วยเหลือซึ่งเราสามารถสร้างคลังคำที่ติดแท็ก POS ที่จริงแล้วการติดแท็ก POS เป็นกระบวนการในการระบุแท็กส่วนของคำพูดสำหรับคำ
หนึ่งในรูปแบบที่ง่ายที่สุดสำหรับคลังข้อมูลที่ติดแท็กคือรูปแบบ 'word / tag' เหมือนตามข้อความที่ตัดตอนมาจากคลังข้อมูลสีน้ำตาล -
The/at-tl expense/nn and/cc time/nn involved/vbn are/ber
astronomical/jj ./.
ในข้อความที่ตัดตอนมาข้างต้นแต่ละคำมีแท็กซึ่งแสดงถึง POS ตัวอย่างเช่น,vb หมายถึงกริยา
ตอนนี้ให้เราสร้างตัวอย่างไฟล์ TaggedCorpusReaderคลาสที่สร้างคำที่ติดแท็ก POS จะสร้างไฟล์ ‘list.pos’ซึ่งมีข้อความที่ตัดตอนมาข้างต้น
from nltk.corpus.reader import TaggedCorpusReader
reader_corpus = TaggedCorpusReader('.', r'.*\.pos')
reader_corpus.tagged_words()
เอาต์พุต
[('The', 'AT-TL'), ('expense', 'NN'), ('and', 'CC'), ...]
การสร้างคลังวลีแบบก้อน
NLTK มี ChnkedCorpusReaderคลาสด้วยความช่วยเหลือซึ่งเราสามารถสร้างคลังวลีแบบก้อนได้ จริงๆแล้ว chunk คือวลีสั้น ๆ ในประโยค
ตัวอย่างเช่นเรามีข้อความที่ตัดตอนมาจากแท็กต่อไปนี้ treebank คลังข้อมูล -
[Earlier/JJR staff-reduction/NN moves/NNS] have/VBP trimmed/VBN about/
IN [300/CD jobs/NNS] ,/, [the/DT spokesman/NN] said/VBD ./.
ในข้อความที่ตัดตอนมาข้างต้นทุกท่อนเป็นวลีคำนาม แต่คำที่ไม่อยู่ในวงเล็บเป็นส่วนหนึ่งของโครงสร้างประโยคและไม่ได้เป็นส่วนหนึ่งของทรีย่อยของวลีนามใด ๆ
ตอนนี้ให้เราสร้างตัวอย่างไฟล์ ChunkedCorpusReader คลาสที่สร้างวลีที่เป็นกลุ่มจากไฟล์ ‘list.chunk’ซึ่งมีข้อความที่ตัดตอนมาข้างต้น
from nltk.corpus.reader import ChunkedCorpusReader
reader_corpus = TaggedCorpusReader('.', r'.*\.chunk')
reader_corpus.chunked_words()
เอาต์พุต
[
Tree('NP', [('Earlier', 'JJR'), ('staff-reduction', 'NN'), ('moves', 'NNS')]),
('have', 'VBP'), ...
]
การสร้างคลังข้อความที่จัดหมวดหมู่
NLTK มี CategorizedPlaintextCorpusReaderชั้นเรียนด้วยความช่วยเหลือซึ่งเราสามารถสร้างคลังข้อความที่จัดหมวดหมู่ได้ มีประโยชน์มากในกรณีที่เรามีคลังข้อความจำนวนมากและต้องการจัดหมวดหมู่ข้อความนั้นออกเป็นส่วนต่างๆ
ตัวอย่างเช่นคลังข้อมูลสีน้ำตาลมีหมวดหมู่ต่างๆมากมาย ให้เราค้นหาด้วยความช่วยเหลือของการทำตามรหัส Python -
from nltk.corpus import brown^M
brown.categories()
เอาต์พุต
[
'adventure', 'belles_lettres', 'editorial', 'fiction', 'government',
'hobbies', 'humor', 'learned', 'lore', 'mystery', 'news', 'religion',
'reviews', 'romance', 'science_fiction'
]
วิธีที่ง่ายที่สุดวิธีหนึ่งในการจัดหมวดหมู่คลังข้อมูลคือการมีไฟล์เดียวสำหรับทุกหมวดหมู่ ตัวอย่างเช่นให้เราดูสองข้อความที่ตัดตอนมาจากไฟล์movie_reviews คลังข้อมูล -
movie_pos.txt
เส้นสีแดงบาง ๆ มีตำหนิ แต่มันกระตุ้น
movie_neg.txt
งบประมาณจำนวนมากและการผลิตแบบมันวาวไม่สามารถชดเชยการขาดความเป็นธรรมชาติที่แทรกซึมรายการทีวีของพวกเขาได้
ดังนั้นจากสองไฟล์ด้านบนเรามีสองประเภทคือ pos และ neg.
ตอนนี้ให้เราสร้างตัวอย่างไฟล์ CategorizedPlaintextCorpusReader ชั้นเรียน.
from nltk.corpus.reader import CategorizedPlaintextCorpusReader
reader_corpus = CategorizedPlaintextCorpusReader('.', r'movie_.*\.txt',
cat_pattern = r'movie_(\w+)\.txt')
reader_corpus.categories()
reader_corpus.fileids(categories = [‘neg’])
reader_corpus.fileids(categories = [‘pos’])
เอาต์พุต
['neg', 'pos']
['movie_neg.txt']
['movie_pos.txt']
การติดแท็ก POS คืออะไร?
การติดแท็กเป็นการจัดหมวดหมู่เป็นการกำหนดคำอธิบายของโทเค็นโดยอัตโนมัติ เราเรียกแท็ก descriptor ซึ่งแสดงถึงส่วนใดส่วนหนึ่งของคำพูด (คำนามกริยาคำวิเศษณ์คำคุณศัพท์คำสรรพนามการรวมและหมวดหมู่ย่อย) ข้อมูลความหมายและอื่น ๆ
ในทางกลับกันถ้าเราพูดถึงการติดแท็ก Part-of-Speech (POS) มันอาจถูกกำหนดให้เป็นกระบวนการแปลงประโยคในรูปแบบของรายการคำให้เป็นรายการ tuples ที่นี่ tuples อยู่ในรูปแบบของ (word, tag) นอกจากนี้เรายังสามารถเรียกการติดแท็ก POS เป็นกระบวนการกำหนดส่วนของคำพูดให้กับคำที่กำหนด
ตารางต่อไปนี้แสดงการแจ้งเตือน POS ที่ใช้บ่อยที่สุดในคลังข้อมูลของ Penn Treebank -
ซีเนียร์ No | แท็ก | คำอธิบาย |
---|---|---|
1 | เอ็น. เอ็น. พี | คำนามเอกพจน์ |
2 | สวป | คำนามพหูพจน์ |
3 | กปปส | ตัวกำหนดล่วงหน้า |
4 | POS | สิ้นสุดที่เป็นเจ้าของ |
5 | PRP | สรรพนามส่วนตัว |
6 | PRP $ | สรรพนามแสดงความเป็นเจ้าของ |
7 | RB | กริยาวิเศษณ์ |
8 | RBR | กริยาวิเศษณ์เปรียบเทียบ |
9 | RBS | กริยาวิเศษณ์สุดยอด |
10 | RP | อนุภาค |
11 | SYM | สัญลักษณ์ (ทางคณิตศาสตร์หรือวิทยาศาสตร์) |
12 | ถึง | ถึง |
13 | UH | คำอุทาน |
14 | VB | คำกริยารูปฐาน |
15 | VBD | กริยาอดีตกาล |
16 | VBG | กริยา Gerund / ปัจจุบันกริยา |
17 | VBN | กริยาที่ผ่านมา |
18 | WP | Wh- สรรพนาม |
19 | WP $ | มีสรรพนาม wh |
20 | WRB | Wh-adverb |
21 | # | เครื่องหมายปอนด์ |
22 | $ | เครื่องหมายดอลลาร์ |
23 | . | เครื่องหมายวรรคตอนสุดท้ายของประโยค |
24 | , | จุลภาค |
25 | : | ลำไส้ใหญ่กึ่งลำไส้ใหญ่ |
26 | ( | อักขระวงเล็บซ้าย |
27 | ) | อักขระวงเล็บขวา |
28 | " | คำพูดคู่ตรง |
29 | ' | เปิดเครื่องหมายคำพูดเดี่ยวด้านซ้าย |
30 | " | เปิดเครื่องหมายคำพูดคู่ซ้าย |
31 | ' | ปิดคำพูดเดียว |
32 | " | เปิดเครื่องหมายคำพูดคู่ |
ตัวอย่าง
ให้เราเข้าใจด้วยการทดลอง Python -
import nltk
from nltk import word_tokenize
sentence = "I am going to school"
print (nltk.pos_tag(word_tokenize(sentence)))
เอาต์พุต
[('I', 'PRP'), ('am', 'VBP'), ('going', 'VBG'), ('to', 'TO'), ('school', 'NN')]
ทำไมต้องติดแท็ก POS
การติดแท็ก POS เป็นส่วนสำคัญของ NLP เนื่องจากทำงานเป็นข้อกำหนดเบื้องต้นสำหรับการวิเคราะห์ NLP เพิ่มเติมดังนี้ -
- Chunking
- การแยกวิเคราะห์ไวยากรณ์
- การสกัดข้อมูล
- การแปลด้วยเครื่อง
- การวิเคราะห์ความเชื่อมั่น
- การวิเคราะห์ไวยากรณ์และการเปลี่ยนความหมายของคำ
TaggerI - คลาสพื้นฐาน
แท็กเกอร์ทั้งหมดอยู่ในแพ็คเกจ nltk.tag ของ NLTK คลาสพื้นฐานของแท็กเกอร์เหล่านี้คือTaggerIหมายถึงแท็กเกอร์ทั้งหมดที่สืบทอดมาจากคลาสนี้
Methods - คลาส TaggerI มีสองวิธีดังต่อไปนี้ซึ่งต้องนำไปใช้โดยคลาสย่อยทั้งหมด -
tag() method - ตามความหมายของชื่อวิธีนี้จะใช้รายการคำเป็นอินพุตและส่งคืนรายการคำที่ติดแท็กเป็นเอาต์พุต
evaluate() method - ด้วยความช่วยเหลือของวิธีนี้เราสามารถประเมินความแม่นยำของแท็กเกอร์ได้
พื้นฐานของการติดแท็ก POS
พื้นฐานหรือขั้นตอนพื้นฐานของการติดแท็ก POS คือ Default Taggingซึ่งสามารถทำได้โดยใช้คลาส DefaultTagger ของ NLTK การติดแท็กเริ่มต้นเพียงแค่กำหนดแท็ก POS เดียวกันให้กับทุกโทเค็น การติดแท็กเริ่มต้นยังเป็นพื้นฐานในการวัดการปรับปรุงความแม่นยำ
คลาส DefaultTagger
การติดแท็กเริ่มต้นดำเนินการโดยใช้ DefaultTagging คลาสซึ่งใช้อาร์กิวเมนต์เดียวนั่นคือแท็กที่เราต้องการใช้
มันทำงานอย่างไร?
อย่างที่บอกไปก่อนหน้านี้ taggers ทั้งหมดได้รับการถ่ายทอดมาจาก TaggerIชั้นเรียน. DefaultTagger สืบทอดมาจาก SequentialBackoffTagger ซึ่งเป็นคลาสย่อยของ TaggerI class. ให้เราเข้าใจด้วยแผนภาพต่อไปนี้ -
ในฐานะที่เป็นส่วนหนึ่งของ SeuentialBackoffTagger, DefaultTagger ต้องใช้เมธอด select_tag () ซึ่งรับสามอาร์กิวเมนต์ต่อไปนี้
- รายการของโทเค็น
- ดัชนีของโทเค็นปัจจุบัน
- รายการโทเค็นก่อนหน้า ได้แก่ ประวัติ
ตัวอย่าง
import nltk
from nltk.tag import DefaultTagger
exptagger = DefaultTagger('NN')
exptagger.tag(['Tutorials','Point'])
เอาต์พุต
[('Tutorials', 'NN'), ('Point', 'NN')]
ในตัวอย่างนี้เราเลือกแท็กคำนามเนื่องจากเป็นประเภทคำที่พบบ่อยที่สุด ยิ่งไปกว่านั้นDefaultTagger ยังมีประโยชน์มากที่สุดเมื่อเราเลือกแท็ก POS ที่พบบ่อยที่สุด
การประเมินความถูกต้อง
DefaultTaggerยังเป็นพื้นฐานในการประเมินความแม่นยำของผู้ติดแท็ก นั่นคือเหตุผลที่เราสามารถใช้มันควบคู่ไปด้วยevaluate()วิธีการวัดความแม่นยำ evaluate() วิธีใช้รายการโทเค็นที่ติดแท็กเป็นมาตรฐานทองคำเพื่อประเมินผู้ติดแท็ก
ต่อไปนี้เป็นตัวอย่างที่เราใช้แท็กเกอร์เริ่มต้นชื่อ exptaggerสร้างขึ้นด้านบนเพื่อประเมินความถูกต้องของชุดย่อยของ treebank คลังประโยคที่ติดแท็ก -
ตัวอย่าง
import nltk
from nltk.tag import DefaultTagger
exptagger = DefaultTagger('NN')
from nltk.corpus import treebank
testsentences = treebank.tagged_sents() [1000:]
exptagger.evaluate (testsentences)
เอาต์พุต
0.13198749536374715
ผลลัพธ์ด้านบนแสดงให้เห็นว่าโดยการเลือก NN สำหรับทุกแท็กเราสามารถทำการทดสอบความแม่นยำได้ประมาณ 13% ใน 1,000 รายการของไฟล์ treebank คลังข้อมูล
แท็กรายการประโยค
แทนที่จะติดแท็กประโยคเดียว NLTK's TaggerI ชั้นเรียนยังมี tag_sents()วิธีการด้วยความช่วยเหลือซึ่งเราสามารถแท็กรายการประโยค ต่อไปนี้เป็นตัวอย่างที่เราติดแท็กสองประโยคง่ายๆ
ตัวอย่าง
import nltk
from nltk.tag import DefaultTagger
exptagger = DefaultTagger('NN')
exptagger.tag_sents([['Hi', ','], ['How', 'are', 'you', '?']])
เอาต์พุต
[
[
('Hi', 'NN'),
(',', 'NN')
],
[
('How', 'NN'),
('are', 'NN'),
('you', 'NN'),
('?', 'NN')
]
]
ในตัวอย่างข้างต้นเราใช้แท็กเกอร์เริ่มต้นที่สร้างขึ้นก่อนหน้านี้ชื่อ exptagger.
การยกเลิกการติดแท็กประโยค
นอกจากนี้เรายังสามารถยกเลิกการแท็กประโยค NLTK จัดเตรียมวิธีการ nltk.tag.untag () สำหรับวัตถุประสงค์นี้ จะใช้ประโยคที่แท็กเป็นอินพุตและแสดงรายการคำที่ไม่มีแท็ก ให้เราดูตัวอย่าง -
ตัวอย่าง
import nltk
from nltk.tag import untag
untag([('Tutorials', 'NN'), ('Point', 'NN')])
เอาต์พุต
['Tutorials', 'Point']
Unigram Tagger คืออะไร?
ตามความหมายของชื่อ unigram tagger คือแท็กเกอร์ที่ใช้เพียงคำเดียวเป็นบริบทในการกำหนดแท็ก POS (Part-of-Speech) พูดง่ายๆ Unigram Tagger คือแท็กเกอร์ตามบริบทที่มีบริบทเป็นคำเดียวคือ Unigram
มันทำงานอย่างไร?
NLTK จัดเตรียมโมดูลที่ชื่อ UnigramTaggerเพื่อจุดประสงค์นี้. แต่ก่อนที่จะดำน้ำลึกในการทำงานให้เราเข้าใจลำดับชั้นด้วยความช่วยเหลือของแผนภาพต่อไปนี้ -
จากแผนภาพด้านบนเป็นที่เข้าใจว่า UnigramTagger สืบทอดมาจาก NgramTagger ซึ่งเป็นคลาสย่อยของ ContextTaggerซึ่งสืบทอดมาจาก SequentialBackoffTagger.
การทำงานของ UnigramTagger อธิบายด้วยความช่วยเหลือของขั้นตอนต่อไปนี้ -
อย่างที่เราเห็น UnigramTagger สืบทอดมาจาก ContextTaggerมันใช้ context()วิธี. นี้context() method ใช้สามอาร์กิวเมนต์เดียวกันกับ choose_tag() วิธี.
ผลของ context()วิธีการจะเป็นโทเค็นคำที่ใช้ในการสร้างแบบจำลองต่อไป เมื่อสร้างแบบจำลองแล้วโทเค็นคำจะถูกใช้เพื่อค้นหาแท็กที่ดีที่สุด
ทางนี้, UnigramTagger จะสร้างแบบจำลองบริบทจากรายการประโยคที่ติดแท็ก
การฝึก Unigram Tagger
NLTK ของ UnigramTaggerสามารถฝึกได้โดยให้รายการประโยคที่ติดแท็กในขณะเริ่มต้น ในตัวอย่างด้านล่างเราจะใช้ประโยคที่ติดแท็กของคลังข้อมูลธนาคารต้นไม้ เราจะใช้ 2500 ประโยคแรกจากคลังข้อมูลนั้น
ตัวอย่าง
ก่อนอื่นให้นำเข้าโมดูล UniframTagger จาก nltk -
from nltk.tag import UnigramTagger
จากนั้นนำเข้าคลังข้อมูลที่คุณต้องการใช้ ที่นี่เรากำลังใช้คลังข้อมูลธนาคารต้นไม้ -
from nltk.corpus import treebank
ตอนนี้ใช้ประโยคสำหรับการฝึกอบรม เราใช้ 2500 ประโยคแรกเพื่อจุดประสงค์ในการฝึกอบรมและจะแท็ก -
train_sentences = treebank.tagged_sents()[:2500]
จากนั้นใช้ UnigramTagger กับประโยคที่ใช้เพื่อการฝึกอบรม -
Uni_tagger = UnigramTagger(train_sentences)
ใช้บางประโยคไม่ว่าจะเท่ากับหรือน้อยกว่าที่นำมาเพื่อวัตถุประสงค์ในการฝึกอบรมเช่น 2500 เพื่อการทดสอบ ที่นี่เราใช้ 1,500 คนแรกเพื่อการทดสอบ -
test_sentences = treebank.tagged_sents()[1500:]
Uni_tagger.evaluate(test_sents)
เอาต์พุต
0.8942306156033808
ที่นี่เรามีความแม่นยำประมาณ 89 เปอร์เซ็นต์สำหรับแท็กเกอร์ที่ใช้การค้นหาคำเดียวเพื่อกำหนดแท็ก POS
ตัวอย่างการใช้งานที่สมบูรณ์
from nltk.tag import UnigramTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
Uni_tagger = UnigramTagger(train_sentences)
test_sentences = treebank.tagged_sents()[1500:]
Uni_tagger.evaluate(test_sentences)
เอาต์พุต
0.8942306156033808
การลบล้างโมเดลบริบท
จากแผนภาพด้านบนแสดงลำดับชั้นสำหรับ UnigramTaggerเรารู้จักแท็กเกอร์ทั้งหมดที่สืบทอดมาจาก ContextTaggerแทนที่จะฝึกฝนตนเองสามารถใช้แบบจำลองที่สร้างไว้ล่วงหน้า โมเดลที่สร้างไว้ล่วงหน้านี้เป็นเพียงการแมปพจนานุกรม Python ของคีย์บริบทไปยังแท็ก และสำหรับUnigramTaggerคีย์บริบทคือคำแต่ละคำในขณะที่คำอื่น ๆ NgramTagger คลาสย่อยมันจะเป็นทูเปิล
เราสามารถลบล้างโมเดลบริบทนี้ได้โดยส่งโมเดลพื้นฐานอื่นไปยังไฟล์ UnigramTaggerชั้นเรียนแทนที่จะผ่านชุดฝึก ให้เราทำความเข้าใจด้วยตัวอย่างง่ายๆด้านล่างนี้ -
ตัวอย่าง
from nltk.tag import UnigramTagger
from nltk.corpus import treebank
Override_tagger = UnigramTagger(model = {‘Vinken’ : ‘NN’})
Override_tagger.tag(treebank.sents()[0])
เอาต์พุต
[
('Pierre', None),
('Vinken', 'NN'),
(',', None),
('61', None),
('years', None),
('old', None),
(',', None),
('will', None),
('join', None),
('the', None),
('board', None),
('as', None),
('a', None),
('nonexecutive', None),
('director', None),
('Nov.', None),
('29', None),
('.', None)
]
เนื่องจากโมเดลของเรามี 'Vinken' เป็นคีย์บริบทเพียงอย่างเดียวคุณสามารถสังเกตได้จากผลลัพธ์ด้านบนว่ามีเพียงคำนี้เท่านั้นที่มีแท็กและคำอื่น ๆ ทุกคำไม่มีเป็นแท็ก
การกำหนดเกณฑ์ความถี่ขั้นต่ำ
สำหรับการตัดสินใจว่าแท็กใดมีแนวโน้มมากที่สุดสำหรับบริบทหนึ่ง ๆ ContextTaggerคลาสใช้ความถี่ของการเกิดขึ้น มันจะทำตามค่าเริ่มต้นแม้ว่าคำบริบทและแท็กจะเกิดขึ้นเพียงครั้งเดียว แต่เราสามารถกำหนดเกณฑ์ความถี่ขั้นต่ำได้โดยส่งcutoff ค่า UnigramTaggerชั้นเรียน. ในตัวอย่างด้านล่างเรากำลังส่งผ่านค่าการตัดในสูตรก่อนหน้านี้ซึ่งเราได้ฝึกฝน UnigramTagger -
ตัวอย่าง
from nltk.tag import UnigramTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
Uni_tagger = UnigramTagger(train_sentences, cutoff = 4)
test_sentences = treebank.tagged_sents()[1500:]
Uni_tagger.evaluate(test_sentences)
เอาต์พุต
0.7357651629613641
การรวม Taggers
การรวมแท็กเกอร์หรือการเชื่อมโยงแท็กเกอร์เข้าด้วยกันถือเป็นคุณสมบัติที่สำคัญอย่างหนึ่งของ NLTK แนวคิดหลักที่อยู่เบื้องหลังการรวมแท็กเกอร์คือในกรณีที่ผู้ติดแท็กไม่รู้วิธีแท็กคำก็จะถูกส่งต่อไปยังผู้ติดแท็กที่ถูกล่ามโซ่ไว้ เพื่อให้บรรลุวัตถุประสงค์นี้SequentialBackoffTagger ให้เรา Backoff tagging ลักษณะเฉพาะ.
Backoff Tagging
อย่างที่บอกไปก่อนหน้านี้การติดแท็กแบ็คออฟเป็นหนึ่งในคุณสมบัติที่สำคัญของ SequentialBackoffTaggerซึ่งช่วยให้เราสามารถรวมแท็กเกอร์ในลักษณะที่หากผู้ติดแท็กคนหนึ่งไม่รู้วิธีแท็กคำคำนั้นจะถูกส่งต่อไปยังแท็กเกอร์ตัวถัดไปและอื่น ๆ จนกว่าจะไม่มีแบ็กออฟแท็กเกอร์เหลือให้ตรวจสอบ
มันทำงานอย่างไร?
อันที่จริงทุกคลาสย่อยของ SequentialBackoffTaggerสามารถใช้อาร์กิวเมนต์คำหลัก 'backoff' ค่าของอาร์กิวเมนต์คำหลักนี้เป็นอีกตัวอย่างหนึ่งของSequentialBackoffTagger. เมื่อใดก็ตามที่เป็นเช่นนี้SequentialBackoffTaggerเริ่มต้นคลาสแล้วรายการภายในของ backoff taggers (โดยมีตัวเองเป็นองค์ประกอบแรก) จะถูกสร้างขึ้น ยิ่งไปกว่านั้นหากมีการกำหนด backoff tagger รายการภายในของ backoff taggers จะถูกต่อท้าย
ในตัวอย่างด้านล่างเรากำลังใช้ DefaulTagger ในฐานะผู้ติดแท็กแบ็คออฟในสูตร Python ด้านบนซึ่งเราได้ฝึกฝนไฟล์ UnigramTagger.
ตัวอย่าง
ในตัวอย่างนี้เรากำลังใช้ DefaulTaggerเป็นผู้ติดแท็กแบ็คออฟ เมื่อใดก็ตามที่UnigramTagger ไม่สามารถติดแท็กคำ backoff tagger เช่น DefaulTaggerในกรณีของเราจะติดแท็กด้วย "NN"
from nltk.tag import UnigramTagger
from nltk.tag import DefaultTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
back_tagger = DefaultTagger('NN')
Uni_tagger = UnigramTagger(train_sentences, backoff = back_tagger)
test_sentences = treebank.tagged_sents()[1500:]
Uni_tagger.evaluate(test_sentences)
เอาต์พุต
0.9061975746536931
จากผลลัพธ์ข้างต้นคุณสามารถสังเกตได้ว่าการเพิ่ม backoff tagger ความแม่นยำจะเพิ่มขึ้นประมาณ 2%
บันทึกแท็กเกอร์ด้วยของดอง
ดังที่เราได้เห็นแล้วว่าการฝึกนักแท็กเกอร์นั้นยุ่งยากมากและต้องใช้เวลาด้วย เพื่อประหยัดเวลาเราสามารถดองแท็กเกอร์ที่ได้รับการฝึกฝนมาเพื่อใช้ในภายหลัง ในตัวอย่างด้านล่างเราจะทำสิ่งนี้กับแท็กเกอร์ที่ได้รับการฝึกฝนมาแล้วซึ่งมีชื่อว่า‘Uni_tagger’.
ตัวอย่าง
import pickle
f = open('Uni_tagger.pickle','wb')
pickle.dump(Uni_tagger, f)
f.close()
f = open('Uni_tagger.pickle','rb')
Uni_tagger = pickle.load(f)
คลาส NgramTagger
จากแผนภาพลำดับชั้นที่กล่าวถึงในหน่วยก่อนหน้านี้ UnigramTagger สืบทอดมาจาก NgarmTagger คลาส แต่เรามีคลาสย่อยอีกสองคลาสของ NgarmTagger ชั้นเรียน -
คลาสย่อย BigramTagger
อันที่จริงแล้ว ngram เป็นสิ่งที่ตามมาของ n รายการดังนั้นตามที่ชื่อมีความหมาย BigramTaggerคลาสย่อยดูสองรายการ รายการแรกคือคำที่ติดแท็กก่อนหน้าและรายการที่สองคือคำที่ติดแท็กปัจจุบัน
คลาสย่อย TrigramTagger
ในบันทึกเดียวกันของ BigramTagger, TrigramTagger คลาสย่อยจะดูสามรายการ ได้แก่ คำที่ติดแท็กก่อนหน้าสองคำและคำที่ติดแท็กปัจจุบันหนึ่งคำ
ในทางปฏิบัติถ้าเราสมัคร BigramTagger และ TrigramTaggerคลาสย่อยทีละคลาสเหมือนกับที่เราทำกับคลาสย่อย UnigramTagger ทั้งคู่ทำงานได้แย่มาก ให้เราดูในตัวอย่างด้านล่าง:
ใช้ BigramTagger Subclass
from nltk.tag import BigramTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
Bi_tagger = BigramTagger(train_sentences)
test_sentences = treebank.tagged_sents()[1500:]
Bi_tagger.evaluate(test_sentences)
เอาต์พุต
0.44669191071913594
ใช้ TrigramTagger Subclass
from nltk.tag import TrigramTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
Tri_tagger = TrigramTagger(train_sentences)
test_sentences = treebank.tagged_sents()[1500:]
Tri_tagger.evaluate(test_sentences)
เอาต์พุต
0.41949863394526193
คุณสามารถเปรียบเทียบประสิทธิภาพของ UnigramTagger ที่เราใช้ก่อนหน้านี้ (ให้ความแม่นยำประมาณ 89%) กับ BigramTagger (ให้ความแม่นยำประมาณ 44%) และ TrigramTagger (ให้ความแม่นยำประมาณ 41%) เหตุผลก็คือผู้ติดแท็ก Bigram และ Trigram ไม่สามารถเรียนรู้บริบทจากคำแรกในประโยคได้ ในทางกลับกันคลาส UnigramTagger ไม่สนใจบริบทก่อนหน้านี้และคาดเดาแท็กที่พบบ่อยที่สุดสำหรับแต่ละคำดังนั้นจึงมีความแม่นยำพื้นฐานสูง
การรวม ngram taggers
จากตัวอย่างข้างต้นจะเห็นได้ชัดว่าผู้ติดแท็ก Bigram และ Trigram สามารถมีส่วนร่วมเมื่อเรารวมเข้ากับการแท็กแบ็กออฟ ในตัวอย่างด้านล่างเรากำลังรวม Unigram, Bigram และ Trigram taggers เข้ากับ backoff tagging แนวคิดนี้เหมือนกับสูตรก่อนหน้าในขณะที่รวม UnigramTagger กับ backoff tagger ข้อแตกต่างเพียงอย่างเดียวคือเรากำลังใช้ฟังก์ชันชื่อ backoff_tagger () จาก tagger_util.py ที่ระบุด้านล่างสำหรับการดำเนินการ backoff
def backoff_tagger(train_sentences, tagger_classes, backoff=None):
for cls in tagger_classes:
backoff = cls(train_sentences, backoff=backoff)
return backoff
ตัวอย่าง
from tagger_util import backoff_tagger
from nltk.tag import UnigramTagger
from nltk.tag import BigramTagger
from nltk.tag import TrigramTagger
from nltk.tag import DefaultTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
back_tagger = DefaultTagger('NN')
Combine_tagger = backoff_tagger(train_sentences,
[UnigramTagger, BigramTagger, TrigramTagger], backoff = back_tagger)
test_sentences = treebank.tagged_sents()[1500:]
Combine_tagger.evaluate(test_sentences)
เอาต์พุต
0.9234530029238365
จากผลลัพธ์ข้างต้นเราจะเห็นว่ามันเพิ่มความแม่นยำประมาณ 3%
ติดแท็กเกอร์
คลาสย่อยที่สำคัญอีกคลาสของ ContextTagger คือ AffixTagger ในคลาส AffixTagger บริบทคือคำนำหน้าหรือคำต่อท้ายของคำ นั่นคือเหตุผลที่คลาส AffixTagger สามารถเรียนรู้แท็กตามสตริงย่อยที่มีความยาวคงที่ของจุดเริ่มต้นหรือจุดสิ้นสุดของคำ
มันทำงานอย่างไร?
การทำงานขึ้นอยู่กับอาร์กิวเมนต์ที่ชื่อ affix_length ซึ่งระบุความยาวของคำนำหน้าหรือคำต่อท้าย ค่าเริ่มต้นคือ 3 แต่จะแยกแยะได้อย่างไรว่าคลาส AffixTagger เรียนรู้คำนำหน้าหรือคำต่อท้ายหรือไม่?
affix_length=positive - ถ้าค่าของ affix_lenght เป็นบวกแสดงว่าคลาส AffixTagger จะเรียนรู้คำนำหน้าของคำ
affix_length=negative - หากค่าของ affix_lenght เป็นค่าลบหมายความว่าคลาส AffixTagger จะเรียนรู้คำต่อท้ายของคำ
เพื่อให้ชัดเจนขึ้นในตัวอย่างด้านล่างเราจะใช้คลาส AffixTagger กับประโยค Treebank ที่ติดแท็ก
ตัวอย่าง
ในตัวอย่างนี้ AffixTagger จะเรียนรู้คำนำหน้าของคำเนื่องจากเราไม่ได้ระบุค่าใด ๆ สำหรับอาร์กิวเมนต์ affix_length อาร์กิวเมนต์จะใช้ค่าเริ่มต้น 3 -
from nltk.tag import AffixTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
Prefix_tagger = AffixTagger(train_sentences)
test_sentences = treebank.tagged_sents()[1500:]
Prefix_tagger.evaluate(test_sentences)
เอาต์พุต
0.2800492099250667
ให้เราดูในตัวอย่างด้านล่างว่าอะไรจะเป็นความแม่นยำเมื่อเราให้ค่า 4 กับอาร์กิวเมนต์ affix_length -
from nltk.tag import AffixTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
Prefix_tagger = AffixTagger(train_sentences, affix_length=4 )
test_sentences = treebank.tagged_sents()[1500:]
Prefix_tagger.evaluate(test_sentences)
เอาต์พุต
0.18154947354966527
ตัวอย่าง
ในตัวอย่างนี้ AffixTagger จะเรียนรู้คำต่อท้ายของคำเพราะเราจะระบุค่าลบสำหรับอาร์กิวเมนต์ affix_length
from nltk.tag import AffixTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
Suffix_tagger = AffixTagger(train_sentences, affix_length = -3)
test_sentences = treebank.tagged_sents()[1500:]
Suffix_tagger.evaluate(test_sentences)
เอาต์พุต
0.2800492099250667
Brill Tagger
Brill Tagger คือแท็กเกอร์ตามการเปลี่ยนแปลง NLTK ให้BrillTagger คลาสซึ่งเป็น tagger ตัวแรกที่ไม่ใช่คลาสย่อยของ SequentialBackoffTagger. ตรงข้ามกับชุดของกฎเพื่อแก้ไขผลลัพธ์ของแท็กเกอร์เริ่มต้นถูกใช้โดยBrillTagger.
มันทำงานอย่างไร?
เพื่อฝึกอบรมก BrillTagger คลาสโดยใช้ BrillTaggerTrainer เรากำหนดฟังก์ชันต่อไปนี้ -
def train_brill_tagger(initial_tagger, train_sentences, **kwargs) -
templates = [
brill.Template(brill.Pos([-1])),
brill.Template(brill.Pos([1])),
brill.Template(brill.Pos([-2])),
brill.Template(brill.Pos([2])),
brill.Template(brill.Pos([-2, -1])),
brill.Template(brill.Pos([1, 2])),
brill.Template(brill.Pos([-3, -2, -1])),
brill.Template(brill.Pos([1, 2, 3])),
brill.Template(brill.Pos([-1]), brill.Pos([1])),
brill.Template(brill.Word([-1])),
brill.Template(brill.Word([1])),
brill.Template(brill.Word([-2])),
brill.Template(brill.Word([2])),
brill.Template(brill.Word([-2, -1])),
brill.Template(brill.Word([1, 2])),
brill.Template(brill.Word([-3, -2, -1])),
brill.Template(brill.Word([1, 2, 3])),
brill.Template(brill.Word([-1]), brill.Word([1])),
]
trainer = brill_trainer.BrillTaggerTrainer(initial_tagger, templates, deterministic=True)
return trainer.train(train_sentences, **kwargs)
อย่างที่เราเห็นต้องใช้ฟังก์ชันนี้ initial_tagger และ train_sentences. ใช้เวลาinitial_tagger อาร์กิวเมนต์และรายการเทมเพลตซึ่งใช้ BrillTemplateอินเตอร์เฟซ. BrillTemplate พบอินเทอร์เฟซในไฟล์ nltk.tbl.templateโมดูล. หนึ่งในการดำเนินการดังกล่าวคือbrill.Template ชั้นเรียน.
บทบาทหลักของแท็กเกอร์ตามการแปลงคือการสร้างกฎการเปลี่ยนแปลงที่แก้ไขเอาต์พุตของแท็กเกอร์เริ่มต้นให้สอดคล้องกับประโยคการฝึกอบรมมากขึ้น ให้เราดูขั้นตอนการทำงานด้านล่าง -
ตัวอย่าง
สำหรับตัวอย่างนี้เราจะใช้ combine_tagger ซึ่งเราสร้างขึ้นในขณะที่รวม taggers (ในสูตรก่อนหน้า) จาก backoff chain ของ NgramTagger คลาสเช่น initial_tagger. ขั้นแรกให้เราประเมินผลลัพธ์โดยใช้Combine.tagger แล้วใช้เป็น initial_tagger ในการฝึกอบรมแท็กเกอร์ brill
from tagger_util import backoff_tagger
from nltk.tag import UnigramTagger
from nltk.tag import BigramTagger
from nltk.tag import TrigramTagger
from nltk.tag import DefaultTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
back_tagger = DefaultTagger('NN')
Combine_tagger = backoff_tagger(
train_sentences, [UnigramTagger, BigramTagger, TrigramTagger], backoff = back_tagger
)
test_sentences = treebank.tagged_sents()[1500:]
Combine_tagger.evaluate(test_sentences)
เอาต์พุต
0.9234530029238365
ตอนนี้ให้เราดูผลการประเมินเมื่อ Combine_tagger ใช้เป็น initial_tagger ในการฝึกอบรมแท็กเกอร์ brill -
from tagger_util import train_brill_tagger
brill_tagger = train_brill_tagger(combine_tagger, train_sentences)
brill_tagger.evaluate(test_sentences)
เอาต์พุต
0.9246832510505041
เราสามารถสังเกตได้ว่า BrillTagger คลาสมีความแม่นยำเพิ่มขึ้นเล็กน้อยในช่วง Combine_tagger.
ตัวอย่างการใช้งานที่สมบูรณ์
from tagger_util import backoff_tagger
from nltk.tag import UnigramTagger
from nltk.tag import BigramTagger
from nltk.tag import TrigramTagger
from nltk.tag import DefaultTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
back_tagger = DefaultTagger('NN')
Combine_tagger = backoff_tagger(train_sentences,
[UnigramTagger, BigramTagger, TrigramTagger], backoff = back_tagger)
test_sentences = treebank.tagged_sents()[1500:]
Combine_tagger.evaluate(test_sentences)
from tagger_util import train_brill_tagger
brill_tagger = train_brill_tagger(combine_tagger, train_sentences)
brill_tagger.evaluate(test_sentences)
เอาต์พุต
0.9234530029238365
0.9246832510505041
TnT Tagger
TnT Tagger ย่อมาจาก Trigrams'nTags เป็นแท็กเกอร์ทางสถิติซึ่งอิงตามแบบจำลอง Markov ลำดับที่สอง
มันทำงานอย่างไร?
เราสามารถเข้าใจการทำงานของ TnT tagger ด้วยความช่วยเหลือของขั้นตอนต่อไปนี้ -
อันดับแรกจากข้อมูลการฝึกอบรม TnT tegger จะเก็บข้อมูลภายในไว้หลายอย่าง FreqDist และ ConditionalFreqDist ตัวอย่าง.
หลังจากนั้น unigrams bigrams และ trigrams จะถูกนับโดยการแจกแจงความถี่เหล่านี้
ตอนนี้ในระหว่างการแท็กโดยใช้ความถี่จะคำนวณความน่าจะเป็นของแท็กที่เป็นไปได้สำหรับแต่ละคำ
นั่นเป็นเหตุผลว่าทำไมแทนที่จะสร้างห่วงโซ่ backoff ของ NgramTagger มันใช้โมเดล ngram ทั้งหมดร่วมกันเพื่อเลือกแท็กที่ดีที่สุดสำหรับแต่ละคำ ให้เราประเมินความถูกต้องด้วย TnT tagger ในตัวอย่างต่อไปนี้ -
from nltk.tag import tnt
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
tnt_tagger = tnt.TnT()
tnt_tagger.train(train_sentences)
test_sentences = treebank.tagged_sents()[1500:]
tnt_tagger.evaluate(test_sentences)
เอาต์พุต
0.9165508316157791
เรามีความแม่นยำน้อยกว่าที่เราได้รับจาก Brill Tagger เล็กน้อย
โปรดทราบว่าเราจำเป็นต้องโทร train() ก่อน evaluate() มิฉะนั้นเราจะได้รับความแม่นยำ 0%
การแยกวิเคราะห์และความเกี่ยวข้องใน NLP
คำว่า 'Parsing' ซึ่งมีต้นกำเนิดมาจากคำภาษาละติน ‘pars’ (ซึ่งหมายความว่า ‘part’) ใช้เพื่อวาดความหมายที่แน่นอนหรือความหมายตามพจนานุกรมจากข้อความ เรียกอีกอย่างว่า Syntactic analysis หรือการวิเคราะห์ไวยากรณ์ การเปรียบเทียบกฎของไวยากรณ์ที่เป็นทางการการวิเคราะห์ไวยากรณ์จะตรวจสอบความหมายของข้อความ ตัวอย่างเช่นประโยคเช่น“ Give me hot ice-cream” จะถูกปฏิเสธโดย parser หรือ syntactic analyzer
ในแง่นี้เราสามารถกำหนดการแยกวิเคราะห์หรือการวิเคราะห์วากยสัมพันธ์หรือการวิเคราะห์วากยสัมพันธ์ได้ดังนี้ -
อาจถูกกำหนดให้เป็นกระบวนการวิเคราะห์สตริงของสัญลักษณ์ในภาษาธรรมชาติที่สอดคล้องกับกฎเกณฑ์ของไวยากรณ์ที่เป็นทางการ
เราสามารถเข้าใจความเกี่ยวข้องของการแยกวิเคราะห์ใน NLP ด้วยความช่วยเหลือของประเด็นต่อไปนี้ -
Parser ใช้เพื่อรายงานข้อผิดพลาดทางไวยากรณ์
ช่วยในการกู้คืนจากข้อผิดพลาดที่เกิดขึ้นโดยทั่วไปเพื่อให้การประมวลผลส่วนที่เหลือของโปรแกรมสามารถดำเนินต่อไปได้
ต้นไม้แยกวิเคราะห์ถูกสร้างขึ้นด้วยความช่วยเหลือของโปรแกรมแยกวิเคราะห์
Parser ใช้เพื่อสร้างตารางสัญลักษณ์ซึ่งมีบทบาทสำคัญใน NLP
Parser ยังใช้ในการสร้างตัวแทนระดับกลาง (IR)
การแยกวิเคราะห์แบบลึก Vs ตื้น
การแยกวิเคราะห์ลึก | การแยกวิเคราะห์แบบตื้น |
---|---|
ในการแยกวิเคราะห์เชิงลึกกลยุทธ์การค้นหาจะให้โครงสร้างทางวากยสัมพันธ์ที่สมบูรณ์ให้กับประโยค | เป็นงานในการแยกวิเคราะห์ข้อมูลวากยสัมพันธ์บางส่วนจากงานที่กำหนด |
เหมาะสำหรับการใช้งาน NLP ที่ซับซ้อน | สามารถใช้สำหรับแอปพลิเคชัน NLP ที่ซับซ้อนน้อยกว่า |
ระบบการสนทนาและการสรุปเป็นตัวอย่างของแอปพลิเคชัน NLP ที่ใช้การแยกวิเคราะห์แบบลึก | การแยกข้อมูลและการขุดข้อความเป็นตัวอย่างของแอปพลิเคชัน NLP ที่ใช้การแยกวิเคราะห์แบบลึก |
เรียกอีกอย่างว่าการแยกวิเคราะห์แบบเต็ม | เรียกอีกอย่างว่า chunking |
ตัวแยกวิเคราะห์ประเภทต่างๆ
ตามที่กล่าวไว้โปรแกรมแยกวิเคราะห์เป็นขั้นตอนการตีความไวยากรณ์ พบต้นไม้ที่เหมาะสมที่สุดสำหรับประโยคที่กำหนดหลังจากค้นหาผ่านพื้นที่ของต้นไม้หลากหลายชนิด ให้เราดูตัวแยกวิเคราะห์ที่มีอยู่ด้านล่าง -
ตัวแยกวิเคราะห์การสืบเชื้อสายซ้ำ
การแยกวิเคราะห์แบบเรียกซ้ำเป็นรูปแบบการแยกวิเคราะห์ที่ตรงไปตรงมาที่สุดรูปแบบหนึ่ง ต่อไปนี้เป็นประเด็นสำคัญบางประการเกี่ยวกับตัวแยกวิเคราะห์การสืบเชื้อสายซ้ำ -
เป็นไปตามกระบวนการจากบนลงล่าง
พยายามตรวจสอบว่าไวยากรณ์ของอินพุตสตรีมถูกต้องหรือไม่
มันอ่านประโยคอินพุตจากซ้ายไปขวา
การดำเนินการอย่างหนึ่งที่จำเป็นสำหรับตัวแยกวิเคราะห์การสืบเชื้อสายซ้ำคือการอ่านอักขระจากอินพุตสตรีมและจับคู่กับเทอร์มินัลจากไวยากรณ์
Shift- ลดตัวแยกวิเคราะห์
ต่อไปนี้เป็นประเด็นสำคัญบางประการเกี่ยวกับตัวแยกวิเคราะห์การลดการเปลี่ยนแปลง -
เป็นไปตามขั้นตอนง่ายๆจากล่างขึ้นบน
จะพยายามค้นหาลำดับของคำและวลีที่ตรงกับด้านขวามือของการผลิตไวยากรณ์และแทนที่ด้วยด้านซ้ายมือของการผลิต
ความพยายามข้างต้นในการค้นหาลำดับของคำจะดำเนินต่อไปจนกว่าทั้งประโยคจะลดลง
พูดง่ายๆก็คือตัวแยกวิเคราะห์ลดการเลื่อนจะเริ่มต้นด้วยสัญลักษณ์อินพุตและพยายามสร้างโครงสร้างตัวแยกวิเคราะห์จนถึงสัญลักษณ์เริ่มต้น
ตัวแยกวิเคราะห์แผนภูมิ
ต่อไปนี้เป็นประเด็นสำคัญบางประการเกี่ยวกับตัวแยกวิเคราะห์แผนภูมิ -
ส่วนใหญ่มีประโยชน์หรือเหมาะสำหรับไวยากรณ์ที่ไม่ชัดเจนรวมถึงไวยากรณ์ของภาษาธรรมชาติ
ใช้โปรแกรมแบบไดนามิกกับปัญหาการแยกวิเคราะห์
เนื่องจากการเขียนโปรแกรมแบบไดนามิกผลลัพธ์ที่ตั้งสมมติฐานบางส่วนจะถูกเก็บไว้ในโครงสร้างที่เรียกว่า 'แผนภูมิ'
'แผนภูมิ' ยังสามารถใช้ซ้ำได้
ตัวแยกวิเคราะห์ Regexp
การแยกวิเคราะห์ Regexp เป็นหนึ่งในเทคนิคการแยกวิเคราะห์ที่ใช้กันมาก ต่อไปนี้เป็นประเด็นสำคัญบางประการเกี่ยวกับตัวแยกวิเคราะห์ Regexp -
ตามความหมายของชื่อจะใช้นิพจน์ทั่วไปที่กำหนดในรูปแบบของไวยากรณ์ที่ด้านบนของสตริงที่ติดแท็ก POS
โดยทั่วไปจะใช้นิพจน์ทั่วไปเหล่านี้เพื่อแยกวิเคราะห์ประโยคอินพุตและสร้างโครงสร้างการแยกวิเคราะห์จากสิ่งนี้
ตัวอย่าง
ต่อไปนี้เป็นตัวอย่างการทำงานของ Regexp Parser -
import nltk
sentence = [
("a", "DT"),
("clever", "JJ"),
("fox","NN"),
("was","VBP"),
("jumping","VBP"),
("over","IN"),
("the","DT"),
("wall","NN")
]
grammar = "NP:{<DT>?<JJ>*<NN>}"
Reg_parser = nltk.RegexpParser(grammar)
Reg_parser.parse(sentence)
Output = Reg_parser.parse(sentence)
Output.draw()
เอาต์พุต
การแยกวิเคราะห์การพึ่งพา
Dependency Parsing (DP) ซึ่งเป็นกลไกการแยกวิเคราะห์สมัยใหม่ซึ่งมีแนวคิดหลักคือหน่วยภาษาแต่ละคำ ได้แก่ คำที่เกี่ยวข้องกันโดยการเชื่อมโยงโดยตรง ลิงก์โดยตรงเหล่านี้มีอยู่จริง‘dependencies’ในภาษาศาสตร์ ตัวอย่างเช่นแผนภาพต่อไปนี้แสดงไวยากรณ์การพึ่งพาสำหรับประโยค“John can hit the ball”.
NLTK Package
We have following the two ways to do dependency parsing with NLTK −
Probabilistic, projective dependency parser
This is the first way we can do dependency parsing with NLTK. But this parser has the restriction of training with a limited set of training data.
Stanford parser
This is another way we can do dependency parsing with NLTK. Stanford parser is a state-of-the-art dependency parser. NLTK has a wrapper around it. To use it we need to download following two things −
The Stanford CoreNLP parser.
Language model for desired language. For example, English language model.
Example
Once you downloaded the model, we can use it through NLTK as follows −
from nltk.parse.stanford import StanfordDependencyParser
path_jar = 'path_to/stanford-parser-full-2014-08-27/stanford-parser.jar'
path_models_jar = 'path_to/stanford-parser-full-2014-08-27/stanford-parser-3.4.1-models.jar'
dep_parser = StanfordDependencyParser(
path_to_jar = path_jar, path_to_models_jar = path_models_jar
)
result = dep_parser.raw_parse('I shot an elephant in my sleep')
depndency = result.next()
list(dependency.triples())
Output
[
((u'shot', u'VBD'), u'nsubj', (u'I', u'PRP')),
((u'shot', u'VBD'), u'dobj', (u'elephant', u'NN')),
((u'elephant', u'NN'), u'det', (u'an', u'DT')),
((u'shot', u'VBD'), u'prep', (u'in', u'IN')),
((u'in', u'IN'), u'pobj', (u'sleep', u'NN')),
((u'sleep', u'NN'), u'poss', (u'my', u'PRP$'))
]
What is Chunking?
Chunking, one of the important processes in natural language processing, is used to identify parts of speech (POS) and short phrases. In other simple words, with chunking, we can get the structure of the sentence. It is also called partial parsing.
Chunk patterns and chinks
Chunk patterns are the patterns of part-of-speech (POS) tags that define what kind of words made up a chunk. We can define chunk patterns with the help of modified regular expressions.
Moreover, we can also define patterns for what kind of words should not be in a chunk and these unchunked words are known as chinks.
Implementation example
In the example below, along with the result of parsing the sentence “the book has many chapters”, there is a grammar for noun phrases that combines both a chunk and a chink pattern −
import nltk
sentence = [
("the", "DT"),
("book", "NN"),
("has","VBZ"),
("many","JJ"),
("chapters","NNS")
]
chunker = nltk.RegexpParser(
r'''
NP:{<DT><NN.*><.*>*<NN.*>}
}<VB.*>{
'''
)
chunker.parse(sentence)
Output = chunker.parse(sentence)
Output.draw()
Output
As seen above, the pattern for specifying a chunk is to use curly braces as follows −
{<DT><NN>}
And to specify a chink, we can flip the braces such as follows −
}<VB>{.
Now, for a particular phrase type, these rules can be combined into a grammar.
Information Extraction
We have gone through taggers as well as parsers that can be used to build information extraction engine. Let us see a basic information extraction pipeline −
Information extraction has many applications including −
- Business intelligence
- Resume harvesting
- Media analysis
- Sentiment detection
- Patent search
- Email scanning
Named-entity recognition (NER)
Named-entity recognition (NER) is actually a way of extracting some of most common entities like names, organizations, location, etc. Let us see an example that took all the preprocessing steps such as sentence tokenization, POS tagging, chunking, NER, and follows the pipeline provided in the figure above.
Example
Import nltk
file = open (
# provide here the absolute path for the file of text for which we want NER
)
data_text = file.read()
sentences = nltk.sent_tokenize(data_text)
tokenized_sentences = [nltk.word_tokenize(sentence) for sentence in sentences]
tagged_sentences = [nltk.pos_tag(sentence) for sentence in tokenized_sentences]
for sent in tagged_sentences:
print nltk.ne_chunk(sent)
Some of the modified Named-entity recognition (NER) can also be used to extract entities such as product names, bio-medical entities, brand name and much more.
Relation extraction
Relation extraction, another commonly used information extraction operation, is the process of extracting the different relationships between various entities. There can be different relationships like inheritance, synonyms, analogous, etc., whose definition depends on the information need. For example, suppose if we want to look for write of a book then the authorship would be a relation between the author name and book name.
Example
In the following example, we use the same IE pipeline, as shown in the above diagram, that we used till Named-entity relation (NER) and extend it with a relation pattern based on the NER tags.
import nltk
import re
IN = re.compile(r'.*\bin\b(?!\b.+ing)')
for doc in nltk.corpus.ieer.parsed_docs('NYT_19980315'):
for rel in nltk.sem.extract_rels('ORG', 'LOC', doc, corpus = 'ieer',
pattern = IN):
print(nltk.sem.rtuple(rel))
Output
[ORG: 'WHYY'] 'in' [LOC: 'Philadelphia']
[ORG: 'McGlashan & Sarrail'] 'firm in' [LOC: 'San Mateo']
[ORG: 'Freedom Forum'] 'in' [LOC: 'Arlington']
[ORG: 'Brookings Institution'] ', the research group in' [LOC: 'Washington']
[ORG: 'Idealab'] ', a self-described business incubator based in' [LOC: 'Los Angeles']
[ORG: 'Open Text'] ', based in' [LOC: 'Waterloo']
[ORG: 'WGBH'] 'in' [LOC: 'Boston']
[ORG: 'Bastille Opera'] 'in' [LOC: 'Paris']
[ORG: 'Omnicom'] 'in' [LOC: 'New York']
[ORG: 'DDB Needham'] 'in' [LOC: 'New York']
[ORG: 'Kaplan Thaler Group'] 'in' [LOC: 'New York']
[ORG: 'BBDO South'] 'in' [LOC: 'Atlanta']
[ORG: 'Georgia-Pacific'] 'in' [LOC: 'Atlanta']
In the above code, we have used an inbuilt corpus named ieer. In this corpus, the sentences are tagged till Named-entity relation (NER). Here we only need to specify the relation pattern that we want and the kind of NER we want the relation to define. In our example, we defined relationship between an organization and a location. We extracted all the combinations of these patterns.
Why transforming Chunks?
Till now we have got chunks or phrases from sentences but what are we supposed to do with them. One of the important tasks is to transform them. But why? It is to do the following −
- grammatical correction and
- rearranging phrases
Filtering insignificant/useless words
Suppose if you want to judge the meaning of a phrase then there are many commonly used words such as, ‘the’, ‘a’, are insignificant or useless. For example, see the following phrase −
‘The movie was good’.
Here the most significant words are ‘movie’ and ‘good’. Other words, ‘the’ and ‘was’ both are useless or insignificant. It is because without them also we can get the same meaning of the phrase. ‘Good movie’.
In the following python recipe, we will learn how to remove useless/insignificant words and keep the significant words with the help of POS tags.
Example
First, by looking through treebank corpus for stopwords we need to decide which part-of-speech tags are significant and which are not. Let us see the following table of insignificant words and tags −
Word | Tag |
---|---|
a | DT |
All | PDT |
An | DT |
And | CC |
Or | CC |
That | WDT |
The | DT |
From the above table, we can see other than CC, all the other tags end with DT which means we can filter out insignificant words by looking at the tag’s suffix.
For this example, we are going to use a function named filter() which takes a single chunk and returns a new chunk without any insignificant tagged words. This function filters out any tags that end with DT or CC.
Example
import nltk
def filter(chunk, tag_suffixes=['DT', 'CC']):
significant = []
for word, tag in chunk:
ok = True
for suffix in tag_suffixes:
if tag.endswith(suffix):
ok = False
break
if ok:
significant.append((word, tag))
return (significant)
Now, let us use this function filter() in our Python recipe to delete insignificant words −
from chunk_parse import filter
filter([('the', 'DT'),('good', 'JJ'),('movie', 'NN')])
Output
[('good', 'JJ'), ('movie', 'NN')]
Verb Correction
Many times, in real-world language we see incorrect verb forms. For example, ‘is you fine?’ is not correct. The verb form is not correct in this sentence. The sentence should be ‘are you fine?’ NLTK provides us the way to correct such mistakes by creating verb correction mappings. These correction mappings are used depending on whether there is a plural or singular noun in the chunk.
Example
To implement Python recipe, we first need to need define verb correction mappings. Let us create two mapping as follows −
Plural to Singular mappings
plural= {
('is', 'VBZ'): ('are', 'VBP'),
('was', 'VBD'): ('were', 'VBD')
}
Singular to Plural mappings
singular = {
('are', 'VBP'): ('is', 'VBZ'),
('were', 'VBD'): ('was', 'VBD')
}
As seen above, each mapping has a tagged verb which maps to another tagged verb. The initial mappings in our example cover the basic of mappings is to are, was to were, and vice versa.
Next, we will define a function named verbs(), in which you can pass a chink with incorrect verb form and ‘ll get a corrected chunk back. To get it done, verb() function uses a helper function named index_chunk() which will search the chunk for the position of the first tagged word.
Let us see these functions −
def index_chunk(chunk, pred, start = 0, step = 1):
l = len(chunk)
end = l if step > 0 else -1
for i in range(start, end, step):
if pred(chunk[i]):
return i
return None
def tag_startswith(prefix):
def f(wt):
return wt[1].startswith(prefix)
return f
def verbs(chunk):
vbidx = index_chunk(chunk, tag_startswith('VB'))
if vbidx is None:
return chunk
verb, vbtag = chunk[vbidx]
nnpred = tag_startswith('NN')
nnidx = index_chunk(chunk, nnpred, start = vbidx+1)
if nnidx is None:
nnidx = index_chunk(chunk, nnpred, start = vbidx-1, step = -1)
if nnidx is None:
return chunk
noun, nntag = chunk[nnidx]
if nntag.endswith('S'):
chunk[vbidx] = plural.get((verb, vbtag), (verb, vbtag))
else:
chunk[vbidx] = singular.get((verb, vbtag), (verb, vbtag))
return chunk
Save these functions in a Python file in your local directory where Python or Anaconda is installed and run it. I have saved it as verbcorrect.py.
Now, let us call verbs() function on a POS tagged is you fine chunk −
from verbcorrect import verbs
verbs([('is', 'VBZ'), ('you', 'PRP$'), ('fine', 'VBG')])
Output
[('are', 'VBP'), ('you', 'PRP$'), ('fine','VBG')]
Eliminating passive voice from phrases
Another useful task is to eliminate passive voice from phrases. This can be done with the help of swapping the words around a verb. For example, ‘the tutorial was great’ can be transformed into ‘the great tutorial’.
Example
To achieve this we are defining a function named eliminate_passive() that will swap the right-hand side of the chunk with the left-hand side by using the verb as the pivot point. In order to find the verb to pivot around, it will also use the index_chunk() function defined above.
def eliminate_passive(chunk):
def vbpred(wt):
word, tag = wt
return tag != 'VBG' and tag.startswith('VB') and len(tag) > 2
vbidx = index_chunk(chunk, vbpred)
if vbidx is None:
return chunk
return chunk[vbidx+1:] + chunk[:vbidx]
Now, let us call eliminate_passive() function on a POS tagged the tutorial was great chunk −
from passiveverb import eliminate_passive
eliminate_passive(
[
('the', 'DT'), ('tutorial', 'NN'), ('was', 'VBD'), ('great', 'JJ')
]
)
Output
[('great', 'JJ'), ('the', 'DT'), ('tutorial', 'NN')]
Swapping noun cardinals
As we know, a cardinal word such as 5, is tagged as CD in a chunk. These cardinal words often occur before or after a noun but for normalization purpose it is useful to put them before the noun always. For example, the date January 5 can be written as 5 January. Let us understand it with the following example.
Example
To achieve this we are defining a function named swapping_cardinals() that will swap any cardinal that occurs immediately after a noun with the noun. With this the cardinal will occur immediately before the noun. In order to do equality comparison with the given tag, it uses a helper function which we named as tag_eql().
def tag_eql(tag):
def f(wt):
return wt[1] == tag
return f
Now we can define swapping_cardinals() −
def swapping_cardinals (chunk):
cdidx = index_chunk(chunk, tag_eql('CD'))
if not cdidx or not chunk[cdidx-1][1].startswith('NN'):
return chunk
noun, nntag = chunk[cdidx-1]
chunk[cdidx-1] = chunk[cdidx]
chunk[cdidx] = noun, nntag
return chunk
Now, Let us call swapping_cardinals() function on a date “January 5” −
from Cardinals import swapping_cardinals()
swapping_cardinals([('Janaury', 'NNP'), ('5', 'CD')])
Output
[('10', 'CD'), ('January', 'NNP')]
10 January
Following are the two reasons to transform the trees −
- To modify deep parse tree and
- To flatten deep parse trees
Converting Tree or Subtree to Sentence
The first recipe we are going to discuss here is to convert a Tree or subtree back to a sentence or chunk string. This is very simple, let us see in the following example −
Example
from nltk.corpus import treebank_chunk
tree = treebank_chunk.chunked_sents()[2]
' '.join([w for w, t in tree.leaves()])
Output
'Rudolph Agnew , 55 years old and former chairman of Consolidated Gold Fields
PLC , was named a nonexecutive director of this British industrial
conglomerate .'
Deep tree flattening
Deep trees of nested phrases can’t be used for training a chunk hence we must flatten them before using. In the following example, we are going to use 3rd parsed sentence, which is deep tree of nested phrases, from the treebank corpus.
Example
To achieve this, we are defining a function named deeptree_flat() that will take a single Tree and will return a new Tree that keeps only the lowest level trees. In order to do most of the work, it uses a helper function which we named as childtree_flat().
from nltk.tree import Tree
def childtree_flat(trees):
children = []
for t in trees:
if t.height() < 3:
children.extend(t.pos())
elif t.height() == 3:
children.append(Tree(t.label(), t.pos()))
else:
children.extend(flatten_childtrees([c for c in t]))
return children
def deeptree_flat(tree):
return Tree(tree.label(), flatten_childtrees([c for c in tree]))
Now, let us call deeptree_flat() function on 3rd parsed sentence, which is deep tree of nested phrases, from the treebank corpus. We saved these functions in a file named deeptree.py.
from deeptree import deeptree_flat
from nltk.corpus import treebank
deeptree_flat(treebank.parsed_sents()[2])
Output
Tree('S', [Tree('NP', [('Rudolph', 'NNP'), ('Agnew', 'NNP')]),
(',', ','), Tree('NP', [('55', 'CD'),
('years', 'NNS')]), ('old', 'JJ'), ('and', 'CC'),
Tree('NP', [('former', 'JJ'),
('chairman', 'NN')]), ('of', 'IN'), Tree('NP', [('Consolidated', 'NNP'),
('Gold', 'NNP'), ('Fields', 'NNP'), ('PLC',
'NNP')]), (',', ','), ('was', 'VBD'),
('named', 'VBN'), Tree('NP-SBJ', [('*-1', '-NONE-')]),
Tree('NP', [('a', 'DT'), ('nonexecutive', 'JJ'), ('director', 'NN')]),
('of', 'IN'), Tree('NP',
[('this', 'DT'), ('British', 'JJ'),
('industrial', 'JJ'), ('conglomerate', 'NN')]), ('.', '.')])
Building Shallow tree
In the previous section, we flatten a deep tree of nested phrases by only keeping the lowest level subtrees. In this section, we are going to keep only the highest-level subtrees i.e. to build the shallow tree. In the following example we are going to use 3rd parsed sentence, which is deep tree of nested phrases, from the treebank corpus.
Example
To achieve this, we are defining a function named tree_shallow() that will eliminate all the nested subtrees by keeping only the top subtree labels.
from nltk.tree import Tree
def tree_shallow(tree):
children = []
for t in tree:
if t.height() < 3:
children.extend(t.pos())
else:
children.append(Tree(t.label(), t.pos()))
return Tree(tree.label(), children)
Now, let us call tree_shallow() function on 3rd parsed sentence, which is deep tree of nested phrases, from the treebank corpus. We saved these functions in a file named shallowtree.py.
from shallowtree import shallow_tree
from nltk.corpus import treebank
tree_shallow(treebank.parsed_sents()[2])
Output
Tree('S', [Tree('NP-SBJ-1', [('Rudolph', 'NNP'), ('Agnew', 'NNP'), (',', ','),
('55', 'CD'), ('years', 'NNS'), ('old', 'JJ'), ('and', 'CC'),
('former', 'JJ'), ('chairman', 'NN'), ('of', 'IN'), ('Consolidated', 'NNP'),
('Gold', 'NNP'), ('Fields', 'NNP'), ('PLC', 'NNP'), (',', ',')]),
Tree('VP', [('was', 'VBD'), ('named', 'VBN'), ('*-1', '-NONE-'), ('a', 'DT'),
('nonexecutive', 'JJ'), ('director', 'NN'), ('of', 'IN'), ('this', 'DT'),
('British', 'JJ'), ('industrial', 'JJ'), ('conglomerate', 'NN')]), ('.', '.')])
We can see the difference with the help of getting the height of the trees −
from nltk.corpus import treebank
tree_shallow(treebank.parsed_sents()[2]).height()
Output
3
from nltk.corpus import treebank
treebank.parsed_sents()[2].height()
Output
9
Tree labels conversion
In parse trees there are variety of Tree label types that are not present in chunk trees. But while using parse tree to train a chunker, we would like to reduce this variety by converting some of Tree labels to more common label types. For example, we have two alternative NP subtrees namely NP-SBL and NP-TMP. We can convert both of them into NP. Let us see how to do it in the following example.
Example
To achieve this we are defining a function named tree_convert() that takes following two arguments −
- Tree to convert
- A label conversion mapping
This function will return a new Tree with all matching labels replaced based on the values in the mapping.
from nltk.tree import Tree
def tree_convert(tree, mapping):
children = []
for t in tree:
if isinstance(t, Tree):
children.append(convert_tree_labels(t, mapping))
else:
children.append(t)
label = mapping.get(tree.label(), tree.label())
return Tree(label, children)
Now, let us call tree_convert() function on 3rd parsed sentence, which is deep tree of nested phrases, from the treebank corpus. We saved these functions in a file named converttree.py.
from converttree import tree_convert
from nltk.corpus import treebank
mapping = {'NP-SBJ': 'NP', 'NP-TMP': 'NP'}
convert_tree_labels(treebank.parsed_sents()[2], mapping)
Output
Tree('S', [Tree('NP-SBJ-1', [Tree('NP', [Tree('NNP', ['Rudolph']),
Tree('NNP', ['Agnew'])]), Tree(',', [',']),
Tree('UCP', [Tree('ADJP', [Tree('NP', [Tree('CD', ['55']),
Tree('NNS', ['years'])]),
Tree('JJ', ['old'])]), Tree('CC', ['and']),
Tree('NP', [Tree('NP', [Tree('JJ', ['former']),
Tree('NN', ['chairman'])]), Tree('PP', [Tree('IN', ['of']),
Tree('NP', [Tree('NNP', ['Consolidated']),
Tree('NNP', ['Gold']), Tree('NNP', ['Fields']),
Tree('NNP', ['PLC'])])])])]), Tree(',', [','])]),
Tree('VP', [Tree('VBD', ['was']),Tree('VP', [Tree('VBN', ['named']),
Tree('S', [Tree('NP', [Tree('-NONE-', ['*-1'])]),
Tree('NP-PRD', [Tree('NP', [Tree('DT', ['a']),
Tree('JJ', ['nonexecutive']), Tree('NN', ['director'])]),
Tree('PP', [Tree('IN', ['of']), Tree('NP',
[Tree('DT', ['this']), Tree('JJ', ['British']), Tree('JJ', ['industrial']),
Tree('NN', ['conglomerate'])])])])])])]), Tree('.', ['.'])])
What is text classification?
Text classification, as the name implies, is the way to categorize pieces of text or documents. But here the question arises that why we need to use text classifiers? Once examining the word usage in a document or piece of text, classifiers will be able to decide what class label should be assigned to it.
Binary Classifier
As name implies, binary classifier will decide between two labels. For example, positive or negative. In this the piece of text or document can either be one label or another, but not both.
Multi-label Classifier
Opposite to binary classifier, multi-label classifier can assign one or more labels to a piece of text or document.
Labeled Vs Unlabeled Feature set
A key-value mapping of feature names to feature values is called a feature set. Labeled feature sets or training data is very important for classification training so that it can later classify unlabeled feature set.
Labeled Feature Set | Unlabeled Feature Set |
---|---|
It is a tuple that look like (feat, label). | It is a feat itself. |
It is an instance with a known class label. | Without associated label, we can call it an instance. |
Used for training a classification algorithm. | Once trained, classification algorithm can classify an unlabeled feature set. |
Text Feature Extraction
Text feature extraction, as the name implies, is the process of transforming a list of words into a feature set that is usable by a classifier. We must have to transform our text into ‘dict’ style feature sets because Natural Language Tool Kit (NLTK) expect ‘dict’ style feature sets.
Bag of Words (BoW) model
BoW, one of the simplest models in NLP, is used to extract the features from piece of text or document so that it can be used in modeling such that in ML algorithms. It basically constructs a word presence feature set from all the words of an instance. The concept behind this method is that it doesn’t care about how many times a word occurs or about the order of the words, it only cares weather the word is present in a list of words or not.
Example
For this example, we are going to define a function named bow() −
def bow(words):
return dict([(word, True) for word in words])
Now, let us call bow() function on words. We saved this functions in a file named bagwords.py.
from bagwords import bow
bow(['we', 'are', 'using', 'tutorialspoint'])
Output
{'we': True, 'are': True, 'using': True, 'tutorialspoint': True}
Training classifiers
In previous sections, we learned how to extract features from the text. So now we can train a classifier. The first and easiest classifier is NaiveBayesClassifier class.
Naïve Bayes Classifier
To predict the probability that a given feature set belongs to a particular label, it uses Bayes theorem. The formula of Bayes theorem is as follows.
$$P(A|B)=\frac{P(B|A)P(A)}{P(B)}$$Here,
P(A|B) − It is also called the posterior probability i.e. the probability of first event i.e. A to occur given that second event i.e. B occurred.
P(B|A) − It is the probability of second event i.e. B to occur after first event i.e. A occurred.
P(A), P(B) − It is also called prior probability i.e. the probability of first event i.e. A or second event i.e. B to occur.
To train Naïve Bayes classifier, we will be using the movie_reviews corpus from NLTK. This corpus has two categories of text, namely: pos and neg. These categories make a classifier trained on them a binary classifier. Every file in the corpus is composed of two,one is positive movie review and other is negative movie review. In our example, we are going to use each file as a single instance for both training and testing the classifier.
Example
For training classifier, we need a list of labeled feature sets, which will be in the form [(featureset, label)]. Here the featureset variable is a dict and label is the known class label for the featureset. We are going to create a function named label_corpus() which will take a corpus named movie_reviewsand also a function named feature_detector, which defaults to bag of words. It will construct and returns a mapping of the form, {label: [featureset]}. After that we will use this mapping to create a list of labeled training instances and testing instances.
import collections
def label_corpus(corp, feature_detector=bow):
label_feats = collections.defaultdict(list)
for label in corp.categories():
for fileid in corp.fileids(categories=[label]):
feats = feature_detector(corp.words(fileids=[fileid]))
label_feats[label].append(feats)
return label_feats
With the help of above function we will get a mapping {label:fetaureset}. Now we are going to define one more function named split that will take a mapping returned from label_corpus() function and splits each list of feature sets into labeled training as well as testing instances.
def split(lfeats, split=0.75):
train_feats = []
test_feats = []
for label, feats in lfeats.items():
cutoff = int(len(feats) * split)
train_feats.extend([(feat, label) for feat in feats[:cutoff]])
test_feats.extend([(feat, label) for feat in feats[cutoff:]])
return train_feats, test_feats
Now, let us use these functions on our corpus, i.e. movie_reviews −
from nltk.corpus import movie_reviews
from featx import label_feats_from_corpus, split_label_feats
movie_reviews.categories()
Output
['neg', 'pos']
Example
lfeats = label_feats_from_corpus(movie_reviews)
lfeats.keys()
Output
dict_keys(['neg', 'pos'])
Example
train_feats, test_feats = split_label_feats(lfeats, split = 0.75)
len(train_feats)
Output
1500
Example
len(test_feats)
Output
500
We have seen that in movie_reviews corpus, there are 1000 pos files and 1000 neg files. We also end up with 1500 labeled training instances and 500 labeled testing instances.
Now let us train NaïveBayesClassifier using its train() class method −
from nltk.classify import NaiveBayesClassifier
NBC = NaiveBayesClassifier.train(train_feats)
NBC.labels()
Output
['neg', 'pos']
Decision Tree Classifier
Another important classifier is decision tree classifier. Here to train it the DecisionTreeClassifier class will create a tree structure. In this tree structure each node corresponds to a feature name and the branches correspond to the feature values. And down the branches we will get to the leaves of the tree i.e. the classification labels.
To train decision tree classifier, we will use the same training and testing features i.e. train_feats and test_feats, variables we have created from movie_reviews corpus.
Example
To train this classifier, we will call DecisionTreeClassifier.train() class method as follows −
from nltk.classify import DecisionTreeClassifier
decisiont_classifier = DecisionTreeClassifier.train(
train_feats, binary = True, entropy_cutoff = 0.8,
depth_cutoff = 5, support_cutoff = 30
)
accuracy(decisiont_classifier, test_feats)
Output
0.725
Maximum Entropy Classifier
Another important classifier is MaxentClassifier which is also known as a conditional exponential classifier or logistic regression classifier. Here to train it, the MaxentClassifier class will convert labeled feature sets to vector using encoding.
To train decision tree classifier, we will use the same training and testing features i.e. train_featsand test_feats, variables we have created from movie_reviews corpus.
Example
To train this classifier, we will call MaxentClassifier.train() class method as follows −
from nltk.classify import MaxentClassifier
maxent_classifier = MaxentClassifier
.train(train_feats,algorithm = 'gis', trace = 0, max_iter = 10, min_lldelta = 0.5)
accuracy(maxent_classifier, test_feats)
Output
0.786
Scikit-learn Classifier
One of the best machine learning (ML) libraries is Scikit-learn. It actually contains all sorts of ML algorithms for various purposes, but they all have the same fit design pattern as follows −
- Fitting the model to the data
- And use that model to make predictions
Rather than accessing scikit-learn models directly, here we are going to use NLTK’s SklearnClassifier class. This class is a wrapper class around a scikit-learn model to make it conform to NLTK’s Classifier interface.
We will follow following steps to train a SklearnClassifier class −
Step 1 − First we will create training features as we did in previous recipes.
Step 2 − Now, choose and import a Scikit-learn algorithm.
Step 3 − Next, we need to construct a SklearnClassifier class with the chosen algorithm.
Step 4 − Last, we will train SklearnClassifier class with our training features.
Let us implement these steps in the below Python recipe −
from nltk.classify.scikitlearn import SklearnClassifier
from sklearn.naive_bayes import MultinomialNB
sklearn_classifier = SklearnClassifier(MultinomialNB())
sklearn_classifier.train(train_feats)
<SklearnClassifier(MultinomialNB(alpha = 1.0,class_prior = None,fit_prior = True))>
accuracy(sk_classifier, test_feats)
Output
0.885
Measuring precision and recall
While training various classifiers we have measured their accuracy also. But apart from accuracy there are number of other metrics which are used to evaluate the classifiers. Two of these metrics are precision and recall.
Example
In this example, we are going to calculate precision and recall of the NaiveBayesClassifier class we trained earlier. To achieve this we will create a function named metrics_PR() which will take two arguments, one is the trained classifier and other is the labeled test features. Both the arguments are same as we passed while calculating the accuracy of the classifiers −
import collections
from nltk import metrics
def metrics_PR(classifier, testfeats):
refsets = collections.defaultdict(set)
testsets = collections.defaultdict(set)
for i, (feats, label) in enumerate(testfeats):
refsets[label].add(i)
observed = classifier.classify(feats)
testsets[observed].add(i)
precisions = {}
recalls = {}
for label in classifier.labels():
precisions[label] = metrics.precision(refsets[label],testsets[label])
recalls[label] = metrics.recall(refsets[label], testsets[label])
return precisions, recalls
Let us call this function to find the precision and recall −
from metrics_classification import metrics_PR
nb_precisions, nb_recalls = metrics_PR(nb_classifier,test_feats)
nb_precisions['pos']
Output
0.6713532466435213
Example
nb_precisions['neg']
Output
0.9676271186440678
Example
nb_recalls['pos']
Output
0.96
Example
nb_recalls['neg']
Output
0.478
Combination of classifier and voting
Combining classifiers is one of the best ways to improve classification performance. And voting is one of the best ways to combine multiple classifiers. For voting we need to have odd number of classifiers. In the following Python recipe we are going to combine three classifiers namely NaiveBayesClassifier class, DecisionTreeClassifier class and MaxentClassifier class.
To achieve this we are going to define a function named voting_classifiers() as follows.
import itertools
from nltk.classify import ClassifierI
from nltk.probability import FreqDist
class Voting_classifiers(ClassifierI):
def __init__(self, *classifiers):
self._classifiers = classifiers
self._labels = sorted(set(itertools.chain(*[c.labels() for c in classifiers])))
def labels(self):
return self._labels
def classify(self, feats):
counts = FreqDist()
for classifier in self._classifiers:
counts[classifier.classify(feats)] += 1
return counts.max()
Let us call this function to combine three classifiers and find the accuracy −
from vote_classification import Voting_classifiers
combined_classifier = Voting_classifiers(NBC, decisiont_classifier, maxent_classifier)
combined_classifier.labels()
Output
['neg', 'pos']
Example
accuracy(combined_classifier, test_feats)
Output
0.948
From the above output, we can see that the combined classifiers got highest accuracy than the individual classifiers.