ฉันจะสร้างแบบจำลองเพื่อแยกแยะทวีตเกี่ยวกับ Apple (Inc. ) จากทวีตเกี่ยวกับแอปเปิ้ล (ผลไม้) ได้อย่างไร


85

ดูด้านล่างสำหรับ 50 ทวีตเกี่ยวกับ "apple" ฉันติดป้ายกำกับการจับคู่เชิงบวกเกี่ยวกับ Apple Inc. ไว้ด้วยมือโดยมีเครื่องหมาย 1 ด้านล่าง

สองสามบรรทัดมีดังนี้

1|“@chrisgilmer: Apple targets big business with new iOS 7 features http://bit.ly/15F9JeF ”. Finally.. A corp iTunes account!
0|“@Zach_Paull: When did green skittles change from lime to green apple? #notafan” @Skittles
1|@dtfcdvEric: @MaroneyFan11 apple inc is searching for people to help and tryout all their upcoming tablet within our own net page No.
0|@STFUTimothy have you tried apple pie shine?
1|#SuryaRay #India Microsoft to bring Xbox and PC games to Apple, Android phones: Report: Microsoft Corp... http://dlvr.it/3YvbQx  @SuryaRay

นี่คือชุดข้อมูลทั้งหมด: http://pastebin.com/eJuEb4eB

ฉันต้องการสร้างโมเดลที่จัดประเภท "Apple" (Inc) จากส่วนที่เหลือ

ฉันไม่ได้มองหาภาพรวมทั่วไปของแมชชีนเลิร์นนิง แต่ฉันกำลังมองหาโมเดลจริงในโค้ด ( แนะนำให้ใช้Python )


18
โดยทั่วไปคุณต้องการสิ่งนี้: en.wikipedia.org/wiki/Bayesian_spam_filtering
eddi

1
คุณติดป้ายกำกับข้อมูลของคุณเอง แต่ต้องการไลบรารีที่ปรับขนาดได้ สิ่งนี้อยู่ภายใต้การดูแลหรือไม่ได้รับการดูแล?
dan

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

5
ตั้งชื่อรู้เอนทิตี: nlp.stanford.edu/software/CRF-NER.shtml
Neil McGuigan

1
@NeilMcGuigan. ฉันวางข้อความบางส่วนในการสาธิตของพวกเขา ( nlp.stanford.edu:8080/ner/process ) และรู้สึกประทับใจกับการที่โมเดลต่างๆจำแนกคำ
Ryan

คำตอบ:


39

ฉันจะทำดังนี้:

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

2
ขอบคุณสำหรับคำตอบของคุณเกี่ยวกับเรื่องนี้ คำตอบของคุณร่วมกับความคิดเห็นด้านบนช่วยให้ฉันแก้ปัญหาได้จริง คุณช่วยฉันปรับปรุงวิธีแก้ปัญหานี้ได้ไหม
SAL

10
นี่คือคำอธิบายอย่างไม่เป็นทางการเกี่ยวกับการจำแนกแบบเบย์
sanityinc

1
ฉันชอบ "การใช้รหัสหลอกของการจำแนกแบบเบย์" :)
AMADANON Inc.

73

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

โดยพื้นฐานแล้วจะดูที่เนื้อหาและบริบทของคำ (มองย้อนกลับไปและส่งต่อคำสองสามคำ) เพื่อประมาณความน่าจะเป็นที่คำนั้นเป็นเอนทิตีที่มีชื่อ

ซอฟต์แวร์ที่ดีสามารถดูคุณสมบัติอื่น ๆ ของคำเช่นความยาวหรือรูปร่าง (เช่น "Vcv" หากขึ้นต้นด้วย "สระ - พยัญชนะ - สระ")

ห้องสมุดที่ดีมาก (GPL) คือNER ของ Stanford

นี่คือการสาธิต: http://nlp.stanford.edu:8080/ner/

ตัวอย่างข้อความที่จะลอง:

ฉันกินแอปเปิ้ลที่สำนักงานใหญ่ของ Apple และคิดถึง Apple Martin ลูกสาวของ Coldplay

(ตัวแยกประเภท 3class และ 4class ทำให้ถูกต้อง)


5
นั่นน่าสนใจจริงๆ เป็นไปได้ไหมที่จะดูรหัสสำหรับenglish.conll.4class.distsim.crf.ser.gz? ฉันชอบที่จะเห็นว่าใครสร้างอะไรแบบนี้
Ryan

รหัสสำหรับ NER เป็นโอเพ่นซอร์ส แต่ข้อมูลที่ใช้ในการประชุม CONLL ไม่ใช่ อย่างไรก็ตามคุณสามารถค้นหา Reuters Corpus ทางออนไลน์ได้ที่ NIST
Neil McGuigan

31

