बिना ज्यादा मेहनत के एआई-नस्लवादी कैसे बना जाए

एक सावधान सबक।

चलो एक टॉन्सिलिटी क्लासिफ़ायर करें!

प्राकृतिक भाषा प्रसंस्करण (एनएलपी) में सेंटीमेंट एनालिसिस (भावना विश्लेषण) एक बहुत ही सामान्य कार्य है, और यह आश्चर्य की बात नहीं है। एक व्यवसाय के लिए यह समझना महत्वपूर्ण है कि लोग क्या कह रहे हैं: सकारात्मक या नकारात्मक। इस तरह के विश्लेषण का उपयोग सोशल नेटवर्क, ग्राहक प्रतिक्रिया और यहां तक ​​कि एल्गोरिथम स्टॉक ट्रेडिंग की निगरानी के लिए किया जाता है (परिणामस्वरूप, बॉटर्स ने आखिरी फिल्म में ऐनी हैथवे की भूमिका के बारे में सकारात्मक समीक्षा पोस्ट करने के बाद बर्कशायर हैथवे शेयर खरीदते हैं )।

विश्लेषण विधि कभी-कभी बहुत सरल होती है, लेकिन यह मापने योग्य परिणाम प्राप्त करने के सबसे आसान तरीकों में से एक है। बस पाठ सबमिट करें - और आउटपुट सकारात्मक और नकारात्मक है। पार्सिंग ट्री से निपटने, कोई ग्राफ़ बनाने या कुछ अन्य जटिल प्रतिनिधित्व करने की आवश्यकता नहीं है।

यही हम करेंगे। हम कम से कम प्रतिरोध के मार्ग का अनुसरण करेंगे और सरलतम वर्गीकरण करेंगे, जो शायद हर किसी के लिए बहुत परिचित है जो एनएलपी के क्षेत्र में प्रासंगिक विकास में शामिल है। उदाहरण के लिए, इस तरह के मॉडल को डीप एवरेजिंग नेटवर्क्स (अय्यर एट अल।, 2015) के लेख में पाया जा सकता है। हम उनके परिणामों को चुनौती देने या मॉडल की आलोचना करने की कोशिश नहीं कर रहे हैं; हम बस शब्दों के वेक्टर प्रतिनिधित्व का एक प्रसिद्ध तरीका देते हैं।

कार्य योजना:

  • अर्थ (अर्थ) के साथ काम करने के लिए शब्दों का एक विशिष्ट वेक्टर प्रतिनिधित्व करें
  • सकारात्मक और नकारात्मक शब्दों की मानक सूची के साथ प्रशिक्षण और डेटा सेट का परिचय दें।
  • उनके वेक्टर प्रतिनिधित्व के आधार पर अन्य सकारात्मक और नकारात्मक शब्दों को पहचानने के लिए ढाल वंश वर्गीकरण को प्रशिक्षित करें।
  • पाठ के वाक्यों के लिए टनटन रेटिंग की गणना करने के लिए इस वर्गीकरण का उपयोग करें।
  • हमारे द्वारा बनाए गए राक्षस को देखने के लिए

और फिर हम देखेंगे, "विशेष प्रयासों के बिना एआई-नस्लवादी कैसे बनाएं।" बेशक, आप इस तरह के राक्षसी रूप में सिस्टम को नहीं छोड़ सकते हैं, इसलिए हम यहां जा रहे हैं:

  • समस्या का सांख्यिकीय रूप से मूल्यांकन करने के लिए , ताकि यह हल होने के साथ प्रगति को माप सके।
  • अधिक सटीक और कम नस्लवादी शब्दार्थ मॉडल प्राप्त करने के लिए डेटा में सुधार करें

सॉफ्टवेयर निर्भरता


यह ट्यूटोरियल पायथन में लिखा गया है और एक विशिष्ट पायथन मशीन लर्निंग स्टैक पर निर्भर करता है: संख्यात्मक कंप्यूटिंग, डेटा प्रबंधन के लिए pandas और मशीन सीखने के लिए scikit-learn । अंत में, हम आरेख बनाने के seaborn matplotlib और seaborn का भी seaborn matplotlib

सिद्धांत रूप में, scikit-learn को टेन्सरफ्लो या केरस के साथ प्रतिस्थापित किया जा सकता है, या ऐसा कुछ: वे ग्रेडिएंट को ढाल वंश पर प्रशिक्षित करने में भी सक्षम हैं। लेकिन हमें उनके सार की आवश्यकता नहीं है, क्योंकि यहां प्रशिक्षण एक चरण में होता है।

 import numpy as np import pandas as pd import matplotlib import seaborn import re import statsmodels.formula.api from sklearn.linear_model import SGDClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score #     %matplotlib inline seaborn.set_context('notebook', rc={'figure.figsize': (10, 6)}, font_scale=1.5) 

