모든 프로그래밍 언어로 NLP 프로젝트를 작업하고 있습니다 (Python이 선호됩니다).
두 개의 문서를 가져 와서 얼마나 비슷한 지 결정하고 싶습니다.
답변
이를 수행하는 일반적인 방법은 문서를 TF-IDF 벡터로 변환 한 다음 이들 간의 코사인 유사성을 계산하는 것입니다. 정보 검색 (IR)에 관한 모든 교과서가 이에 해당됩니다. esp를 참조하십시오. 정보 검색 소개 는 무료이며 온라인으로 제공됩니다.
쌍별 유사성 계산
TF-IDF (및 유사한 텍스트 변환)는 Python 패키지 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
Gensim은 이런 종류의 작업에 더 많은 옵션을 제공 할 수 있습니다.
이 질문 도 참조하십시오 .
[면책 조항 : 나는 scikit-learn TF-IDF 구현에 관여했습니다.]
결과 해석
위에서, pairwise_similarity
Scipy 희소 행렬 은 정사각형이며 행과 열의 수는 말뭉치의 문서 수와 같습니다.
>>> pairwise_similarity
<5x5 sparse matrix of type '<class 'numpy.float64'>'
with 17 stored elements in Compressed Sparse Row format>
당신은 NumPy와 배열을 통해 스파 스 배열을 변환 할 수 있습니다 .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. ]])
“scikit-learn 문서는 주황색과 파란색입니다”라는 최종 문서와 가장 유사한 문서를 찾고 싶다고 가정하겠습니다. 이 문서의 색인은 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
답변
@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')
답변
그것은 오래된 질문이지만 Spacy로 쉽게 수행 할 수 있음을 알았습니다 . 문서가 읽 히면 간단한 API 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
답변
일반적으로 두 문서 간의 코사인 유사성이 문서의 유사성 측정으로 사용됩니다. Java에서는 Lucene (컬렉션이 꽤 큰 경우) 또는 LingPipe 를 사용하여이를 수행 할 수 있습니다. 기본 개념은 모든 문서에서 항을 세고 항 벡터의 내적을 계산하는 것입니다. 라이브러리는이 일반적인 접근 방식에 비해 여러 가지 개선 된 기능을 제공합니다. copmlex를 수행하려는 경우 LingPipe는 코사인 유사성보다 더 나은 결과를 제공하는 문서 간의 LSA 유사성을 계산하는 방법도 제공합니다. Python의 경우 NLTK 를 사용할 수 있습니다 .
답변
매우 정확한 것을 찾고 있다면 tf-idf보다 더 나은 도구를 사용해야합니다. 범용 문장 인코더 는 두 텍스트 사이의 유사성을 찾는 가장 정확한 것 중 하나입니다. Google은 처음부터 학습 할 필요없이 자체 애플리케이션에 사용할 수있는 사전 훈련 된 모델을 제공했습니다. 먼저 tensorflow 및 tensorflow-hub를 설치해야합니다.
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)
답변
코사인 문서 유사성 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