ฉันมีระบบกึ่งทำงานที่ช่วยแก้ปัญหานี้ซึ่งเปิดแหล่งที่มาโดยใช้ scikit-learn โดยมีบล็อกโพสต์ที่อธิบายถึงสิ่งที่ฉันกำลังทำอยู่ ปัญหาที่ฉันกำลังแก้ไขคือการเปลี่ยนความหมายของคำ (การเลือกหนึ่งในตัวเลือกความรู้สึกหลายคำ ) ซึ่งไม่เหมือนกับการรับรู้เอนทิตีที่มีชื่อ แนวทางพื้นฐานของฉันค่อนข้างแข่งขันกับโซลูชันที่มีอยู่และ (สำคัญมาก) สามารถปรับแต่งได้

มีเครื่องมือ NER เชิงพาณิชย์ที่มีอยู่ (OpenCalais, DBPedia Spotlight และ AlchemyAPI) ที่อาจให้ผลลัพธ์ทางการค้าที่ดีพอ - ลองทำก่อน!

ฉันใช้สิ่งเหล่านี้สำหรับโครงการของลูกค้า (ฉันปรึกษาโดยใช้ NLP / ML ในลอนดอน) แต่ฉันไม่พอใจกับการเรียกคืน ( ความแม่นยำและการจำ ) โดยทั่วไปแล้วพวกเขาสามารถพูดได้อย่างแม่นยำ (เมื่อพวกเขาพูดว่า "นี่คือ Apple Inc" มักจะถูกต้อง) แต่มีการเรียกคืนต่ำ (พวกเขาไม่ค่อยพูดว่า "นี่คือ Apple Inc" แม้ว่าจะเป็นทวีตของมนุษย์กับ Apple Inc ก็ตาม ฉันคิดว่ามันเป็นแบบฝึกหัดที่น่าสนใจทางสติปัญญาในการสร้างเวอร์ชันโอเพ่นซอร์สที่เหมาะกับทวีต นี่คือรหัสปัจจุบัน: https://github.com/ianozsvald/social_media_brand_disambiguator

ฉันจะสังเกตว่า - ฉันไม่ได้พยายามแก้ปัญหาการลดทอนความหมายของคำทั่วไปด้วยวิธีนี้เพียงแค่การลดความสับสนของตราสินค้า (บริษัท ผู้คน ฯลฯ ) เมื่อคุณมีชื่อแล้ว นั่นเป็นเหตุผลที่ฉันเชื่อว่าแนวทางที่ตรงไปตรงมานี้จะได้ผล

ฉันเริ่มต้นเมื่อหกสัปดาห์ที่แล้วและเขียนด้วย Python 2.7 โดยใช้ scikit-learn มันใช้วิธีการพื้นฐานมาก ฉัน Vectorize ใช้ไบนารีนับ vectorizer (ฉันจะนับเฉพาะไม่ว่าจะเป็นคำที่ปรากฏไม่กี่ครั้ง) 1-3  n-กรัม ฉันไม่ได้ปรับขนาดด้วย TF-IDF (TF-IDF นั้นดีเมื่อคุณมีความยาวเอกสารที่แปรผันสำหรับฉันทวีตมีเพียงหนึ่งหรือสองประโยคและผลการทดสอบของฉันไม่ได้แสดงให้เห็นถึงการปรับปรุงด้วย TF-IDF)

ฉันใช้ tokenizer พื้นฐานซึ่งเป็นพื้นฐานมาก แต่มีประโยชน์อย่างน่าประหลาดใจ มันละเว้น @ # (ดังนั้นคุณจะสูญเสียบริบทบางส่วน) และแน่นอนว่าจะไม่ขยาย URL จากนั้นฉันก็ฝึกโดยใช้การถดถอยโลจิสติกส์และดูเหมือนว่าปัญหานี้ค่อนข้างแยกกันเป็นเชิงเส้น (ไม่มีคำศัพท์มากมายสำหรับคลาสหนึ่งสำหรับอีกคลาส) ตอนนี้ฉันกำลังหลีกเลี่ยงการอุด / ทำความสะอาดใด ๆ (ฉันกำลังพยายามสิ่งที่ง่ายที่สุดที่อาจได้ผล)

โค้ดนี้มี README เต็มรูปแบบและคุณควรจะนำเข้าทวีตของคุณได้ค่อนข้างง่ายจากนั้นทำตามคำแนะนำของฉันสำหรับการทดสอบ

สิ่งนี้ใช้ได้กับ Apple เนื่องจากผู้คนไม่กินหรือดื่มคอมพิวเตอร์ของ Apple และเราไม่พิมพ์หรือเล่นกับผลไม้ดังนั้นคำจึงถูกแบ่งออกเป็นหมวดหมู่หนึ่งหรืออีกประเภทหนึ่งได้อย่างง่ายดาย เงื่อนไขนี้อาจไม่เกิดขึ้นเมื่อพิจารณาบางอย่างเช่น #definance สำหรับรายการทีวี (ซึ่งผู้คนยังใช้ #definance ที่เกี่ยวข้องกับ Arab Spring, การแข่งขันคริกเก็ต, การแก้ไขข้อสอบและวงดนตรี) อาจจำเป็นต้องใช้วิธีการ Cleverer ที่นี่

ฉันมีบล็อกโพสต์หลายชุดที่อธิบายโครงการนี้รวมถึงการนำเสนอหนึ่งชั่วโมงที่ฉันให้ที่กลุ่มผู้ใช้ BrightonPython (ซึ่งกลายเป็นงานนำเสนอที่สั้นกว่าสำหรับ 140 คนที่ DataScienceLondon)

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

นี่คือแนวทางอัลกอริทึมที่เป็นไปได้โดยใช้ scikit-learn:

  • ใช้ Binary CountVectorizer (ฉันไม่คิดว่าการนับระยะในข้อความสั้น ๆ จะเพิ่มข้อมูลได้มากเนื่องจากคำส่วนใหญ่เกิดขึ้นเพียงครั้งเดียว)
  • เริ่มต้นด้วยลักษณนามแผนผังการตัดสินใจ มันจะมีประสิทธิภาพที่อธิบายได้ (ดูตัวอย่างการใส่โครงสร้างการตัดสินใจมากเกินไป)
  • ย้ายไปที่การถดถอยโลจิสติก
  • ตรวจสอบข้อผิดพลาดที่สร้างโดยตัวแยกประเภท (อ่านเอาต์พุตที่ส่งออกของ DecisionTree หรือดูที่ค่าสัมประสิทธิ์ใน LogisticRegression ทำงานทวีตที่จัดประเภทผิดกลับผ่าน Vectorizer เพื่อดูว่าการแสดง Bag of Words ที่อยู่ด้านล่างเป็นอย่างไร - จะมีโทเค็นน้อยกว่า คุณเริ่มต้นด้วยทวีตดิบ - มีเพียงพอสำหรับการจำแนกหรือไม่)
  • ดูโค้ดตัวอย่างของฉันในhttps://github.com/ianozsvald/social_media_brand_disambiguator/blob/master/learn1.pyสำหรับแนวทางนี้

สิ่งที่ควรพิจารณา:

  • คุณต้องมีชุดข้อมูลที่ใหญ่ขึ้น ฉันใช้ทวีตที่มีป้ายกำกับ 2,000 รายการ (ใช้เวลาห้าชั่วโมง) และอย่างน้อยที่สุดคุณต้องการชุดที่สมดุลโดยมี> 100 ต่อคลาส (ดูหมายเหตุที่เหมาะสมด้านล่าง)
  • ปรับปรุงโทเค็น (ง่ายมากด้วย scikit-learn) เพื่อเก็บ # @ ไว้ในโทเค็นและอาจเพิ่มตัวตรวจจับแบรนด์ที่เป็นตัวพิมพ์ใหญ่ (ตามหมายเหตุของผู้ใช้ @ user2425429)
  • พิจารณาตัวแยกประเภทที่ไม่ใช่เชิงเส้น (เช่นคำแนะนำของ @ oiez ด้านบน) เมื่อสิ่งต่างๆยากขึ้น โดยส่วนตัวแล้วฉันพบว่า LinearSVC ทำได้แย่กว่าการถดถอยโลจิสติก (แต่นั่นอาจเป็นเพราะพื้นที่คุณลักษณะมิติสูงที่ฉันยังไม่ลด)
  • ส่วนทวีตเฉพาะของแท็กเกอร์คำพูด (ในความเห็นที่ต่ำต้อยของฉันไม่ใช่ของ Standford ตามที่ @Neil แนะนำ - มันทำงานได้ไม่ดีกับไวยากรณ์ Twitter ที่ไม่ดีในประสบการณ์ของฉัน)
  • เมื่อคุณมีโทเค็นจำนวนมากคุณอาจต้องการลดขนาด (ฉันยังไม่ได้ลอง - ดูโพสต์บล็อกของฉันเกี่ยวกับการลงโทษ LogisticRegression l1 l2)

เรื่อง ฟิตติ้งมากเกินไป ในชุดข้อมูลของฉันที่มี 2,000 รายการฉันมีสแนปชอต 10 นาทีจาก Twitter ของทวีต 'apple' ทวีตประมาณ 2/3 สำหรับ Apple Inc ส่วน 1/3 สำหรับการใช้งานอื่น ๆ ของ Apple ฉันดึงชุดย่อยที่สมดุลออกมา (ประมาณ 584 แถวที่ฉันคิด) ของแต่ละชั้นเรียนและทำการตรวจสอบความถูกต้องไขว้ห้าเท่าสำหรับการฝึกอบรม

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


ฉันไม่มีความสุขในการดูรหัสของคุณและพยายามทำซ้ำ / เลียนแบบ / ให้ความรู้ แต่ฉันต้องขอโทษคุณที่ไม่ได้ให้รางวัล 50 แต้มเต็ม ฉันไม่อยู่ที่ SO ในช่วงสุดสัปดาห์และพลาดกำหนดส่งรางวัล โชคดีที่ชุมชน SO ก้าวเข้ามาและเห็นว่าเหมาะสมที่จะมอบรางวัล 25 คะแนนให้คุณ
Ryan

1
ไม่มีปัญหา :-) รหัส README และบล็อกโพสต์ควรให้แนวคิดเกี่ยวกับแนวทางของฉัน มันเป็นเรื่องง่ายอย่างจงใจ แต่ดูเหมือนจะใช้ได้
Ian Ozsvald