चरण 1. शब्दों का वेक्टर प्रतिनिधित्व


पाठ इनपुट होने पर वेक्टर प्रतिनिधित्व अक्सर उपयोग किया जाता है। शब्द बहुआयामी अंतरिक्ष में वैक्टर बन जाते हैं, जहां आसन्न वैक्टर समान अर्थों का प्रतिनिधित्व करते हैं। वेक्टर अभ्यावेदन का उपयोग करके, आप शब्दों की तुलना उनके अर्थ से कर सकते हैं, न कि केवल सटीक मिलान द्वारा।

सफल सीखने के लिए सैकड़ों गीगाबाइट पाठ की आवश्यकता होती है। सौभाग्य से, विभिन्न शोध टीमों ने पहले ही यह काम किया है और वेक्टर प्रतिनिधित्व के पूर्व-प्रशिक्षित मॉडल डाउनलोड के लिए उपलब्ध हैं।

अंग्रेजी भाषा के लिए दो सबसे प्रसिद्ध डेटासेट्स हैं शब्द 2vec (Google समाचार ग्रंथों पर प्रशिक्षित) और ग्लोवी (कॉमन क्रॉल वेब पेजों पर)। उनमें से कोई भी एक समान परिणाम देगा, लेकिन हम GloVe मॉडल को लेंगे क्योंकि इसमें अधिक पारदर्शी डेटा स्रोत है।

ग्लोव तीन आकारों में आता है: 6 बिलियन, 42 बिलियन और 840 बिलियन। नवीनतम मॉडल सबसे शक्तिशाली है, लेकिन इसके लिए महत्वपूर्ण संसाधन संसाधन की आवश्यकता होती है। 42 बिलियन संस्करण बहुत अच्छा है, और शब्दकोश को बड़े करीने से 1 मिलियन शब्दों में ट्रिम किया गया है। हम कम से कम प्रतिरोध के रास्ते पर हैं, इसलिए 42 बिलियन संस्करण लें।

- एक "प्रसिद्ध" मॉडल का उपयोग करना इतना महत्वपूर्ण क्यों है?

"मुझे खुशी है कि आपने इस बारे में पूछा, काल्पनिक वार्ताकार!" प्रत्येक चरण में हम कुछ विशिष्ट करने की कोशिश करते हैं, और किसी कारण से शब्दों के वेक्टर प्रतिनिधित्व के लिए सबसे अच्छा मॉडल अभी तक निर्धारित नहीं किया गया है। मुझे उम्मीद है कि यह लेख आधुनिक उच्च-गुणवत्ता वाले मॉडल का उपयोग करने की इच्छा जगाएगा, विशेष रूप से वे जो एक एल्गोरिथम त्रुटि को ध्यान में रखते हैं और इसे सही करने का प्रयास करते हैं। हालांकि, बाद में उस पर और अधिक।

GloVe वेबसाइट से glove.42B.300d.zip डाउनलोड करें और फ़ाइल data/glove.42B.300d.txt । अगला, हम एक सरल प्रारूप में वैक्टर पढ़ने के लिए एक फ़ंक्शन को परिभाषित करते हैं।

 def load_embeddings(filename): """  DataFrame      ,   word2vec, GloVe, fastText  ConceptNet Numberbatch.            . """ labels = [] rows = [] with open(filename, encoding='utf-8') as infile: for i, line in enumerate(infile): items = line.rstrip().split(' ') if len(items) == 2: # This is a header row giving the shape of the matrix continue labels.append(items[0]) values = np.array([float(x) for x in items[1:]], 'f') rows.append(values) arr = np.vstack(rows) return pd.DataFrame(arr, index=labels, dtype='f') embeddings = load_embeddings('data/glove.42B.300d.txt') embeddings.shape 

(1917494, 300)

चरण 2. स्वर्ण मानक टनक शब्दकोश


अब हमें जानकारी की आवश्यकता है कि कौन से शब्द सकारात्मक माने जाते हैं और कौन से नकारात्मक। ऐसे कई शब्दकोश हैं, लेकिन हम एक बहुत ही सरल शब्दकोश (हू और लियू, 2004) लेंगे, जिसका उपयोग डीप एवरेजिंग नेटवर्क्स के लेख में किया गया है।

बिंग लियू की वेबसाइट से डिक्शनरी डाउनलोड करें और data/positive-words.txt और data/negative-words.txt

अगला, हम निर्धारित करते हैं कि इन फ़ाइलों को कैसे पढ़ा pos_words और उन्हें pos_words और neg_words रूप में निर्दिष्ट किया pos_words :

 def load_lexicon(filename): """       (https://www.cs.uic.edu/~liub/FBS/sentiment-analysis.html)      Latin-1.      ,    - .    ,    ';'   ,   . """ lexicon = [] with open(filename, encoding='latin-1') as infile: for line in infile: line = line.rstrip() if line and not line.startswith(';'): lexicon.append(line) return lexicon pos_words = load_lexicon('data/positive-words.txt') neg_words = load_lexicon('data/negative-words.txt') 

