मैं एनएलपी परियोजना पर काम कर रहा हूं, किसी भी प्रोग्रामिंग भाषा में (हालांकि पायथन मेरी प्राथमिकता होगी)।
मैं दो दस्तावेज लेना चाहता हूं और निर्धारित करना चाहता हूं कि वे कितने समान हैं।
मैं एनएलपी परियोजना पर काम कर रहा हूं, किसी भी प्रोग्रामिंग भाषा में (हालांकि पायथन मेरी प्राथमिकता होगी)।
मैं दो दस्तावेज लेना चाहता हूं और निर्धारित करना चाहता हूं कि वे कितने समान हैं।
जवाबों:
ऐसा करने का सामान्य तरीका यह है कि दस्तावेजों को TF-IDF वैक्टर में बदल दिया जाए और फिर उनके बीच कॉस्मिक समानता की गणना की जाए। सूचना पुनर्प्राप्ति (आईआर) पर कोई भी पाठ्यपुस्तक इसमें शामिल है। जासूसी देखें। सूचना पुनर्प्राप्ति का परिचय , जो मुफ़्त है और ऑनलाइन उपलब्ध है।
TF-IDF (और इसी तरह के टेक्स्ट ट्रांसफ़ॉर्मेशन) पायथन पैकेज में लागू होते हैं Gensim और scikit-learn । बाद के पैकेज में, कोसाइन समानताओं की गणना करना उतना ही आसान है जितना कि
from sklearn.feature_extraction.text import TfidfVectorizer
documents = [open(f) for f in text_files]
tfidf = TfidfVectorizer().fit_transform(documents)
# no need to normalize, since Vectorizer will return normalized tf-idf
pairwise_similarity = tfidf * tfidf.T
या, यदि दस्तावेज़ सादे तार हैं,
>>> corpus = ["I'd like an apple",
... "An apple a day keeps the doctor away",
... "Never compare an apple to an orange",
... "I prefer scikit-learn to Orange",
... "The scikit-learn docs are Orange and Blue"]
>>> vect = TfidfVectorizer(min_df=1, stop_words="english")
>>> tfidf = vect.fit_transform(corpus)
>>> pairwise_similarity = tfidf * tfidf.T
हालांकि इस तरह के कार्य के लिए जेनसिम के पास अधिक विकल्प हो सकते हैं।
यह प्रश्न भी देखें ।
[अस्वीकरण: मैं scikit-TF-IDF कार्यान्वयन में शामिल था।]
ऊपर से, pairwise_similarity
एक स्किपी स्पार्स मैट्रिक्स है जो आकार में चौकोर है, जिसमें कोर और डॉक्यूमेंट की संख्या के बराबर पंक्तियों और कॉलमों की संख्या है।
>>> pairwise_similarity
<5x5 sparse matrix of type '<class 'numpy.float64'>'
with 17 stored elements in Compressed Sparse Row format>
आप विरल ऐरे को न्यूपे सरणी में बदल सकते हैं .toarray()
या इसके द्वारा .A
:
>>> pairwise_similarity.toarray()
array([[1. , 0.17668795, 0.27056873, 0. , 0. ],
[0.17668795, 1. , 0.15439436, 0. , 0. ],
[0.27056873, 0.15439436, 1. , 0.19635649, 0.16815247],
[0. , 0. , 0.19635649, 1. , 0.54499756],
[0. , 0. , 0.16815247, 0.54499756, 1. ]])
मान लें कि हम दस्तावेज़ को अंतिम दस्तावेज़ के समान ढूंढना चाहते हैं, "स्किटिट-लर्न डॉक्स ऑरेंज और ब्लू हैं"। इस दस्तावेज़ में सूचकांक 4 है corpus
। आप उस पंक्ति के argmax को ले कर सबसे समान दस्तावेज़ के सूचकांक को पा सकते हैं , लेकिन सबसे पहले आपको 1 के मास्क की आवश्यकता होगी, जो प्रत्येक दस्तावेज़ की समानता को अपने आप में दर्शाता है । आप बाद के माध्यम से np.fill_diagonal()
, और पूर्व के माध्यम से कर सकते हैं np.nanargmax()
:
>>> import numpy as np
>>> arr = pairwise_similarity.toarray()
>>> np.fill_diagonal(arr, np.nan)
>>> input_doc = "The scikit-learn docs are Orange and Blue"
>>> input_idx = corpus.index(input_doc)
>>> input_idx
4
>>> result_idx = np.nanargmax(arr[input_idx])
>>> corpus[result_idx]
'I prefer scikit-learn to Orange'
नोट: एक विरल मैट्रिक्स का उपयोग करने का उद्देश्य एक बड़े कॉर्पस और शब्दावली के लिए (अंतरिक्ष की एक बड़ी मात्रा) को बचाने के लिए है। एक NumPy सरणी में कनवर्ट करने के बजाय, आप कर सकते हैं:
>>> n, _ = pairwise_similarity.shape
>>> pairwise_similarity[np.arange(n), np.arange(n)] = -1.0
>>> pairwise_similarity[input_idx].argmax()
3
X.mean(axis=0)
, फिर उस अर्थ से औसत / अधिकतम / माध्य (∗) यूक्लिडियन दूरी की गणना करें। (Wh) जो भी आपके फैंस को चुनें।
@Larsman की पहचान, लेकिन कुछ पूर्वप्रक्रिया के साथ
import nltk, string
from sklearn.feature_extraction.text import TfidfVectorizer
nltk.download('punkt') # if necessary...
stemmer = nltk.stem.porter.PorterStemmer()
remove_punctuation_map = dict((ord(char), None) for char in string.punctuation)
def stem_tokens(tokens):
return [stemmer.stem(item) for item in tokens]
'''remove punctuation, lowercase, stem'''
def normalize(text):
return stem_tokens(nltk.word_tokenize(text.lower().translate(remove_punctuation_map)))
vectorizer = TfidfVectorizer(tokenizer=normalize, stop_words='english')
def cosine_sim(text1, text2):
tfidf = vectorizer.fit_transform([text1, text2])
return ((tfidf * tfidf.T).A)[0,1]
print cosine_sim('a little bird', 'a little bird')
print cosine_sim('a little bird', 'a little bird chirps')
print cosine_sim('a little bird', 'a big dog barks')
fit
और कौन से transform
?
यह एक पुराना प्रश्न है, लेकिन मैंने पाया कि यह स्पैसी के साथ आसानी से किया जा सकता है । एक बार दस्तावेज़ को पढ़ने के बाद, similarity
दस्तावेज़ वैक्टर के बीच कोसाइन समानता को खोजने के लिए एक साधारण एपीआई का उपयोग किया जा सकता है।
import spacy
nlp = spacy.load('en')
doc1 = nlp(u'Hello hi there!')
doc2 = nlp(u'Hello hi there!')
doc3 = nlp(u'Hey whatsup?')
print doc1.similarity(doc2) # 0.999999954642
print doc2.similarity(doc3) # 0.699032527716
print doc1.similarity(doc3) # 0.699032527716
आम तौर पर दो दस्तावेजों के बीच एक कोसाइन समानता का उपयोग दस्तावेजों की समानता माप के रूप में किया जाता है। जावा में, आप ऐसा करने के लिए Lucene (यदि आपका संग्रह बहुत बड़ा है) या LingPipe का उपयोग कर सकते हैं । मूल अवधारणा हर दस्तावेज़ में शब्दों को गिनना और वैक्टर शब्द के डॉट उत्पाद की गणना करना होगा। पुस्तकालय इस सामान्य दृष्टिकोण पर कई सुधार प्रदान करते हैं, जैसे उलटे दस्तावेज़ आवृत्तियों का उपयोग करना और tf-idf वैक्टरों की गणना करना। यदि आप कुछ कॉप्लेक्स करना चाह रहे हैं, तो लिन्गिपाइप एलएसए समानता की गणना दस्तावेजों के बीच करने के तरीके भी प्रदान करता है जो कोसाइन समानता की तुलना में बेहतर परिणाम देता है। पायथन के लिए, आप एनएलटीके का उपयोग कर सकते हैं ।
यदि आप कुछ बहुत सटीक खोज रहे हैं, तो आपको tf-idf से कुछ बेहतर टूल का उपयोग करने की आवश्यकता है। सार्वभौमिक वाक्य एनकोडर पाठ के किसी भी दो टुकड़ों के बीच समानता खोजने के लिए सबसे सटीक लोगों में से एक है। Google ने प्रीट्रेन किए हुए मॉडल प्रदान किए जिन्हें आप अपने स्वयं के एप्लिकेशन के लिए उपयोग कर सकते हैं, बिना किसी चीज को प्रशिक्षित किए बिना। सबसे पहले, आपको टेंसरफ़्लो और टेंसोफ़्लो-हब स्थापित करना होगा:
pip install tensorflow
pip install tensorflow_hub
नीचे दिए गए कोड से आप किसी पाठ को एक निश्चित लंबाई के वेक्टर प्रतिनिधित्व में बदल सकते हैं और फिर आप उनके बीच समानता का पता लगाने के लिए डॉट उत्पाद का उपयोग कर सकते हैं।
import tensorflow_hub as hub
module_url = "https://tfhub.dev/google/universal-sentence-encoder/1?tf-hub-format=compressed"
# Import the Universal Sentence Encoder's TF Hub module
embed = hub.Module(module_url)
# sample text
messages = [
# Smartphones
"My phone is not good.",
"Your cellphone looks great.",
# Weather
"Will it snow tomorrow?",
"Recently a lot of hurricanes have hit the US",
# Food and health
"An apple a day, keeps the doctors away",
"Eating strawberries is healthy",
]
similarity_input_placeholder = tf.placeholder(tf.string, shape=(None))
similarity_message_encodings = embed(similarity_input_placeholder)
with tf.Session() as session:
session.run(tf.global_variables_initializer())
session.run(tf.tables_initializer())
message_embeddings_ = session.run(similarity_message_encodings, feed_dict={similarity_input_placeholder: messages})
corr = np.inner(message_embeddings_, message_embeddings_)
print(corr)
heatmap(messages, messages, corr)
और प्लॉटिंग के लिए कोड:
def heatmap(x_labels, y_labels, values):
fig, ax = plt.subplots()
im = ax.imshow(values)
# We want to show all ticks...
ax.set_xticks(np.arange(len(x_labels)))
ax.set_yticks(np.arange(len(y_labels)))
# ... and label them with the respective list entries
ax.set_xticklabels(x_labels)
ax.set_yticklabels(y_labels)
# Rotate the tick labels and set their alignment.
plt.setp(ax.get_xticklabels(), rotation=45, ha="right", fontsize=10,
rotation_mode="anchor")
# Loop over data dimensions and create text annotations.
for i in range(len(y_labels)):
for j in range(len(x_labels)):
text = ax.text(j, i, "%.2f"%values[i, j],
ha="center", va="center", color="w",
fontsize=6)
fig.tight_layout()
plt.show()
जैसा कि आप देख सकते हैं कि सबसे अधिक समानता स्वयं के साथ और फिर अर्थ में उनके करीबी ग्रंथों के बीच है।
महत्वपूर्ण : पहली बार जब आप कोड चलाते हैं तो यह धीमा होगा क्योंकि इसे मॉडल डाउनलोड करना होगा। यदि आप इसे फिर से मॉडल डाउनलोड करने से रोकना चाहते हैं और स्थानीय मॉडल का उपयोग करना चाहते हैं तो आपको कैश के लिए एक फ़ोल्डर बनाना होगा और इसे पर्यावरण चर में जोड़ना होगा और फिर पहली बार चलने के बाद उस पथ का उपयोग करना होगा:
tf_hub_cache_dir = "universal_encoder_cached/"
os.environ["TFHUB_CACHE_DIR"] = tf_hub_cache_dir
# pointing to the folder inside cache dir, it will be unique on your system
module_url = tf_hub_cache_dir+"/d8fbeb5c580e50f975ef73e80bebba9654228449/"
embed = hub.Module(module_url)
अधिक जानकारी: https://tfhub.dev/google/universal-sentence-encoder/2
यहां आपको शुरू करने के लिए थोड़ा सा ऐप दिया गया है ...
import difflib as dl
a = file('file').read()
b = file('file1').read()
sim = dl.get_close_matches
s = 0
wa = a.split()
wb = b.split()
for i in wa:
if sim(i, wb):
s += 1
n = float(s) / float(len(wa))
print '%d%% similarity' % int(n * 100)
आप इस ऑनलाइन सेवा को cosine दस्तावेज़ समानता http://www.scurtu.it/documentSimilarity.html के लिए आज़माना चाह सकते हैं
import urllib,urllib2
import json
API_URL="http://www.scurtu.it/apis/documentSimilarity"
inputDict={}
inputDict['doc1']='Document with some text'
inputDict['doc2']='Other document with some text'
params = urllib.urlencode(inputDict)
f = urllib2.urlopen(API_URL, params)
response= f.read()
responseObject=json.loads(response)
print responseObject
यदि आप पाठ के दो टुकड़ों की शब्दार्थ समानता को मापने में अधिक रुचि रखते हैं, तो मेरा सुझाव है कि इस गीतालाब परियोजना पर एक नज़र डालें । आप इसे सर्वर के रूप में चला सकते हैं, एक पूर्व-निर्मित मॉडल भी है जिसका उपयोग आप आसानी से पाठ के दो टुकड़ों की समानता को मापने के लिए कर सकते हैं; भले ही यह ज्यादातर दो वाक्यों की समानता को मापने के लिए प्रशिक्षित किया जाता है, फिर भी आप इसे अपने मामले में उपयोग कर सकते हैं। यह जावा में लिखा गया है, लेकिन आप इसे एक सेवा के रूप में चला सकते हैं।
एक अन्य विकल्प डीकेप्रो समानता भी है जो ग्रंथों की समानता को मापने के लिए विभिन्न एल्गोरिदम के साथ एक पुस्तकालय है। हालाँकि, इसे जावा में भी लिखा जाता है।
कोड उदाहरण:
// this similarity measure is defined in the dkpro.similarity.algorithms.lexical-asl package
// you need to add that to your .pom to make that example work
// there are some examples that should work out of the box in dkpro.similarity.example-gpl
TextSimilarityMeasure measure = new WordNGramJaccardMeasure(3); // Use word trigrams
String[] tokens1 = "This is a short example text .".split(" ");
String[] tokens2 = "A short example text could look like that .".split(" ");
double score = measure.getSimilarity(tokens1, tokens2);
System.out.println("Similarity: " + score);
बहुत कम डेटासेट के साथ वाक्य समानता को खोजने के लिए और उच्च सटीकता प्राप्त करने के लिए आप नीचे दिए गए पायथन पैकेज का उपयोग कर सकते हैं जो पहले से प्रशिक्षित किए गए कार्य का उपयोग कर रहा है,
pip install similar-sentences
सिंथेटिक समानता के लिए समानता का पता लगाने के 3 आसान तरीके हो सकते हैं।
शब्दार्थ समानता के लिए कोई भी BERT एम्बेडिंग का उपयोग कर सकता है और दस्तावेज़ एम्बेडिंग प्राप्त करने के लिए एक अलग शब्द पूलिंग रणनीति का प्रयास कर सकता है और फिर दस्तावेज़ एम्बेडिंग पर कोज़ाइन समानता लागू कर सकता है।
एक उन्नत पद्धति समानता प्राप्त करने के लिए BERT SCORE का उपयोग कर सकती है।
शोध पत्र लिंक: https://arxiv.org/abs/1904.09675