Python: tf-idf-cosine: เพื่อค้นหาความคล้ายคลึงกันของเอกสาร


93

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

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from nltk.corpus import stopwords
import numpy as np
import numpy.linalg as LA

train_set = ["The sky is blue.", "The sun is bright."]  # Documents
test_set = ["The sun in the sky is bright."]  # Query
stopWords = stopwords.words('english')

vectorizer = CountVectorizer(stop_words = stopWords)
#print vectorizer
transformer = TfidfTransformer()
#print transformer

trainVectorizerArray = vectorizer.fit_transform(train_set).toarray()
testVectorizerArray = vectorizer.transform(test_set).toarray()
print 'Fit Vectorizer to train set', trainVectorizerArray
print 'Transform Vectorizer to test set', testVectorizerArray

transformer.fit(trainVectorizerArray)
print
print transformer.transform(trainVectorizerArray).toarray()

transformer.fit(testVectorizerArray)
print 
tfidf = transformer.transform(testVectorizerArray)
print tfidf.todense()

อันเป็นผลมาจากรหัสด้านบนฉันมีเมทริกซ์ต่อไปนี้

Fit Vectorizer to train set [[1 0 1 0]
 [0 1 0 1]]
Transform Vectorizer to test set [[0 1 1 1]]

[[ 0.70710678  0.          0.70710678  0.        ]
 [ 0.          0.70710678  0.          0.70710678]]

[[ 0.          0.57735027  0.57735027  0.57735027]]

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


3
สำหรับเวกเตอร์แต่ละตัวใน trainVectorizerArray คุณต้องหาค่าความคล้ายคลึงโคไซน์กับเวกเตอร์ใน testVectorizerArray
ยกเว้น

@excray ขอบคุณด้วยประเด็นที่เป็นประโยชน์ของคุณฉันจัดการเพื่อหาคำตอบได้ไหม
add-semi-colons

@excray แต่ฉันมีคำถามเล็กน้อยการคำนวณ actuall tf * idf ไม่มีประโยชน์สำหรับสิ่งนี้เพราะฉันไม่ได้ใช้ผลลัพธ์สุดท้ายที่แสดงในเมทริกซ์
add-semi-colons

4
นี่คือส่วนที่ 3 ของบทช่วยสอนที่คุณอ้างถึงซึ่งจะตอบคำถามของคุณโดยละเอียดpyevolve.sourceforge.net/wordpress/?p=2497
Clément Renaud

@ ClémentRenaudฉันตามด้วยลิงค์ที่คุณให้มา แต่เนื่องจากเอกสารของฉันมีขนาดใหญ่ขึ้นมันก็เริ่มที่จะโยน MemoryError เราจะจัดการได้อย่างไร?
ashim888

คำตอบ:


173

ก่อนอื่นถ้าคุณต้องการแยกคุณสมบัติการนับและใช้การทำให้เป็นมาตรฐาน TF-IDF และการทำให้เป็นมาตรฐานยูคลิดแบบแถวคุณสามารถทำได้ในการดำเนินการเดียวด้วยTfidfVectorizer:

>>> from sklearn.feature_extraction.text import TfidfVectorizer
>>> from sklearn.datasets import fetch_20newsgroups
>>> twenty = fetch_20newsgroups()

>>> tfidf = TfidfVectorizer().fit_transform(twenty.data)
>>> tfidf
<11314x130088 sparse matrix of type '<type 'numpy.float64'>'
    with 1787553 stored elements in Compressed Sparse Row format>

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

ตามที่คริสคลาร์กอธิบายในความคิดเห็นและที่นี่ความคล้ายคลึงกันของโคไซน์ไม่ได้คำนึงถึงขนาดของเวกเตอร์ Row-normalized มีขนาดเท่ากับ 1 ดังนั้น Linear Kernel จึงเพียงพอที่จะคำนวณค่าความคล้ายคลึงกัน