चरण 3. हम मॉडल को प्रशिक्षित करते हैं कि वह टॉन्सिलिटी की भविष्यवाणी करे


सकारात्मक और नकारात्मक शब्दों के वैक्टर के आधार पर, हम सभी शब्दों के वेक्टर प्रतिनिधित्व के लिए खोज करने के लिए पंडों .loc[] कमांड का उपयोग करते हैं।

GloVe डिक्शनरी में कुछ शब्द गायब हैं। अक्सर ये "फैंकिंग" जैसे टाइपो होते हैं। यहां हम NaN का एक गुच्छा देखते हैं, जो वेक्टर की अनुपस्थिति को इंगित करता है, और उन्हें .dropna() कमांड से .dropna()

pos_vectors = embeddings.loc[pos_words].dropna()
neg_vectors = embeddings.loc[neg_words].dropna()


अब हम इनपुट (वेक्टर प्रतिनिधित्व) और आउटपुट (सकारात्मक शब्दों के लिए 1 और नकारात्मक के लिए -1) पर डेटा के सरणियों का निर्माण करते हैं। हम यह भी जांचते हैं कि वैक्टर शब्दों से जुड़े हुए हैं ताकि हम परिणामों की व्याख्या कर सकें।

vectors = pd.concat([pos_vectors, neg_vectors])
targets = np.array([1 for entry in pos_vectors.index] + [-1 for entry in neg_vectors.index])
labels = list(pos_vectors.index) + list(neg_vectors.index)


- पकड़ो। कुछ शब्द न तो सकारात्मक हैं और न ही नकारात्मक, वे तटस्थ हैं। क्या तटस्थ शब्दों के लिए तीसरी श्रेणी नहीं बनानी चाहिए?

"मुझे लगता है कि वह काम में आया होगा।" बाद में हम देखेंगे कि तटस्थता शब्दों के लिए आज रात के काम के कारण क्या समस्याएं आती हैं। यदि हम निष्पक्ष रूप से तटस्थ शब्दों की पहचान कर सकते हैं, तो क्लासिफायर की जटिलता को तीन श्रेणियों में बढ़ाना काफी संभव है। लेकिन आपको तटस्थ शब्दों का एक शब्दकोश खोजने की आवश्यकता है, क्योंकि लियू के शब्दकोश में केवल सकारात्मक और नकारात्मक हैं।

इसलिए मैंने शब्दों के 800 उदाहरणों के साथ अपने संस्करण की कोशिश की और तटस्थ शब्दों की भविष्यवाणी करने के लिए वजन बढ़ाया। लेकिन अंतिम परिणाम आप अब जो देखेंगे उससे बहुत अलग नहीं थे।

- यह सूची सकारात्मक और नकारात्मक शब्दों को कैसे अलग करती है? क्या यह संदर्भ पर निर्भर नहीं करता है?

- अच्छा सवाल है। सामान्य कुंजियों का विश्लेषण उतना सरल नहीं है जितना लगता है। कुछ जगहों पर सीमा काफी मनमानी है। इस सूची में, "अभेद्य" शब्द को "बुरा" और "महत्वाकांक्षी" को "अच्छा" के रूप में चिह्नित किया गया है। "हास्य" बुरा है, और "मजाकिया" अच्छा है। एक "धनवापसी" अच्छा है, हालांकि यह आमतौर पर एक बुरे संदर्भ में उल्लेख किया जाता है जब आप किसी को पैसा देते हैं या आप किसी को देते हैं।

हर कोई समझता है कि आज की रात संदर्भ द्वारा निर्धारित की जाती है, लेकिन एक साधारण मॉडल में आपको संदर्भ को नजरअंदाज करना होगा और आशा है कि औसत टनिटी का सही अनुमान लगाया जाएगा।

train_test_split फ़ंक्शन का उपयोग करते train_test_split , train_test_split एक साथ इनपुट वैक्टर, आउटपुट मान और लेबल को प्रशिक्षण और परीक्षण डेटा में विभाजित करते हैं, जबकि परीक्षण के लिए 10% छोड़ते हैं।

 train_vectors, test_vectors, train_targets, test_targets, train_labels, test_labels = \ train_test_split(vectors, targets, labels, test_size=0.1, random_state=0) 