12

คุณสามารถทำสิ่งต่อไปนี้:

  1. สร้างคำตามคำบอกที่มีจำนวนการเกิดขึ้นในทวีตที่เกี่ยวข้องกับผลไม้และ บริษัท สิ่งนี้สามารถทำได้โดยการป้อนทวีตตัวอย่างที่เรารู้จัก

  2. เมื่อใช้ข้อมูลก่อนหน้านี้เพียงพอเราสามารถค้นหาความน่าจะเป็นของคำที่เกิดขึ้นในทวีตเกี่ยวกับ apple inc

  3. คูณความน่าจะเป็นของคำแต่ละคำเพื่อให้ได้ความน่าจะเป็นของทวีตทั้งหมด

ตัวอย่างที่เรียบง่าย:

p_f = ความน่าจะเป็นของทวีตผลไม้

p_w_f = ความน่าจะเป็นของคำที่เกิดขึ้นในทวีตผลไม้

p_t_f = ความน่าจะเป็นรวมของคำทั้งหมดในทวีตที่เกิดทวีตผลไม้ = p_w1_f * p_w2_f * ...

p_f_t = ความน่าจะเป็นของผลไม้ในทวีตเฉพาะ

p_c, p_w_c, p_t_c, p_c_tเป็นค่าตามลำดับสำหรับ บริษัท