API เมทริกซ์แบบกระจัดกระจาย scipy นั้นค่อนข้างแปลก (ไม่ยืดหยุ่นเท่าอาร์เรย์ numpy ที่มีมิติหนาแน่น) ในการรับเวกเตอร์แรกคุณต้องแบ่งแถวเมทริกซ์อย่างชาญฉลาดเพื่อให้ได้เมทริกซ์ย่อยด้วยแถวเดียว:

>>> tfidf[0:1]
<1x130088 sparse matrix of type '<type 'numpy.float64'>'
    with 89 stored elements in Compressed Sparse Row format>

scikit-learn มีเมตริกแบบคู่ (aka kernels ในการเรียนรู้ของเครื่อง) ซึ่งใช้ได้กับทั้งการแสดงคอลเลกชันเวกเตอร์ที่หนาแน่นและเบาบาง ในกรณีนี้เราต้องการผลิตภัณฑ์ดอทที่เรียกอีกอย่างว่าเคอร์เนลเชิงเส้น:

>>> from sklearn.metrics.pairwise import linear_kernel
>>> cosine_similarities = linear_kernel(tfidf[0:1], tfidf).flatten()
>>> cosine_similarities
array([ 1.        ,  0.04405952,  0.11016969, ...,  0.04433602,
    0.04457106,  0.03293218])

ดังนั้นในการค้นหาเอกสารที่เกี่ยวข้อง 5 อันดับแรกเราสามารถใช้argsortและการแบ่งส่วนอาร์เรย์เชิงลบ (เอกสารที่เกี่ยวข้องส่วนใหญ่มีค่าความคล้ายคลึงกันของโคไซน์สูงสุดดังนั้นในตอนท้ายของอาร์เรย์ดัชนีที่เรียงลำดับ):

>>> related_docs_indices = cosine_similarities.argsort()[:-5:-1]
>>> related_docs_indices
array([    0,   958, 10576,  3277])
>>> cosine_similarities[related_docs_indices]
array([ 1.        ,  0.54967926,  0.32902194,  0.2825788 ])

ผลลัพธ์แรกคือการตรวจสอบความมีสติ: เราพบว่าเอกสารแบบสอบถามเป็นเอกสารที่คล้ายกันมากที่สุดโดยมีคะแนนความคล้ายคลึงกันของโคไซน์เท่ากับ 1 ซึ่งมีข้อความต่อไปนี้:

>>> print twenty.data[0]
From: lerxst@wam.umd.edu (where's my thing)
Subject: WHAT car is this!?
Nntp-Posting-Host: rac3.wam.umd.edu
Organization: University of Maryland, College Park
Lines: 15

 I was wondering if anyone out there could enlighten me on this car I saw
the other day. It was a 2-door sports car, looked to be from the late 60s/
early 70s. It was called a Bricklin. The doors were really small. In addition,
the front bumper was separate from the rest of the body. This is
all I know. If anyone can tellme a model name, engine specs, years
of production, where this car is made, history, or whatever info you
have on this funky looking car, please e-mail.

Thanks,
- IL
   ---- brought to you by your neighborhood Lerxst ----

เอกสารที่คล้ายกันมากที่สุดอันดับสองคือคำตอบที่อ้างถึงข้อความต้นฉบับด้วยเหตุนี้จึงมีคำทั่วไปหลายคำ:

>>> print twenty.data[958]
From: rseymour@reed.edu (Robert Seymour)
Subject: Re: WHAT car is this!?
Article-I.D.: reed.1993Apr21.032905.29286
Reply-To: rseymour@reed.edu
Organization: Reed College, Portland, OR
Lines: 26

In article <1993Apr20.174246.14375@wam.umd.edu> lerxst@wam.umd.edu (where's my
thing) writes:
>
>  I was wondering if anyone out there could enlighten me on this car I saw
> the other day. It was a 2-door sports car, looked to be from the late 60s/
> early 70s. It was called a Bricklin. The doors were really small. In
addition,
> the front bumper was separate from the rest of the body. This is
> all I know. If anyone can tellme a model name, engine specs, years
> of production, where this car is made, history, or whatever info you
> have on this funky looking car, please e-mail.

Bricklins were manufactured in the 70s with engines from Ford. They are rather
odd looking with the encased front bumper. There aren't a lot of them around,
but Hemmings (Motor News) ususally has ten or so listed. Basically, they are a
performance Ford with new styling slapped on top.

>    ---- brought to you by your neighborhood Lerxst ----

Rush fan?

--
Robert Seymour              rseymour@reed.edu
Physics and Philosophy, Reed College    (NeXTmail accepted)
Artificial Life Project         Reed College
Reed Solar Energy Project (SolTrain)    Portland, OR

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

คุณสามารถใช้คำค้นหา "เพิ่มเติมเช่นนี้" ของ Elastic Search และ Solr ซึ่งควรให้คำตอบโดยประมาณพร้อมกับโปรไฟล์ความสามารถในการปรับขนาดเชิงเส้น
ogrisel

7
สิ่งนี้จะทำให้คุณมีความคล้ายคลึงกันของเอกสารแต่ละฉบับกับเอกสารอื่น ๆ ทั้งหมดแทนที่จะเป็นเพียงเอกสารแรก: cosine_similarities = linear_kernel(tfidf, tfidf)?
ionox0

2
ใช่นี่จะทำให้คุณได้เมทริกซ์กำลังสองที่มีความคล้ายคลึงกัน
ogrisel

10
ในกรณีที่คนอื่นสงสัยเหมือนฉันในกรณีนี้ linear_kernel จะเทียบเท่ากับ cosine_similarity เนื่องจาก TfidfVectorizer สร้างเวกเตอร์ที่เป็นมาตรฐาน ดูหมายเหตุในเอกสาร: scikit-learn.org/stable/modules/metrics.html#cosine-similarity
Chris Clark

22

ด้วยความช่วยเหลือของความคิดเห็นของ @ excray ฉันจัดการเพื่อหาคำตอบสิ่งที่เราต้องทำจริงๆคือเขียนแบบง่ายๆสำหรับการวนซ้ำเพื่อวนซ้ำสองอาร์เรย์ที่แสดงถึงข้อมูลรถไฟและข้อมูลการทดสอบ

ขั้นแรกให้ใช้ฟังก์ชันแลมด้าอย่างง่ายเพื่อเก็บสูตรสำหรับการคำนวณโคไซน์:

cosine_function = lambda a, b : round(np.inner(a, b)/(LA.norm(a)*LA.norm(b)), 3)

จากนั้นเขียนแบบธรรมดาสำหรับการวนซ้ำเพื่อวนซ้ำบนเวกเตอร์ถึงตรรกะคือสำหรับทุก ๆ "สำหรับเวกเตอร์แต่ละตัวใน trainVectorizerArray คุณต้องหาค่าโคไซน์ที่คล้ายคลึงกับเวกเตอร์ใน testVectorizerArray"

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from nltk.corpus import stopwords
import numpy as np
import numpy.linalg as LA

train_set = ["The sky is blue.", "The sun is bright."] #Documents
test_set = ["The sun in the sky is bright."] #Query
stopWords = stopwords.words('english')

vectorizer = CountVectorizer(stop_words = stopWords)
#print vectorizer
transformer = TfidfTransformer()
#print transformer

trainVectorizerArray = vectorizer.fit_transform(train_set).toarray()
testVectorizerArray = vectorizer.transform(test_set).toarray()
print 'Fit Vectorizer to train set', trainVectorizerArray
print 'Transform Vectorizer to test set', testVectorizerArray
cx = lambda a, b : round(np.inner(a, b)/(LA.norm(a)*LA.norm(b)), 3)

for vector in trainVectorizerArray:
    print vector
    for testV in testVectorizerArray:
        print testV
        cosine = cx(vector, testV)
        print cosine

transformer.fit(trainVectorizerArray)
print
print transformer.transform(trainVectorizerArray).toarray()

transformer.fit(testVectorizerArray)
print 
tfidf = transformer.transform(testVectorizerArray)
print tfidf.todense()

นี่คือผลลัพธ์:

Fit Vectorizer to train set [[1 0 1 0]
 [0 1 0 1]]
Transform Vectorizer to test set [[0 1 1 1]]
[1 0 1 0]
[0 1 1 1]
0.408
[0 1 0 1]
[0 1 1 1]
0.816

[[ 0.70710678  0.          0.70710678  0.        ]
 [ 0.          0.70710678  0.          0.70710678]]

[[ 0.          0.57735027  0.57735027  0.57735027]]

1
ดีจัง.. ฉันก็เรียนรู้ตั้งแต่แรกเช่นกันคำถามและคำตอบของคุณง่ายที่สุดที่จะปฏิบัติตาม ฉันคิดว่าคุณสามารถใช้ np.corrcoef () แทนวิธีการม้วนของคุณเอง
wbg

วัตถุประสงค์ของการtransformer.fitดำเนินงานtfidf.todense()คืออะไร? คุณได้ค่าความคล้ายคลึงกันจากลูปแล้วทำ tfidf ต่อไป? ค่าโคไซน์ที่คำนวณของคุณถูกนำไปใช้ที่ไหน? ตัวอย่างของคุณทำให้สับสน
แร่ธาตุ

โคไซน์จะกลับมาเป็นอย่างไรถ้าคุณไม่คิดจะอธิบาย ในตัวอย่างที่คุณได้รับ0.408และ0.816ค่าเหล่านี้คืออะไร?
buydadip

20

ฉันรู้ว่ามันเป็นโพสต์เก่า แต่ฉันลองใช้แพ็คเกจhttp://scikit-learn.sourceforge.net/stable/ นี่คือรหัสของฉันเพื่อค้นหาความคล้ายคลึงกันของโคไซน์ คำถามคือคุณจะคำนวณความคล้ายคลึงกันของโคไซน์กับแพ็คเกจนี้ได้อย่างไรและนี่คือรหัสของฉันสำหรับสิ่งนั้น

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.feature_extraction.text import TfidfVectorizer

f = open("/root/Myfolder/scoringDocuments/doc1")
doc1 = str.decode(f.read(), "UTF-8", "ignore")
f = open("/root/Myfolder/scoringDocuments/doc2")
doc2 = str.decode(f.read(), "UTF-8", "ignore")
f = open("/root/Myfolder/scoringDocuments/doc3")
doc3 = str.decode(f.read(), "UTF-8", "ignore")

train_set = ["president of India",doc1, doc2, doc3]

tfidf_vectorizer = TfidfVectorizer()
tfidf_matrix_train = tfidf_vectorizer.fit_transform(train_set)  #finds the tfidf score with normalization
print "cosine scores ==> ",cosine_similarity(tfidf_matrix_train[0:1], tfidf_matrix_train)  #here the first element of tfidf_matrix_train is matched with other three elements

ต่อไปนี้สมมติว่าแบบสอบถามเป็นองค์ประกอบแรกของ train_set และ doc1, doc2 และ doc3 เป็นเอกสารที่ฉันต้องการจัดอันดับด้วยความช่วยเหลือของความคล้ายคลึงกันของโคไซน์ จากนั้นฉันสามารถใช้รหัสนี้

นอกจากนี้แบบฝึกหัดที่ให้ไว้ในคำถามก็มีประโยชน์มาก นี่คือส่วนทั้งหมดของมัน part-I , part-II , part-III

ผลลัพธ์จะเป็นดังนี้:

[[ 1.          0.07102631  0.02731343  0.06348799]]

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


1
cosine_similarity (tfidf_matrix_train [0: 1], tfidf_matrix_train) จะเป็นอย่างไรถ้า 1 นั้นเปลี่ยนเป็นมากกว่าหลายพัน เราจะจัดการได้อย่างไร ??
ashim888

1
วิธีจัดการValueError: Incompatible dimension for X and Y matrices: X.shape[1] == 1664 while Y.shape[1] == 2
pyd

17

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

คุณจึงมีlist_of_documentsซึ่งเป็นเพียงอาร์เรย์ของสตริงและอีกdocumentอันซึ่งเป็นเพียงสตริง คุณต้องไปหาเอกสารดังกล่าวจากที่อยู่ที่จะคล้ายกันมากที่สุดlist_of_documentsdocument

มารวมเข้าด้วยกัน: documents = list_of_documents + [document]

เริ่มต้นด้วยการอ้างอิง มันจะชัดเจนว่าทำไมเราถึงใช้แต่ละอย่าง

from nltk.corpus import stopwords
import string
from nltk.tokenize import wordpunct_tokenize as tokenize
from nltk.stem.porter import PorterStemmer
from sklearn.feature_extraction.text import TfidfVectorizer
from scipy.spatial.distance import cosine

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

ในภาษาอังกฤษและภาษาอื่น ๆ ของมนุษย์มีคำที่ "ไร้ประโยชน์" มากมายเช่น "a", "the", "in" ซึ่งเป็นเรื่องปกติมากจนไม่มีความหมายมากนัก พวกเขาเรียกว่าคำหยุดและเป็นความคิดที่ดีที่จะลบออก สิ่งที่สังเกตได้อีกอย่างหนึ่งก็คือคำว่า 'วิเคราะห์', 'ตัววิเคราะห์', 'การวิเคราะห์' นั้นคล้ายกันมาก พวกเขามีรากทั่วไปและสามารถแปลงเป็นคำเดียวได้ กระบวนการนี้เรียกว่าเกิดและมีอยู่ Stemmers ที่แตกต่างกันซึ่งแตกต่างกันในความเร็วแข็งขันและอื่น ๆ ดังนั้นเราจึงแปลงเอกสารแต่ละรายการให้เป็นรายการของคำโดยไม่ต้องหยุดคำ นอกจากนี้เรายังทิ้งเครื่องหมายวรรคตอนทั้งหมด

porter = PorterStemmer()
stop_words = set(stopwords.words('english'))

modified_arr = [[porter.stem(i.lower()) for i in tokenize(d.translate(None, string.punctuation)) if i.lower() not in stop_words] for d in documents]

แล้วถุงคำนี้จะช่วยเราได้อย่างไร? ลองนึกภาพเรามี 3 ถุง: [a, b, c], และ[a, c, a] [b, c, d]เราสามารถแปลงให้เป็นพาหะในพื้นฐาน [a, b, c, d]ดังนั้นเราจึงลงเอยด้วยเวกเตอร์: [1, 1, 1, 0], [2, 0, 1, 0]และ[0, 1, 1, 1]. สิ่งที่คล้ายกันคือกับเอกสารของเรา (เฉพาะเวกเตอร์เท่านั้นที่จะยาวขึ้น) ตอนนี้เราเห็นว่าเราลบคำจำนวนมากและตั้งคำอื่น ๆ ด้วยเพื่อลดขนาดของเวกเตอร์ ที่นี่มีข้อสังเกตที่น่าสนใจเพียง เอกสารที่ยาวกว่าจะมีองค์ประกอบเชิงบวกมากกว่าแบบสั้นนั่นเป็นเหตุผลที่ดีที่จะทำให้เวกเตอร์เป็นปกติ สิ่งนี้เรียกว่าระยะความถี่ TF ผู้คนยังใช้ข้อมูลเพิ่มเติมเกี่ยวกับความถี่ในการใช้คำในเอกสารอื่น ๆ - IDF ความถี่เอกสารผกผัน เรามีตัวชี้วัดTF-IDF ซึ่งมีสองรสชาติด้วยกัน. สิ่งนี้สามารถทำได้ด้วยหนึ่งบรรทัดใน sklearn :-)

