Tugas 5 : Mencari Dokumen berdasarkan Kalimat#
Pada Tugas 5 diminta untuk mencari dokumen berdasarkan kalimat yang dimasukkan. Data dokumen dilakukan proses TFIDF dan mengimplementasikan SVD (Singular Value Decomposition) untuk reduksi dimensi serta cosine similarity untuk mencari kedekatan antara kalimat dicari dengan dokumen yang ada.
Dibuat Oleh:
Nama : Sabil Ahmad Hidayat
NIM : 220411100058
Kelas : PPW A
Link Code : https://colab.research.google.com/drive/19V1Li_F8_euESGe6bhCEAcAFffKpnZ67?usp=sharing
Link Github : meinhere/ppw
Import Library#
!pip install -q Sastrawi
^C
# library awal untuk perhitungan dan pengolahan teks
import numpy as np
import re
import pandas as pd
import pickle
import requests
# monitoring
from tqdm import tqdm
# library untuk praproses teks
import nltk
nltk.download('stopwords')
nltk.download('wordnet')
nltk.download('punkt')
from nltk.tokenize import sent_tokenize
from nltk.corpus import stopwords
from Sastrawi.Stemmer.StemmerFactory import StemmerFactory
from sklearn.decomposition import TruncatedSVD
from sklearn.metrics.pairwise import cosine_similarity
# library untuk proses pembentukan vsm
from sklearn.feature_extraction.text import TfidfVectorizer
[nltk_data] Downloading package stopwords to /root/nltk_data...
[nltk_data] Unzipping corpora/stopwords.zip.
[nltk_data] Downloading package wordnet to /root/nltk_data...
[nltk_data] Downloading package punkt to /root/nltk_data...
[nltk_data] Unzipping tokenizers/punkt.zip.
Load Data#
tfidf_df = pd.read_csv('https://raw.githubusercontent.com/meinhere/ppw/master/publish/tugas-2/dataset/train_df_tfidf.csv', delimiter=',')
tfidf_df.drop(columns=['label'], inplace=True)
tfidf_df
| aaion | aali | abadi | abai | abenkh | abnormal | absurd | ac | acara | access | ... | yusdistira | yzr | za | zad | zaman | zarco | zenix | zero | zigzag | zona | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.058149 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 |
| 1 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 |
| 2 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 |
| 3 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 |
| 4 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 75 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 |
| 76 | 0.053854 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.037974 | 0.000000 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 |
| 77 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 |
| 78 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.121219 | 0.000000 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 |
| 79 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.059581 | 0.0 |
80 rows × 3106 columns
Implementasi SVD (Singular Value Decomposition)#
Proses Reduksi Dimensi#
# Menerapkan untuk LSA
n = 80 # Jumlah component/fitur yang ingin dihasilkan dari svd
svd = TruncatedSVD(n_components=n)
svd_matrix = svd.fit_transform(tfidf_df)
# Mengambil sebagian dari matrix V dan matrix Sigma
v_matrix = svd.components_ # Matrix V (komponen term)
singular_values = svd.singular_values_ # Matrix Sigma (singular values)
# Mengambil berapa jumlah component/fitur yang diinginkan
partial_n = 80
partial_v_matrix = v_matrix[:, :partial_n] # Mengambil matrix v dari jumlah yang diambil
partial_singular_values = singular_values[:partial_n] # Mengambil matrix Sigma dari jumlah yang diambil
# Menampilkan matrix svd
print(f"Shape : {svd_matrix.shape}")
print(svd_matrix)
# Menampilkan matrix v
print(f"Shape : {partial_v_matrix.shape}")
print(partial_v_matrix)
# Menampilkan matrix Sigma
print(f"Shape : {partial_singular_values.shape}")
print(partial_singular_values)
Shape : (80, 80)
[[ 1.54510634e-01 -9.21097057e-02 9.38904274e-03 ... -1.14938909e-03
-1.51825296e-04 8.67361738e-19]
[ 1.67615266e-01 -1.60479805e-01 1.23665623e-01 ... 3.11792566e-03
2.75914213e-04 8.67361738e-18]
[ 2.80561596e-01 -7.35551633e-02 -6.58748219e-02 ... -1.58720646e-04
-1.83127832e-03 -9.10729825e-18]
...
[ 2.45615049e-01 3.41531512e-02 2.11698472e-01 ... 1.37748793e-03
-9.76249092e-04 -3.46944695e-18]
[ 3.50620184e-01 4.61250396e-01 1.63725318e-01 ... -2.53879878e-03
4.38598240e-04 -7.26415456e-18]
[ 2.02074170e-01 4.51572108e-02 2.29484661e-01 ... 3.75707600e-02
8.40612527e-04 -1.78893358e-18]]
Shape : (80, 80)
[[ 2.01225651e-03 1.89116869e-03 1.89116869e-03 ... 4.84688813e-03
1.61562938e-03 3.23125875e-03]
[-2.57111925e-04 -3.92085852e-03 -3.92085852e-03 ... -5.81253948e-03
-1.93751316e-03 -3.87502632e-03]
[-5.34058540e-04 -8.34390309e-04 -8.34390309e-04 ... 1.68685095e-03
5.62283651e-04 1.12456730e-03]
...
[ 7.46625040e-04 7.03061102e-04 7.03061102e-04 ... -1.14463982e-03
-3.81546605e-04 -7.63093211e-04]
[ 1.58273886e-04 -3.30449574e-04 -3.30449574e-04 ... 1.02362094e-03
3.41206981e-04 6.82413962e-04]
[-5.85262899e-02 4.46086787e-01 1.66679860e-01 ... 7.30632388e-04
5.01054950e-03 -1.00171660e-03]]
Shape : (80,)
[2.08644723e+00 1.61046945e+00 1.51414718e+00 1.49010163e+00
1.42892895e+00 1.39172559e+00 1.38121960e+00 1.37914621e+00
1.33547173e+00 1.29436047e+00 1.24543876e+00 1.23159841e+00
1.21309281e+00 1.18452936e+00 1.15846926e+00 1.14678667e+00
1.13286842e+00 1.10834460e+00 1.10569312e+00 1.09306941e+00
1.07251215e+00 1.06992768e+00 1.04771950e+00 1.04668181e+00
1.03901828e+00 1.02815257e+00 1.02085022e+00 1.01620363e+00
1.00760994e+00 1.00682166e+00 1.00015803e+00 9.98080575e-01
9.90970953e-01 9.81076139e-01 9.74831789e-01 9.69639700e-01
9.67838856e-01 9.62715192e-01 9.61154589e-01 9.53983034e-01
9.45392116e-01 9.39711136e-01 9.34676233e-01 9.31641353e-01
9.28505148e-01 9.13952859e-01 9.12057024e-01 9.06423462e-01
9.02069972e-01 8.97080939e-01 8.96526698e-01 8.84540253e-01
8.70195758e-01 8.61985572e-01 8.58068447e-01 8.54400226e-01
8.36070057e-01 8.27691628e-01 8.09573151e-01 8.07580606e-01
7.79340481e-01 7.72334579e-01 7.67143915e-01 7.49185508e-01
7.28650204e-01 7.13854736e-01 7.09908188e-01 6.95030444e-01
6.93500732e-01 6.58185159e-01 6.52764474e-01 6.29340292e-01
6.10284846e-01 5.90495438e-01 5.76827008e-01 4.97811913e-01
3.79346297e-01 3.51456913e-01 2.95308832e-01 9.26568701e-16]
Save DataFrame#
# Convert the svd_matrix to a DataFrame
svd_df = pd.DataFrame(svd_matrix)
# Save the DataFrame to a CSV file
svd_df.to_csv('svd_matrix.csv', index=False)
Save Model SVD#
# Save the SVD model
with open('svd_model.pkl', 'wb') as f:
pickle.dump(svd, f)
Pencarian Dokumen dengan Kalimat#
Load Model#
github_raw_url = "https://raw.githubusercontent.com/meinhere/ppw/master/publish/tugas-3/model/tfidf_vectorizer.sav"
response = requests.get(github_raw_url)
response.raise_for_status()
vectorizer = pickle.loads(response.content)
vectorizer
TfidfVectorizer()In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
TfidfVectorizer()
svd = pickle.load(open('svd_model.pkl', 'rb'))
svd
TruncatedSVD(n_components=80)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
TruncatedSVD(n_components=80)
Persiapan Preprocessing#
# Case Folding
def clean_lower(lwr):
lwr = lwr.lower() # lowercase text
return lwr
# Menghapus tanda baca, angka, dan simbol
def clean_punct(text):
clean_spcl = re.compile('[/(){}\[\]\|@,;_]')
clean_symbol = re.compile('[^0-9a-z]')
clean_number = re.compile('[0-9]')
text = clean_spcl.sub('', text)
text = clean_symbol.sub(' ', text)
text = clean_number.sub('', text)
return text
# Menghaps double atau lebih whitespace
def _normalize_whitespace(text):
corrected = str(text)
corrected = re.sub(r"//t",r"\t", corrected)
corrected = re.sub(r"( )\1+",r"\1", corrected)
corrected = re.sub(r"(\n)\1+",r"\1", corrected)
corrected = re.sub(r"(\r)\1+",r"\1", corrected)
corrected = re.sub(r"(\t)\1+",r"\1", corrected)
return corrected.strip(" ")
# Menghapus stopwords
def clean_stopwords(text):
stopword = set(stopwords.words('indonesian'))
text = ' '.join(word for word in text.split() if word not in stopword) # hapus stopword dari kolom deskripsi
return text
# Stemming with Sastrawi
def sastrawistemmer(text):
factory = StemmerFactory()
st = factory.create_stemmer()
text = ' '.join(st.stem(word) for word in tqdm(text.split()) if word in text)
return text
Definisi Fungsi#
def preprocess_text(text):
text = clean_lower(text)
text = clean_punct(text)
text = _normalize_whitespace(text)
text = clean_stopwords(text)
text = sastrawistemmer(text)
return text
def search_doc(query, top=5):
query = preprocess_text(query)
query_tfidf = vectorizer.transform([query])
query_tfidf = pd.DataFrame(query_tfidf.toarray(), columns=vectorizer.get_feature_names_out())
query_svd = svd.transform(query_tfidf)
similarity = cosine_similarity(query_svd, svd_matrix).flatten()
top_indices = similarity.argsort()[-top:][::-1]
top_similarity = similarity[top_indices]
top_df = []
for i in range(len(top_indices)):
data = {}
data['dokumen ke'] = top_indices[i]
data['similarity'] = top_similarity[i]
top_df.append(data)
top_df = pd.DataFrame(top_df)
top_df = top_df.sort_values(by='similarity', ascending=False)
return top_df
Pengujian Pencarian#
query = "indonesia"
results = search_doc(query)
results
100%|██████████| 1/1 [00:00<00:00, 279.92it/s]
| dokumen ke | similarity | |
|---|---|---|
| 0 | 12 | 0.649388 |
| 1 | 50 | 0.441052 |
| 2 | 8 | 0.384027 |
| 3 | 26 | 0.336437 |
| 4 | 45 | 0.300869 |