มีการเพิ่ม Laplacian ที่นุ่มนวลขึ้นของค่า 1 เพื่อขจัดปัญหาเรื่องความถี่ศูนย์ของคำใหม่ที่ไม่มีในฐานข้อมูลของเรา

old_tweets = {'apple pie sweet potatoe cake baby https://vine.co/v/hzBaWVA3IE3': '0', ...}
known_words = {}
total_company_tweets = total_fruit_tweets =total_company_words = total_fruit_words = 0

for tweet in old_tweets:
    company = old_tweets[tweet]
    for word in tweet.lower().split(" "):
        if not word in known_words:
            known_words[word] = {"company":0, "fruit":0 }
        if company == "1":
            known_words[word]["company"] += 1
            total_company_words += 1
        else:
            known_words[word]["fruit"] += 1
            total_fruit_words += 1

    if company == "1":
        total_company_tweets += 1
    else:
        total_fruit_tweets += 1
total_tweets = len(old_tweets)

def predict_tweet(new_tweet,K=1):
    p_f = (total_fruit_tweets+K)/(total_tweets+K*2)
    p_c = (total_company_tweets+K)/(total_tweets+K*2)
    new_words = new_tweet.lower().split(" ")

    p_t_f = p_t_c = 1
    for word in new_words:
        try:
            wordFound = known_words[word]
        except KeyError:
            wordFound = {'fruit':0,'company':0}
        p_w_f = (wordFound['fruit']+K)/(total_fruit_words+K*(len(known_words)))
        p_w_c = (wordFound['company']+K)/(total_company_words+K*(len(known_words)))
    p_t_f *= p_w_f
    p_t_c *= p_w_c

    #Applying bayes rule
    p_f_t = p_f * p_t_f/(p_t_f*p_f + p_t_c*p_c)
    p_c_t = p_c * p_t_c/(p_t_f*p_f + p_t_c*p_c)
    if p_c_t > p_f_t:
        return "Company"
    return "Fruit"

9

หากคุณไม่มีปัญหาในการใช้ห้องสมุดภายนอกฉันขอแนะนำให้ใช้scikit-learnเนื่องจากอาจทำได้ดีกว่าและเร็วกว่าทุกสิ่งที่คุณสามารถเขียนโค้ดด้วยตัวเอง ฉันจะทำสิ่งนี้:

สร้างคลังข้อมูลของคุณ ฉันได้ทำความเข้าใจรายการเพื่อความชัดเจน แต่ขึ้นอยู่กับวิธีการจัดเก็บข้อมูลของคุณคุณอาจต้องทำสิ่งต่างๆ:

def corpus_builder(apple_inc_tweets, apple_fruit_tweets):
    corpus = [tweet for tweet in apple_inc_tweets] + [tweet for tweet in apple_fruit_tweets]
    labels = [1 for x in xrange(len(apple_inc_tweets))] + [0 for x in xrange(len(apple_fruit_tweets))]
    return (corpus, labels)

สิ่งสำคัญคือคุณมีสองรายการที่มีลักษณะดังนี้:

([['apple inc tweet i love ios and iphones'], ['apple iphones are great'], ['apple fruit tweet i love pie'], ['apple pie is great']], [1, 1, 0, 0])

[1, 1, 0, 0] แสดงถึงป้ายกำกับที่เป็นบวกและลบ

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