modified_doc = [' '.join(i) for i in modified_arr] # this is only to convert our list of lists to list of strings that vectorizer uses.
tf_idf = TfidfVectorizer().fit_transform(modified_doc)

vectorizer ที่จริงแล้วช่วยให้สามารถทำสิ่งต่างๆได้มากมายเช่นการลบคำหยุดและตัวย่อ ฉันทำในขั้นตอนแยกต่างหากเพราะ sklearn ไม่มีคำหยุดที่ไม่ใช่ภาษาอังกฤษ แต่มี nltk

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

l = len(documents) - 1
for i in xrange(l):
    minimum = (1, None)
    minimum = min((cosine(tf_idf[i].todense(), tf_idf[l + 1].todense()), i), minimum)
print minimum

ตอนนี้ขั้นต่ำจะมีข้อมูลเกี่ยวกับเอกสารที่ดีที่สุดและคะแนน


3
ลงชื่อนี่ไม่ใช่สิ่งที่ฝ่ายปฏิบัติการต้องการ: ค้นหาเอกสารที่ดีที่สุดที่ให้มาไม่ใช่ "เอกสารที่ดีที่สุด" ในคลังข้อมูล โปรดอย่าทำแบบนั้นคนอย่างฉันจะเสียเวลาไปกับการพยายามใช้ตัวอย่างของคุณสำหรับงาน op และถูกลากเข้าสู่ความบ้าคลั่งในการปรับขนาดเมทริกซ์
แร่ธาตุ