अब एक क्लासिफायरियर बनाएं और इसके माध्यम से पुनरावृत्तियों के माध्यम से वैक्टर पास करें। हम लॉजिस्टिक लॉस फ़ंक्शन का उपयोग करते हैं ताकि अंतिम क्लासिफ़ायर इस संभावना को कम कर सके कि शब्द सकारात्मक है या नकारात्मक।

 model = SGDClassifier(loss='log', random_state=0, n_iter=100) model.fit(train_vectors, train_targets) SGDClassifier(alpha=0.0001, average=False, class_weight=None, epsilon=0.1, eta0=0.0, fit_intercept=True, l1_ratio=0.15, learning_rate='optimal', loss='log', n_iter=100, n_jobs=1, penalty='l2', power_t=0.5, random_state=0, shuffle=True, verbose=0, warm_start=False) 

हम परीक्षण वैक्टर पर क्लासिफायरियर का मूल्यांकन करते हैं। यह 95% की सटीकता दिखाता है। बुरा नहीं है।

accuracy_score(model.predict(test_vectors), test_targets)
0.95022624434389136


हम कुछ शब्दों के लिए टोनिटी भविष्यवाणी समारोह को परिभाषित करते हैं, और फिर परीक्षण डेटा से कुछ उदाहरणों के लिए इसका उपयोग करते हैं।

 def vecs_to_sentiment(vecs): # predict_log_proba  log-    predictions = model.predict_log_proba(vecs) #        #  log-    . return predictions[:, 1] - predictions[:, 0] def words_to_sentiment(words): vecs = embeddings.loc[words].dropna() log_odds = vecs_to_sentiment(vecs) return pd.DataFrame({'sentiment': log_odds}, index=vecs.index) #  20      words_to_sentiment(test_labels).ix[:20] 

रागिनी
कुलबुलाहट-९.९,३१,६७९
बाधा-९.६,३४,७०६
लगातार1.466919
काल्पनिक-२.९,८९,२१५
कराधान0.468522
विश्व प्रसिद्ध6.908561
सस्ता9.237223
निराशा-८.७,३७,१८२
अधिनायकवादी-१०.८,५१,५८०
उग्रवादी-८.३,२८,६७४
फ्रीज़-८.४,५६,९८१
पाप-७.८,३९,६७०
नाज़ुक-४.०,१८,२८९
bamboozled-४.३,०९,३४४
अनसुलझे-२.८,१६,१७२
चालाकी से2.339609
demonizes-२.१,०२,१५२
लापरवाह8.747150
अप्रसिद्ध-७.८,८७,४७५
सहानुभूति रखना1.790899

यह देखा जाता है कि क्लासिफायर काम कर रहा है। उन्होंने प्रशिक्षण डेटा के बाहर के शब्दों में टॉन्सिलिटी को सामान्य करना सीखा।

चरण 4. पाठ के लिए एक टन स्कोर प्राप्त करें।


कुल मिलाकर अनुमान में वैक्टर को जोड़ने के कई तरीके हैं। फिर से, हम कम से कम प्रतिरोध के मार्ग का अनुसरण करते हैं, इसलिए बस औसत मूल्य लें।

 import re TOKEN_RE = re.compile(r"\w.*?\b") # regex  ,     (\w)   #   (.+?)    (\b).   #       . def text_to_sentiment(text): tokens = [token.casefold() for token in TOKEN_RE.findall(text)] sentiments = words_to_sentiment(tokens) return sentiments['sentiment'].mean() 

अनुकूलन के लिए बहुत कुछ पूछा जाना है:

  • शब्द के वजन और इसकी आवृत्ति के बीच एक उलटा संबंध प्रस्तुत करते हैं, ताकि एक ही पूर्वसर्ग का उपयोग करने से टॉन्सिलिटी प्रभावित न हो।
  • यह निर्धारित करना ताकि छोटे वाक्य अत्यधिक टॉनिक मूल्यों के साथ समाप्त न हों।
  • लेखा वाक्यांश।
  • एक और अधिक विश्वसनीय शब्द विभाजन एल्गोरिथ्म जो एपोस्ट्रोफ्स दस्तक नहीं देता है।
  • "संतुष्ट नहीं" जैसे नकारात्मकताओं के लिए लेखांकन।

लेकिन सब कुछ के लिए अतिरिक्त कोड की आवश्यकता होती है और यह मूल रूप से परिणामों को नहीं बदलेगा। कम से कम अब आप विभिन्न प्रस्तावों की तुलना कर सकते हैं:

 text_to_sentiment("this example is pretty cool") 3.889968926086298 

 text_to_sentiment("this example is okay") 2.7997773492425186 

 text_to_sentiment("meh, this example sucks") -1.1774475917460698 

चरण 5. हमारे द्वारा बनाए गए राक्षस को निहारना


हर वाक्य में एक स्पष्टता नहीं होती है। आइए देखें कि तटस्थ वाक्यों के साथ क्या होता है:

 text_to_sentiment("Let's go get Italian food") 2.0429166109408983 

 text_to_sentiment("Let's go get Chinese food") 1.4094033658140972 

 text_to_sentiment("Let's go get Mexican food") 0.38801985560121732 