def train(corpus, labels)
    pipe = Pipeline([('vect', CountVectorizer(ngram_range=(1, 3), stop_words='english')),
                        ('tfidf', TfidfTransformer(norm='l2')),
                        ('clf', LinearSVC()),])
    pipe.fit_transform(corpus, labels)
    return pipe

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

สุดท้ายคุณทำนายหมวดหมู่ของทวีต:

def predict(pipe, tweet):
    prediction = pipe.predict([tweet])
    return prediction

อีกครั้งทวีตต้องอยู่ในรายการดังนั้นฉันคิดว่ามันกำลังเข้าสู่ฟังก์ชันเป็นสตริง

ใส่ข้อมูลทั้งหมดลงในชั้นเรียนหรืออะไรก็ได้เท่านี้ก็เสร็จเรียบร้อย อย่างน้อยด้วยตัวอย่างพื้นฐานนี้

ฉันไม่ได้ทดสอบโค้ดนี้ดังนั้นจึงอาจใช้ไม่ได้หากคุณแค่คัดลอก - วาง แต่ถ้าคุณต้องการใช้ scikit-learn ควรให้แนวคิดว่าจะเริ่มจากตรงไหน

แก้ไข: พยายามอธิบายขั้นตอนโดยละเอียดเพิ่มเติม


6

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

หากคุณต้องการเล่นกับความเป็นไปได้บางอย่างคุณสามารถใช้รหัสต่อไปนี้ซึ่งต้องติดตั้ง nltk นอกจากนี้หนังสือ nltk ยังมีให้บริการทางออนไลน์อย่างอิสระดังนั้นคุณอาจต้องการอ่านเล็กน้อยเกี่ยวกับวิธีการทำงานทั้งหมดนี้: http://nltk.googlecode.com/svn/trunk/doc/book/ch06.html

#coding: utf-8
import nltk
import random
import re

def get_split_sets():
    structured_dataset = get_dataset()
    train_set = set(random.sample(structured_dataset, int(len(structured_dataset) * 0.7)))
    test_set = [x for x in structured_dataset if x not in train_set]

    train_set = [(tweet_features(x[1]), x[0]) for x in train_set]
    test_set = [(tweet_features(x[1]), x[0]) for x in test_set]
    return (train_set, test_set)

def check_accurracy(times=5):
    s = 0
    for _ in xrange(times):
        train_set, test_set = get_split_sets()
        c = nltk.classify.DecisionTreeClassifier.train(train_set)
        # Uncomment to use a naive bayes classifier instead
        #c = nltk.classify.NaiveBayesClassifier.train(train_set)
        s += nltk.classify.accuracy(c, test_set)

    return s / times


def remove_urls(tweet):
    tweet = re.sub(r'http:\/\/[^ ]+', "", tweet)
    tweet = re.sub(r'pic.twitter.com/[^ ]+', "", tweet)
    return tweet

def tweet_features(tweet):
    words = [x for x in nltk.tokenize.wordpunct_tokenize(remove_urls(tweet.lower())) if x.isalpha()]
    features = dict()
    for bigram in nltk.bigrams(words):
        features["hasBigram(%s)" % ",".join(bigram)] = True
    for trigram in nltk.trigrams(words):
        features["hasTrigram(%s)" % ",".join(trigram)] = True  
    return features

def get_dataset():
    dataset = """copy dataset in here
"""
    structured_dataset = [('fruit' if x[0] == '0' else 'company', x[2:]) for x in dataset.splitlines()]
    return structured_dataset

if __name__ == '__main__':
    print check_accurracy()

1
วิธีนี้ทำงานอย่างไร ฉันไม่เห็น "คุณลักษณะที่คุณเลือก" ในรหัสของคุณ มันเลือกคุณสมบัติโดยอัตโนมัติตามชุดการฝึกอบรมหรือไม่? หรือเก็บไว้ที่dict()อื่น? ฉันคิดว่าถ้าชุดฝึกของคน ๆ หนึ่งมีขนาดใหญ่พอคอมพิวเตอร์ก็ไม่ควรจะคิดคุณสมบัติออกมาได้หรือไม่? (ไม่ได้รับการดูแล?)
Ryan

2
คุณสมบัติถูกแยกออกโดยใช้ฟังก์ชันทวีต _ คุณลักษณะ โดยทั่วไปจะลบ url ออกจากทวีตจากนั้นสร้าง feature dict ที่มีรายการอ่านบางอย่างเช่น 'hasBigram (foo, bar)' = True
Paul Dubs

1
ดังนั้น'hasBigram(foo,bar)' = Trueที่สตริงทวีตรวมถึงfoo bar? ดังนั้นจึงสร้าง bigrams และ trigrams สำหรับแต่ละทวีตและตั้งค่าสถานะไว้ในคุณลักษณะเชิงบวกdict()? ดังนั้นเมื่อทวีต"alpha beta gamma delta"มันจะสร้างคำสั่ง () bigrams สำหรับalpha,beta; beta,gamma; and gamma,delta;และ trigrams สำหรับalpha,beta,gammaและbeta,gamma,delta? และจากค่าไบและไตรกรัมที่เป็นบวกและลบที่กำหนดทรีตัดสินใจหรือเบย์สามารถทำเวทมนตร์ได้
Ryan

