Saya mengikuti tutorial yang tersedia di Bagian 1 & Bagian 2 . Sayangnya penulis tidak memiliki waktu untuk bagian terakhir yang menggunakan kesamaan kosinus untuk benar-benar menemukan jarak antara dua dokumen. Saya mengikuti contoh dalam artikel dengan bantuan tautan berikut dari stackoverflow , termasuk kode yang disebutkan di tautan di atas (hanya untuk membuat hidup lebih mudah)
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()
sebagai hasil dari kode di atas saya memiliki matriks berikut
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]]
Saya tidak yakin bagaimana menggunakan output ini untuk menghitung kesamaan kosinus, saya tahu bagaimana menerapkan kesamaan kosinus sehubungan dengan dua vektor dengan panjang yang sama tetapi di sini saya tidak yakin bagaimana mengidentifikasi dua vektor.
python
machine-learning
nltk
information-retrieval
tf-idf
tambahkan titik koma
sumber
sumber
Jawaban:
Pertama, jika Anda ingin mengekstrak fitur penghitungan dan menerapkan normalisasi TF-IDF dan normalisasi euclidean berdasarkan baris, Anda dapat melakukannya dalam satu operasi dengan
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>
Sekarang untuk mencari jarak cosinus dari satu dokumen (misalnya yang pertama dalam dataset) dan yang lainnya, Anda hanya perlu menghitung perkalian titik dari vektor pertama dengan yang lainnya karena vektor tfidf sudah dinormalisasi baris.
Seperti dijelaskan oleh Chris Clark dalam komentar dan di sini Cosine Similarity tidak memperhitungkan besarnya vektor. Baris dinormalisasi memiliki besaran 1 sehingga Linear Kernel cukup untuk menghitung nilai kesamaan.
API matriks jarang scipy agak aneh (tidak sefleksibel array numpy dimensi-N yang padat). Untuk mendapatkan vektor pertama, Anda perlu mengiris baris matriks untuk mendapatkan submatriks dengan satu baris:
>>> tfidf[0:1] <1x130088 sparse matrix of type '<type 'numpy.float64'>' with 89 stored elements in Compressed Sparse Row format>
scikit-learn sudah menyediakan metrik berpasangan (alias kernel dalam bahasa machine learning) yang berfungsi untuk representasi koleksi vektor yang padat dan jarang. Dalam hal ini kita membutuhkan perkalian titik yang juga dikenal sebagai kernel linier:
>>> 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])
Karenanya untuk menemukan 5 dokumen terkait teratas, kita dapat menggunakan
argsort
dan beberapa pemotongan array negatif (sebagian besar dokumen terkait memiliki nilai kesamaan kosinus tertinggi, maka di akhir array indeks yang diurutkan):>>> 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 ])
Hasil pertama adalah pemeriksaan kewarasan: kami menemukan dokumen kueri sebagai dokumen yang paling mirip dengan skor kesamaan kosinus 1 yang memiliki teks berikut:
>>> print twenty.data[0] From: [email protected] (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 ----
Dokumen kedua yang paling mirip adalah balasan yang mengutip pesan asli sehingga memiliki banyak kata yang sama:
>>> print twenty.data[958] From: [email protected] (Robert Seymour) Subject: Re: WHAT car is this!? Article-I.D.: reed.1993Apr21.032905.29286 Reply-To: [email protected] Organization: Reed College, Portland, OR Lines: 26 In article <1993Apr20.174246.14375@wam.umd.edu> [email protected] (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 [email protected] Physics and Philosophy, Reed College (NeXTmail accepted) Artificial Life Project Reed College Reed Solar Energy Project (SolTrain) Portland, OR
sumber
cosine_similarities = linear_kernel(tfidf, tfidf)
?Dengan Bantuan komentar @ excray, saya berhasil menemukan jawabannya, Apa yang perlu kita lakukan sebenarnya adalah menulis loop for sederhana untuk mengulangi dua array yang mewakili data kereta dan data pengujian.
Pertama, terapkan fungsi lambda sederhana untuk menampung rumus untuk perhitungan kosinus:
cosine_function = lambda a, b : round(np.inner(a, b)/(LA.norm(a)*LA.norm(b)), 3)
Dan kemudian tulis saja loop for sederhana untuk mengulang ke vektor ke, logikanya adalah untuk setiap "Untuk setiap vektor di trainVectorizerArray, Anda harus menemukan kesamaan kosinus dengan vektor di 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()
Inilah hasilnya:
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]]
sumber
transformer.fit
operasi dantfidf.todense()
? Anda mendapatkan nilai kesamaan Anda dari loop dan kemudian melanjutkan melakukan tfidf? Di mana nilai kosinus terhitung Anda digunakan? Teladan Anda membingungkan.0.408
dan0.816
, apakah nilai-nilai ini?Saya tahu ini posting lama. tetapi saya mencoba paket http://scikit-learn.sourceforge.net/stable/ . berikut adalah kode saya untuk menemukan kesamaan kosinus. Pertanyaannya adalah bagaimana Anda menghitung kemiripan kosinus dengan paket ini dan inilah kode saya untuk itu
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
Di sini misalkan kueri adalah elemen pertama dari train_set dan doc1, doc2 dan doc3 adalah dokumen yang ingin saya rangking dengan bantuan cosine similarity. maka saya dapat menggunakan kode ini.
Juga tutorial yang diberikan dalam pertanyaan itu sangat berguna. Ini semua bagian untuk itu bagian-I , bagian-II , bagian-III
outputnya adalah sebagai berikut:
[[ 1. 0.07102631 0.02731343 0.06348799]]
di sini 1 menunjukkan bahwa kueri cocok dengan dirinya sendiri dan tiga lainnya adalah skor untuk mencocokkan kueri dengan dokumen terkait.
sumber
ValueError: Incompatible dimension for X and Y matrices: X.shape[1] == 1664 while Y.shape[1] == 2
Izinkan saya memberi Anda tutorial lain yang saya tulis. Ini menjawab pertanyaan Anda, tetapi juga menjelaskan mengapa kami melakukan beberapa hal. Saya juga mencoba membuatnya ringkas.
Jadi Anda memiliki
list_of_documents
yang hanya berupa larik string dan lainnyadocument
yang hanya berupa string. Anda perlu menemukan dokumen seperti itu darilist_of_documents
yang paling mirip dengandocument
.Mari kita gabungkan keduanya:
documents = list_of_documents + [document]
Mari kita mulai dengan dependensi. Ini akan menjadi jelas mengapa kami menggunakan masing-masing.
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
Salah satu pendekatan yang bisa digunakan adalah kantong kata-kata , di mana kita memperlakukan setiap kata dalam dokumen secara terpisah dan hanya memasukkan semuanya ke dalam tas besar. Dari satu sudut pandang, ia kehilangan banyak informasi (seperti bagaimana kata-kata itu dihubungkan), tetapi dari sudut pandang lain, modelnya menjadi sederhana.
Dalam bahasa Inggris dan bahasa manusia lainnya ada banyak kata "tidak berguna" seperti 'a', 'the', 'in' yang sangat umum sehingga tidak memiliki banyak arti. Mereka disebut kata - kata berhenti dan merupakan ide yang baik untuk menghapusnya. Hal lain yang bisa diperhatikan adalah kata-kata seperti 'analyzer', 'analyzer', 'analysis' sangat mirip. Mereka memiliki akar yang sama dan semuanya dapat diubah menjadi hanya satu kata. Proses ini disebut stemming dan terdapat perbedaan stemmer yang berbeda dalam kecepatan, agresivitas dan sebagainya. Jadi kami mengubah setiap dokumen menjadi daftar batang kata tanpa kata henti. Juga kami membuang semua tanda baca.
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]
Jadi bagaimana tas berisi kata-kata ini akan membantu kita? Bayangkan kita memiliki 3 tas:
[a, b, c]
,[a, c, a]
dan[b, c, d]
. Kita dapat mengonversinya menjadi vektor dalam basis[a, b, c, d]
. Jadi kita berakhir dengan vektor:[1, 1, 1, 0]
,[2, 0, 1, 0]
dan[0, 1, 1, 1]
. Hal yang sama juga terjadi pada dokumen kita (hanya vektor yang lebih panjang). Sekarang kita melihat bahwa kita menghapus banyak kata dan menangkis lainnya juga untuk mengurangi dimensi vektor. Di sini hanya ada pengamatan menarik. Dokumen yang lebih panjang akan memiliki lebih banyak elemen positif daripada yang lebih pendek, itulah mengapa bagus untuk menormalkan vektor. Ini disebut TF frekuensi istilah, orang juga menggunakan informasi tambahan tentang seberapa sering kata tersebut digunakan dalam dokumen lain - IDF frekuensi dokumen terbalik. Bersama-sama kami memiliki metrik TF-IDF yang memiliki beberapa rasa. Ini dapat dicapai dengan satu baris di 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)
Sebenarnya vectorizer memungkinkan untuk melakukan banyak hal seperti menghapus kata-kata berhenti dan huruf kecil. Saya telah melakukannya dalam langkah terpisah hanya karena sklearn tidak memiliki stopwords non-Inggris, tetapi nltk memilikinya.
Jadi kita memiliki semua vektor yang dihitung. Langkah terakhir adalah menemukan mana yang paling mirip dengan yang terakhir. Ada berbagai cara untuk mencapainya, salah satunya adalah jarak Euclidean yang tidak terlalu jauh untuk alasan yang dibahas disini . Pendekatan lain adalah kesamaan kosinus . Kami mengulangi semua dokumen dan menghitung kesamaan kosinus antara dokumen dan yang terakhir:
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
Sekarang minimum akan memiliki informasi tentang dokumen terbaik dan nilainya.
sumber
Ini akan membantu Anda.
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
dan keluarannya adalah:
[[ 0.34949812 0.81649658 1. ]]
sumber
Berikut adalah fungsi yang membandingkan data pengujian Anda dengan data pelatihan, dengan transformator Tf-Idf yang dilengkapi dengan data pelatihan. Keuntungannya adalah Anda dapat dengan cepat melakukan pivot atau mengelompokkan untuk menemukan n elemen terdekat, dan perhitungannya turun berdasarkan matriks.
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
sumber