मैंने पहले ही इस तरह की घटना का सामना किया है जब शब्दों के वेक्टर प्रतिनिधित्व को ध्यान में रखते हुए रेस्तरां की समीक्षा का विश्लेषण किया गया था। बिना किसी स्पष्ट कारण के , सभी मैक्सिकन रेस्तरां का कुल स्कोर कम है

वेक्टर अभ्यावेदन संदर्भ में सूक्ष्म अर्थ भेदों को पकड़ते हैं। इसलिए, वे हमारे समाज के पूर्वाग्रहों को दर्शाते हैं।

यहाँ कुछ अन्य तटस्थ सुझाव दिए गए हैं:

 text_to_sentiment("My name is Emily") 2.2286179364745311 

 text_to_sentiment("My name is Heather") 1.3976291151079159 

 text_to_sentiment("My name is Yvette") 0.98463802132985556 

 text_to_sentiment("My name is Shaniqua") -0.47048131775890656 

खैर लानत है ...

लोगों के नाम से जुड़ी प्रणाली पूरी तरह से अलग भावनाएं हैं। आप इन और कई अन्य उदाहरणों को देख सकते हैं और यह देख सकते हैं कि आम तौर पर टॉन्सिलिटिक रूप से सफेद नामों के लिए टॉन्सिलिटी अधिक होती है और स्टिरियोटाइप ब्लैक नामों के लिए कम होती है।

अप्रैल 2017 में जर्नल साइंस में प्रकाशित अपने शोध पत्र में यह परीक्षण कैलिसन, ब्रायसन और नारायणन द्वारा किया गया था। यह साबित होता है कि भाषा कॉर्पस के शब्दार्थ में समाज के पूर्वाग्रह हैं । हम इस विधि का उपयोग करेंगे।

चरण 6. समस्या का आकलन करना


हम समझना चाहते हैं कि इस तरह की गलतियों से कैसे बचा जाए। आइए हम क्लासिफायर के माध्यम से अधिक डेटा पास करें और सांख्यिकीय रूप से इसके "पूर्वाग्रह" को मापें।

यहां हमारे पास नामों की चार सूचियां हैं जो विभिन्न जातीय पृष्ठभूमि को दर्शाती हैं, मुख्य रूप से संयुक्त राज्य अमेरिका में। पहले दो मुख्य रूप से "श्वेत" और "काले" नामों की सूची हैं, जिन्हें कलातन एट अल के एक लेख के आधार पर अनुकूलित किया गया है। मैंने अरबी और उर्दू से स्पेनिश और मुस्लिम नाम भी जोड़े हैं।

यह डेटा कॉन्सेप्टनेट बिल्ड प्रक्रिया के दौरान एल्गोरिथ्म के पूर्वाग्रह को सत्यापित करने के लिए उपयोग किया जाता है: यह conceptnet5.vectors.evaluation.bias मॉड्यूल में पाया जा सकता है। अन्य जातीय समूहों के लिए शब्दकोश का विस्तार करने के लिए एक विचार है, न केवल नामों को ध्यान में रखते हुए, बल्कि उपनाम भी।