2
ตรง เมื่อใช้ลักษณนามเบย์คุณยังสามารถรับคุณสมบัติที่เป็นประโยชน์สูงสุดได้โดยเรียก "show_most_informative_features ()"
Paul Dubs

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

5

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

<?php

// Confusion Matrix Init
$tp = 0;
$fp = 0;
$fn = 0;
$tn = 0;
$arrFP = array();
$arrFN = array();

// Load All Tweets to string
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://pastebin.com/raw.php?i=m6pP8ctM');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$strCorpus = curl_exec($ch);
curl_close($ch);

// Load Tweets as Array
$arrCorpus = explode("\n", $strCorpus);
foreach ($arrCorpus as $k => $v) {
    // init
    $blnActualClass = substr($v,0,1);
    $strTweet = trim(substr($v,2));

    // Score Tweet
    $intScore = score($strTweet);

    // Build Confusion Matrix and Log False Positives & Negatives for Review
    if ($intScore > 0) {
        if ($blnActualClass == 1) {
            // True Positive
            $tp++;
        } else {
            // False Positive
            $fp++;
            $arrFP[] = $strTweet;
        }
    } else {
        if ($blnActualClass == 1) {
            // False Negative
            $fn++;
            $arrFN[] = $strTweet;
        } else {
            // True Negative
            $tn++;
        }
    }
}

// Confusion Matrix and Logging
echo "
           Predicted
            1     0
Actual 1   $tp     $fp
Actual 0    $fn    $tn

";

if (count($arrFP) > 0) {
    echo "\n\nFalse Positives\n";
    foreach ($arrFP as $strTweet) {
        echo "$strTweet\n";
    }
}

if (count($arrFN) > 0) {
    echo "\n\nFalse Negatives\n";
    foreach ($arrFN as $strTweet) {
        echo "$strTweet\n";
    }
}

function LoadDictionaryArray() {
    $strDictionary = <<<EOD
10|iTunes
10|ios 7
10|ios7
10|iPhone
10|apple inc
10|apple corp
10|apple.com
10|MacBook
10|desk top
10|desktop
1|config
1|facebook
1|snapchat
1|intel
1|investor
1|news
1|labs
1|gadget
1|apple store
1|microsoft
1|android
1|bonds
1|Corp.tax
1|macs
-1|pie
-1|clientes
-1|green apple
-1|banana
-10|apple pie
EOD;

    $arrDictionary = explode("\n", $strDictionary);
    foreach ($arrDictionary as $k => $v) {
        $arr = explode('|', $v);
        $arrDictionary[$k] = array('value' => $arr[0], 'term' => strtolower(trim($arr[1])));
    }
    return $arrDictionary;
}

function score($str) {
    $str = strtolower($str);
    $intScore = 0;
    foreach (LoadDictionaryArray() as $arrDictionaryItem) {
        if (strpos($str,$arrDictionaryItem['term']) !== false) {
            $intScore += $arrDictionaryItem['value'];
        }
    }
    return $intScore;
}
?>

ผลลัพธ์ข้างต้น:

           Predicted
            1     0
Actual 1   31     1
Actual 0    1    17


False Positives
1|Royals apple #ASGame @mlb @ News Corp Building http://instagram.com/p/bBzzgMrrIV/


False Negatives
-1|RT @MaxFreixenet: Apple no tiene clientes. Tiene FANS// error.... PAGAS por productos y apps, ergo: ERES CLIENTE.

4

ในตัวอย่างทั้งหมดที่คุณให้มา Apple (inc) อาจเรียกว่าA pple หรือ apple incดังนั้นวิธีที่เป็นไปได้คือการค้นหา:

  • เมืองหลวง "A" ใน Apple

  • "inc" หลังแอปเปิ้ล

  • คำ / วลีเช่น "OS", "operating system", "Mac", "iPhone", ...

  • หรือการรวมกันของพวกเขา


1
ในฟังก์ชั่นนี้ฉันใช้ strtolower เพื่อกรองตัวพิมพ์ใหญ่ออกไป ดิบเล็กน้อย แต่ได้ผล
SAL

@SAL ฉันไม่ได้คาดหวังว่ามันจะมีประโยชน์มากนัก แต่ถ้าคุณมีเวลา จำกัด ...
user2425429

4