และแตกต่างกันอย่างไร? ความคิดเหมือนกันหมด แยกคุณสมบัติคำนวณระยะทางโคไซน์ระหว่างแบบสอบถามและเอกสาร
Salvador Dali

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

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

12

สิ่งนี้จะช่วยคุณได้

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity  

tfidf_vectorizer = TfidfVectorizer()
tfidf_matrix = tfidf_vectorizer.fit_transform(train_set)
print tfidf_matrix
cosine = cosine_similarity(tfidf_matrix[length-1], tfidf_matrix)
print cosine

และผลลัพธ์จะเป็น:

[[ 0.34949812  0.81649658  1.        ]]

9
คุณจะได้ความยาวได้อย่างไร?
gogasca

3

นี่คือฟังก์ชั่นที่เปรียบเทียบข้อมูลการทดสอบของคุณกับข้อมูลการฝึกอบรมโดยที่หม้อแปลง Tf-Idf จะพอดีกับข้อมูลการฝึกอบรม ข้อได้เปรียบคือคุณสามารถหมุนหรือจัดกลุ่มได้อย่างรวดเร็วเพื่อค้นหาองค์ประกอบที่ใกล้เคียงที่สุด n และการคำนวณจะลดลงของเมทริกซ์

def create_tokenizer_score(new_series, train_series, tokenizer):
    """
    return the tf idf score of each possible pairs of documents
    Args:
        new_series (pd.Series): new data (To compare against train data)
        train_series (pd.Series): train data (To fit the tf-idf transformer)
    Returns:
        pd.DataFrame
    """

    train_tfidf = tokenizer.fit_transform(train_series)
    new_tfidf = tokenizer.transform(new_series)
    X = pd.DataFrame(cosine_similarity(new_tfidf, train_tfidf), columns=train_series.index)
    X['ix_new'] = new_series.index
    score = pd.melt(
        X,
        id_vars='ix_new',
        var_name='ix_train',
        value_name='score'
    )
    return score

train_set = pd.Series(["The sky is blue.", "The sun is bright."])
test_set = pd.Series(["The sun in the sky is bright."])
tokenizer = TfidfVectorizer() # initiate here your own tokenizer (TfidfVectorizer, CountVectorizer, with stopwords...)
score = create_tokenizer_score(train_series=train_set, new_series=test_set, tokenizer=tokenizer)
score

   ix_new   ix_train    score
0   0       0       0.617034
1   0       1       0.862012

pandas.pydata.org/pandas-docs/stable/reference/api/… อธิบายว่า pd.melt ทำอะไร
Golden Lion

สำหรับดัชนีใน np.arange (0, len (score)): value = score.loc [index, 'score']
Golden Lion
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.