यहाँ सूचीबद्ध हैं:

 NAMES_BY_ETHNICITY = { #           . 'White': [ 'Adam', 'Chip', 'Harry', 'Josh', 'Roger', 'Alan', 'Frank', 'Ian', 'Justin', 'Ryan', 'Andrew', 'Fred', 'Jack', 'Matthew', 'Stephen', 'Brad', 'Greg', 'Jed', 'Paul', 'Todd', 'Brandon', 'Hank', 'Jonathan', 'Peter', 'Wilbur', 'Amanda', 'Courtney', 'Heather', 'Melanie', 'Sara', 'Amber', 'Crystal', 'Katie', 'Meredith', 'Shannon', 'Betsy', 'Donna', 'Kristin', 'Nancy', 'Stephanie', 'Bobbie-Sue', 'Ellen', 'Lauren', 'Peggy', 'Sue-Ellen', 'Colleen', 'Emily', 'Megan', 'Rachel', 'Wendy' ], 'Black': [ 'Alonzo', 'Jamel', 'Lerone', 'Percell', 'Theo', 'Alphonse', 'Jerome', 'Leroy', 'Rasaan', 'Torrance', 'Darnell', 'Lamar', 'Lionel', 'Rashaun', 'Tyree', 'Deion', 'Lamont', 'Malik', 'Terrence', 'Tyrone', 'Everol', 'Lavon', 'Marcellus', 'Terryl', 'Wardell', 'Aiesha', 'Lashelle', 'Nichelle', 'Shereen', 'Temeka', 'Ebony', 'Latisha', 'Shaniqua', 'Tameisha', 'Teretha', 'Jasmine', 'Latonya', 'Shanise', 'Tanisha', 'Tia', 'Lakisha', 'Latoya', 'Sharise', 'Tashika', 'Yolanda', 'Lashandra', 'Malika', 'Shavonn', 'Tawanda', 'Yvette' ], #         . 'Hispanic': [ 'Juan', 'José', 'Miguel', 'Luís', 'Jorge', 'Santiago', 'Matías', 'Sebastián', 'Mateo', 'Nicolás', 'Alejandro', 'Samuel', 'Diego', 'Daniel', 'Tomás', 'Juana', 'Ana', 'Luisa', 'María', 'Elena', 'Sofía', 'Isabella', 'Valentina', 'Camila', 'Valeria', 'Ximena', 'Luciana', 'Mariana', 'Victoria', 'Martina' ], #       # ,   .     . # #          # -   .    #   ,    . # #       . 'Arab/Muslim': [ 'Mohammed', 'Omar', 'Ahmed', 'Ali', 'Youssef', 'Abdullah', 'Yasin', 'Hamza', 'Ayaan', 'Syed', 'Rishaan', 'Samar', 'Ahmad', 'Zikri', 'Rayyan', 'Mariam', 'Jana', 'Malak', 'Salma', 'Nour', 'Lian', 'Fatima', 'Ayesha', 'Zahra', 'Sana', 'Zara', 'Alya', 'Shaista', 'Zoya', 'Yasmin' ] } 

पंडों का उपयोग करते हुए, हम नामों की एक तालिका, उनके प्रमुख जातीय मूल और आज की रेटिंग को संकलित करेंगे:

 def name_sentiment_table(): frames = [] for group, name_list in sorted(NAMES_BY_ETHNICITY.items()): lower_names = [name.lower() for name in name_list] sentiments = words_to_sentiment(lower_names) sentiments['group'] = group frames.append(sentiments) #           return pd.concat(frames) name_sentiments = name_sentiment_table() 

नमूना डेटा:

name_sentiments.ix[::25]
रागिनीसमूह
मुहम्मद0.834974अरब / मुस्लिम
alya3.916803अरब / मुस्लिम
terryl-२.८,५८,०१०काला
जोस0.432956हिस्पैनिक
लुसियाना1.086073हिस्पैनिक
अटेरना0.391858सफेद
मेगन2.158679सफेद

हम प्रत्येक नाम के लिए टनटन के वितरण का ग्राफ तैयार करेंगे।

 plot = seaborn.swarmplot(x='group', y='sentiment', data=name_sentiments) plot.set_ylim([-10, 10]) 

(-10, 10)



या 95% की औसत के लिए आत्मविश्वास अंतराल के साथ हिस्टोग्राम के रूप में।

 plot = seaborn.barplot(x='group', y='sentiment', data=name_sentiments, capsize=.1) 



अंत में, गंभीर सांख्यिकीमॉडल सांख्यिकी पैकेज चलाएँ। यह दिखाएगा कि एल्गोरिथ्म का पूर्वाग्रह कितना महान है (अन्य आंकड़ों के एक समूह के साथ)।


OLS प्रतिगमन परिणाम
रवानगी। वैरिएबल:भावआर चुकता:0.208
मॉडल:OLSसमायो। आर चुकता:0.192
विधि:कम से कम वर्गएफ आंकड़ा:13.04
दिनांक:थू, 13 जुलाई 2017शायद (एफ-स्टेटिस्टिक):1.31e-07
समय:11:31:17लॉग-संभावना:-356.78
नहीं। टिप्पणियों:153AIC:721.6
डीएफ अवशिष्ट:149बीआईसी:733.7
डीएफ मॉडल:3
सहसंयोजक प्रकार:nonrobust

एफ-स्टेटिस्टिक समूहों के बीच भिन्नता के बीच भिन्नता का अनुपात है, जिसे पूर्वाग्रह के सामान्य मूल्यांकन के रूप में लिया जा सकता है।

इसके तुरंत बाद इस संभावना को इंगित किया गया है कि हम अशक्त परिकल्पना के साथ अधिकतम एफ-आँकड़ा देखेंगे: अर्थात्, यदि तुलना किए गए विकल्पों में कोई अंतर नहीं है। संभावना बहुत, बहुत कम है। एक वैज्ञानिक लेख में, हम परिणाम को "बहुत सांख्यिकीय रूप से महत्वपूर्ण" कहेंगे।

हमें F- मूल्य में सुधार करने की आवश्यकता है। कम बेहतर है।

ols_model.fvalue
13.041597745167659


चरण 7. अन्य डेटा की कोशिश कर रहा।


अब हमारे पास मॉडल के हानिकारक पूर्वाग्रह को संख्यात्मक रूप से मापने का अवसर है। इसे समायोजित करने का प्रयास करते हैं। ऐसा करने के लिए, आपको उन चीजों का एक समूह दोहराना होगा जो पायथन नोटपैड में बस अलग-अलग चरणों का उपयोग करते थे।

यदि मैंने अच्छा, समर्थित कोड लिखा है, तो मैं model और embeddings जैसे वैश्विक चर का उपयोग नहीं करूंगा। लेकिन वर्तमान स्पेगेटी कोड आपको प्रत्येक चरण की बेहतर जांच करने और समझने की अनुमति देता है कि क्या हो रहा है। हम कोड का पुन: उपयोग करते हैं और कम से कम कुछ चरणों को दोहराने के लिए एक फ़ंक्शन को परिभाषित करते हैं:

 def retrain_model(new_embs): """      . """ global model, embeddings, name_sentiments embeddings = new_embs pos_vectors = embeddings.loc[pos_words].dropna() neg_vectors = embeddings.loc[neg_words].dropna() vectors = pd.concat([pos_vectors, neg_vectors]) targets = np.array([1 for entry in pos_vectors.index] + [-1 for entry in neg_vectors.index]) labels = list(pos_vectors.index) + list(neg_vectors.index) train_vectors, test_vectors, train_targets, test_targets, train_labels, test_labels = \ train_test_split(vectors, targets, labels, test_size=0.1, random_state=0) model = SGDClassifier(loss='log', random_state=0, n_iter=100) model.fit(train_vectors, train_targets) accuracy = accuracy_score(model.predict(test_vectors), test_targets) print("Accuracy of sentiment: {:.2%}".format(accuracy)) name_sentiments = name_sentiment_table() ols_model = statsmodels.formula.api.ols('sentiment ~ group', data=name_sentiments).fit() print("F-value of bias: {:.3f}".format(ols_model.fvalue)) print("Probability given null hypothesis: {:.3}".format(ols_model.f_pvalue)) #        Y plot = seaborn.swarmplot(x='group', y='sentiment', data=name_sentiments) plot.set_ylim([-10, 10]) 

हम शब्द 2vec की कोशिश करते हैं


यह माना जा सकता है कि केवल ग्लोव की समस्या है। कॉमन क्रॉल डेटाबेस में संभवतः बहुत सारे संदिग्ध स्थल हैं और स्ट्रीट स्लैंग के शहरी शब्दकोश की कम से कम 20 प्रतियां हैं। शायद एक अलग आधार पर यह बेहतर होगा: Google समाचार पर प्रशिक्षित अच्छे पुराने शब्द 2vec के बारे में क्या?

ऐसा लगता है कि word2vec डेटा के लिए सबसे आधिकारिक स्रोत Google डिस्क पर यह फ़ाइल है । इसे डाउनलोड करें और इसे data/word2vec-googlenews-300.bin.gz

 #   ConceptNet   word2vec   Pandas     from conceptnet5.vectors.formats import load_word2vec_bin w2v = load_word2vec_bin('data/word2vec-googlenews-300.bin.gz', nrows=2000000) #  word2vec    w2v.index = [label.casefold() for label in w2v.index] #  ,    w2v = w2v.reset_index().drop_duplicates(subset='index', keep='first').set_index('index') retrain_model(w2v) 

Accuracy of sentiment: 94.30%
F-value of bias: 15.573
Probability given null hypothesis: 7.43e-09


तो शब्द 2vec 15 से अधिक के F मान के साथ और भी खराब निकला।

सिद्धांत रूप में, पूर्वाग्रह से समाचार को बेहतर तरीके से संरक्षित करने की अपेक्षा करना मूर्खता थी।

कॉन्सेप्टनेट नंबरबैच की कोशिश करना


अंत में, मैं शब्दों के वेक्टर प्रतिनिधित्व पर अपनी खुद की परियोजना के बारे में बात कर सकता हूं।

वेक्टर प्रस्तुति फीचर के साथ कॉन्सेप्टनेट वह ज्ञान ग्राफ है जिस पर मैं काम कर रहा हूं। यह एल्गोरिदमिक नस्लवाद और लिंगवाद के कुछ स्रोतों को पहचानने और हटाने के प्रशिक्षण चरण में वेक्टर अभ्यावेदन को सामान्य करता है। पूर्वाग्रह को सही करने का यह तरीका बुलुकबाशी एट अल। "डेबिसिंग वर्ड एंबेडिंग्स" के एक वैज्ञानिक लेख पर आधारित है और एक ही समय में कई प्रकार के पूर्वाग्रह को खत्म करने के लिए सामान्यीकृत है। जहां तक ​​मुझे पता है, यह एकमात्र अर्थ प्रणाली है जिसमें ऐसा कुछ है।

समय-समय पर, हम कॉन्सेप्टनेट से पूर्व-गणना वाले वैक्टरों का निर्यात करते हैं - इन रिलीज को कॉन्सेप्टनेट नंबरबैच कहा जाता है। अप्रैल 2017 में, पूर्वाग्रह सुधार के साथ पहली रिलीज जारी की गई थी, इसलिए हम अंग्रेजी भाषा के वैक्टर को लोड करेंगे और अपने मॉडल को फिर से बनाएंगे।

numberbatch-en-17.04b.txt.gz , इसे data/ डायरेक्टरी में सेव करते हैं और मॉडल को numberbatch-en-17.04b.txt.gz करते हैं:

 retrain_model(load_embeddings('data/numberbatch-en-17.04b.txt')) 

Accuracy of sentiment: 97.46%
F-value of bias: 3.805
Probability given null hypothesis: 0.0118




तो, क्या कॉन्सेप्टनेट नंबरबैच ने समस्या को पूरी तरह से ठीक कर दिया है? कोई और अधिक एल्गोरिथम नस्लवाद? नहीं।

क्या जातिवाद बहुत कम हो गया है? निश्चित रूप से

जातीय समूहों के लिए मुख्य श्रेणियाँ GloVe या word2vec वैक्टर की तुलना में बहुत अधिक ओवरलैप होती हैं। GloVe की तुलना में, F का मान तीन गुना से अधिक घट गया, और शब्द 2vec की तुलना में - चार गुना से अधिक। और सामान्य तौर पर, हम अलग-अलग नामों की तुलना करते समय टॉन्सिलिटी में बहुत छोटे अंतर देखते हैं: ऐसा होना चाहिए, क्योंकि नाम वास्तव में विश्लेषण के परिणाम को प्रभावित नहीं करना चाहिए।

लेकिन थोड़ा सहसंबंध बना रहा। शायद मैं ऐसे डेटा और प्रशिक्षण मापदंडों को चुन सकता हूं जो समस्या को हल करने के लिए लगता है। लेकिन यह एक बुरा विकल्प होगा, क्योंकि वास्तव में समस्या बनी हुई है, क्योंकि कॉन्सेप्टनेट में हमने एल्गोरिदमिक नस्लवाद के सभी कारणों की पहचान और क्षतिपूर्ति नहीं की है। लेकिन यह एक अच्छी शुरुआत है।

कोई नुकसान नहीं


कृपया ध्यान दें कि कॉन्सेप्टनेट नंबरबैच के स्विच के साथ, टोनिंग की भविष्यवाणी करने की सटीकता में सुधार हुआ है।

किसी ने सुझाव दिया हो सकता है कि एल्गोरिथम जातिवाद को सही करने से परिणाम किसी और तरीके से खराब हो जाएंगे। लेकिन नहीं। आपके पास डेटा हो सकता है जो बेहतर और कम नस्लवादी हो।इस सुधार के साथ डेटा में वास्तव में सुधार हो रहा है। शब्द 2vec और GloVe नस्लवाद को लोगों से हासिल किया गया एल्गोरिदम की सटीकता से कोई लेना-देना नहीं है।

अन्य दृष्टिकोण


निश्चित रूप से, यह केवल एक तरीका है टनटन का विश्लेषण करने का। कुछ विवरणों को अलग तरीके से लागू किया जा सकता है।

इसके बजाय या वेक्टर बेस को बदलने के अलावा, आप सीधे आउटपुट में इस समस्या को ठीक करने का प्रयास कर सकते हैं। उदाहरण के लिए, आम तौर पर लोगों के नाम और समूहों के लिए टनटन के मूल्यांकन को समाप्त करते हैं।

सामान्य रूप से सभी शब्दों की टोन की गणना करने से इनकार करने और सूची से केवल शब्दों के लिए गणना करने का एक विकल्प है। यह शायद भावुक विश्लेषण का सबसे सामान्य रूप है - बिना मशीन सीखने के। परिणामों में सूची के लेखक की तुलना में अधिक पूर्वाग्रह नहीं होंगे। लेकिन मशीन सीखने से इनकार करने का मतलब है रिकॉल (रिकॉल) को कम करना, और मॉडल को किसी डाटासेट में अनुकूलित करने का एकमात्र तरीका सूची को मैन्युअल रूप से संपादित करना है।

एक हाइब्रिड दृष्टिकोण के रूप में, आप शब्दों के लिए बड़ी संख्या में अनुमानित टॉन्सिलिटी अनुमान बना सकते हैं और किसी व्यक्ति को धैर्यपूर्वक उन्हें संपादित करने का निर्देश दे सकते हैं, शून्य टॉन्सिलिटी वाले अपवाद शब्दों की सूची बना सकते हैं। लेकिन यह एक अतिरिक्त काम है। दूसरी ओर, आप वास्तव में देखेंगे कि मॉडल कैसे काम करता है। मुझे लगता है कि किसी भी मामले में, यह मांग की जानी चाहिए।

Source: https://habr.com/ru/post/hi436506/


All Articles