เพื่อให้คำตอบง่ายขึ้นตามเงื่อนไขสุ่มฟิลด์เล็กน้อย ... บริบทมีมากที่นี่ คุณจะต้องเลือกในทวีตที่แสดงให้เห็นอย่างชัดเจนว่า บริษัท Apple เทียบกับแอปเปิ้ลผลไม้ ผมขอสรุปรายการคุณสมบัติที่อาจเป็นประโยชน์สำหรับคุณในการเริ่มต้น สำหรับข้อมูลเพิ่มเติมให้ค้นหาการแบ่งวลีคำนามและสิ่งที่เรียกว่าป้ายกำกับ BIO ดู ( http://www.cis.upenn.edu/~pereira/papers/crf.pdf )

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

คุณสมบัติอื่น ๆ ที่จะได้รับจากคำรอบ ๆ ได้แก่ :

ไม่ว่าจะเป็นตัวละครตัวแรกเป็นทุน

ไม่ว่าอักขระสุดท้ายในคำจะเป็นช่วงเวลาหรือไม่

ส่วนของคำพูดของคำ (ค้นหาส่วนหนึ่งของการติดแท็กคำพูด)

ข้อความของคำ

ฉันไม่แนะนำสิ่งนี้ แต่จะให้ตัวอย่างเพิ่มเติมของคุณสมบัติเฉพาะสำหรับ Apple:

WordIs (Apple)

NextWordIs (Inc.)

คุณจะได้รับจุด คิดว่าการรับรู้เอนทิตีที่ตั้งชื่อเป็นการอธิบายลำดับจากนั้นใช้คณิตศาสตร์เพื่อบอกคอมพิวเตอร์ว่าจะคำนวณสิ่งนั้นอย่างไร

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

ทั้งหมดนี้คือรายการคุณสมบัติที่คุณสามารถใช้ในรุ่นของคุณเพื่อระบุสิ่งที่คุณกำลังมองหา


3

มีไลบรารีที่ดีมากสำหรับการประมวลผลข้อความภาษาธรรมชาติในPython ที่เรียกว่าnltk. คุณควรดูที่มัน

กลยุทธ์หนึ่งที่คุณสามารถลองทำได้คือดู n-grams (กลุ่มคำ) ที่มีคำว่า "apple" อยู่ในนั้น คำบางคำมีแนวโน้มที่จะใช้ถัดจาก "แอปเปิ้ล" เมื่อพูดถึงผลไม้คำอื่น ๆ เมื่อพูดถึง บริษัท และคุณสามารถใช้คำเหล่านั้นเพื่อจัดหมวดหมู่ทวีตได้


1
ขอบคุณ Manetheran ฉันไม่ใช่ผู้โพสต์ต้นฉบับ แต่ฉันก็สนใจคำตอบเช่นกัน สำหรับเงินรางวัลฉันกำลังมองหารหัสบางอย่าง (แม้จะใช้nltk) ที่สามารถช่วยให้ฉันเริ่มต้นในทิศทางที่ถูกต้องด้วยงานแมชชีนเลิร์นนิงที่ "สวัสดีชาวโลก" Apple (inc) เทียบกับ apple (ผลไม้) ดูเหมือนจะเป็นการมอบหมายงานที่สมบูรณ์แบบ
Ryan

3

ใช้LibShortText Python ตัวนี้ยูทิลิตี้ได้รับการปรับแต่งให้ทำงานสำหรับงานจัดหมวดหมู่ข้อความสั้น ๆ แล้วและทำงานได้ดี สูงสุดที่คุณต้องทำคือเขียนวนซ้ำเพื่อเลือกชุดค่าสถานะที่ดีที่สุด ฉันใช้มันเพื่อทำการจำแนกประเภทการพูดภายใต้การดูแลในอีเมลและผลลัพธ์มีความแม่นยำสูงถึง 95-97% (ระหว่างการตรวจสอบความถูกต้องข้าม 5 เท่า!)

และมาจากผู้ผลิตLIBSVMและLIBLINEARซึ่งมีการใช้งาน support vector machine (SVM) ใน sklearn และ cran ดังนั้นคุณจึงมั่นใจได้อย่างสมเหตุสมผลว่าการนำไปใช้งานนั้นไม่ได้มีปัญหา


2

สร้างตัวกรอง AI เพื่อแยกความแตกต่างของApple Inc (บริษัท ) จากแอปเปิล (ผลไม้) เนื่องจากสิ่งเหล่านี้คือทวีตให้กำหนดชุดการฝึกของคุณด้วยเวกเตอร์ 140 ฟิลด์โดยแต่ละฟิลด์จะเป็นอักขระที่เขียนในทวีตที่ตำแหน่ง X (0 ถึง 139) ถ้าทวีตสั้นกว่าให้ใส่ค่าว่าง

จากนั้นสร้างชุดฝึกให้ใหญ่พอที่จะได้ความแม่นยำที่ดี (ตามรสนิยมของคุณ) กำหนดค่าผลให้แต่ละทวีตเป็นแอปเปิ้ลอิงค์ทวีตแถม 1 (จริง) และทวีตแอปเปิ้ล (ผลไม้) ได้รับ 0. มันจะเป็นกรณีของการเรียนรู้ภายใต้การดูแลในการถดถอยโลจิสติก

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

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

ลองCourseraหลักสูตรการเรียนรู้เครื่องโดยแอนดรูอึ้ง คุณจะได้เรียนรู้แมชชีนเลิร์นนิงบนMATLABหรือOctaveแต่เมื่อคุณมีพื้นฐานแล้วคุณจะสามารถเขียนแมชชีนเลิร์นนิงในภาษาใดก็ได้หากคุณเข้าใจคณิตศาสตร์อย่างง่าย (อย่างง่ายในการถดถอยโลจิสติกส์)

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


ขอบคุณ Fawar ฉันหวังว่าจะมีรหัสบางอย่างเกี่ยวกับ "hello world" เพื่อจุดประสงค์นี้ - เพื่อเรียนรู้วิธีการทำงานของ ML ฉันจะดูชั้นเรียน ดูดี.
Ryan

0

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

ผมคิดว่าเส้นทางที่เร็วที่สุดเพื่อผลจะ spacy + อัจฉริยะ Spacy ได้คิดแบบจำลองสำหรับภาษาอังกฤษมาเป็นอย่างดีดังนั้นคุณจึงไม่จำเป็นต้องสร้างขึ้นเอง ในขณะที่อัจฉริยะช่วยให้สร้างชุดข้อมูลการฝึกอบรมและปรับแต่งโมเดล spacy ได้อย่างรวดเร็วตามความต้องการของคุณ

หากคุณมีตัวอย่างเพียงพอคุณสามารถมีแบบจำลองที่เหมาะสมได้ใน 1 วัน


ในขณะเดียวกันspaCyมีnerส่วนประกอบของท่อมันจะไม่เป็นประโยชน์สำหรับการจำแนกประเภทนี้หรือไม่? ฉันคิดว่าโมเดลของพวกเขาสามารถจดจำได้Apple(เนื่องจากเป็น บริษัท ที่ใหญ่ที่สุดและเป็นที่รู้จักมากที่สุดในโลก) ดีกว่าโมเดลที่คุณสามารถสร้างขึ้นมาได้ในวันเดียว
Szymon Maszke

@Szymon: NER อาจช่วยหรือไม่ก็ได้ ตามที่ฉันเข้าใจคุณต้องการใช้เอนทิตีที่มีชื่อ (ข้อเท็จจริงที่ว่ามีอยู่ในข้อความ) เพื่อเป็นคุณสมบัติสำหรับงานการจัดประเภทหลัก เห็นได้ชัดว่า NER จะไม่มีความแม่นยำ 100% เนื่องจากมีความคลุมเครือในระดับสูง ดังนั้นรูปแบบการจำแนกประเภทหลักจะตัดสินว่าจะเชื่อถือคุณลักษณะนี้ภายใต้สถานการณ์ใด อาจกลายเป็นว่า (ฉันคิดว่าเป็นไปได้มาก) ว่าแบบจำลองการจำแนกขั้นพื้นฐานจะให้น้ำหนักกับผลลัพธ์ของแบบจำลอง NER น้อยมาก และนั่นหมายความว่าคุณจะใช้เวลากับ NER ซึ่ง (เกือบ) ไม่ได้ใช้
สลัว

ไม่ใช่สิ่งที่ฉันหมายถึง เพียงสร้างspacy.Docจากแต่ละข้อความวนซ้ำเหนือ NER ของพวกเขาด้วยdoc.entsและตรวจสอบว่า NER ใดมี.textแอตทริบิวต์เท่ากับAppleหรือไม่ ความสนุกตัวอย่างแรกของพวกเขาประกอบด้วย Apple
Szymon Maszke

และถ้ามีคนต้องการสร้างแบบจำลองส่วนใหญ่อาจเกี่ยวข้องกับ RNNs / CNNs และอื่น ๆ ที่คล้ายกันปรับแต่งตามนั้นค้นหาสถาปัตยกรรมประเภทเซลล์ ฯลฯ ฉันไม่คิดว่าโมเดลที่ง่ายกว่าจะจัดการกับการลดความสับสนและบริบทได้ดี ทำไมต้องทำให้ชีวิตของคุณง่ายขึ้น (เว้นแต่คุณต้องการเรียนรู้บางสิ่งบางอย่างไปพร้อมกัน) ถ้ามีคนทำเพื่อคุณ
Szymon Maszke

@SzymonMaszke โมเดลของคุณซับซ้อนกว่าและฝึกยากกว่า เพื่อให้โมเดลของคุณทำงานได้ตามวัตถุประสงค์ที่กล่าวไว้คุณไม่เพียง แต่จะต้องค้นหา NE เท่านั้น แต่ยังค้นหาในตำแหน่งที่ถูกต้อง (โทเค็น) ด้วย ด้วยรูปแบบการจัดหมวดหมู่ที่ฉันขอแนะนำให้คุณปรับโมเดลให้เหมาะสมกับเป้าหมายหลักของคุณ - ระบุว่าเป็น บริษัท Apple หรือผลไม้ Apple ง่ายต่อการฝึกอบรมและเป็นไปได้มากที่สุดว่าจะแม่นยำกว่า
สลัว
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.