text classification dengan knn

Text Classification dengan K Nearest Neighbors

Pada tutorial kali ini, kita akan membuat text classification dengan KNN atau K Nearest Neighbors. KNN sendiri meurpakan algoritma yang digunakan untuk klasifikasi dengan mencari nilai K terdekat pada data training dan menggunakan label terdekat sebagai hasil prediksi. Untuk mencari jarak terdekat pada KNN bisa menggunakan euclidean distance.

Untuk text classification, kita akan menggunakan library nltk untuk men-generate persamaan kata dan menggunakan skore untuk setiap kemiripan pada setiap kalimat. Kita akan mengindentifikasi nilai KNN yang mana memiliki nilai tertinggi pada kemiripan kalimat selama training corpus.

Pertama, kita buat file notebook baru di google colab. Bisa melalui link berikut https://colab.research.google.com/#create=true

Selanjutnya kita import libraries yang akan kita gunakan dalam text classification dengan KNN

import nltk
from nltk.corpus import wordnet as wn
from nltk.corpus import genesis
nltk.download('omw-1.4')
nltk.download('genesis')
nltk.download('wordnet')
nltk.download('punkt')
nltk.download('averaged_perceptron_tagger')
genesis_ic = wn.ic(genesis, False, 0.0)

import numpy as np
import pandas as pd
from nltk.tokenize import word_tokenize
from nltk.stem.porter import PorterStemmer
from nltk.stem import SnowballStemmer
from nltk.stem.lancaster import LancasterStemmer
from nltk.corpus import stopwords
from sklearn.metrics import roc_auc_score

import warnings
warnings.filterwarnings("ignore") # Untuk Mengabaikan Warnings

Kemudian kita implementasikan algoritma KNN pada clas KNN_NLC_Classifier(). Disini kita mendefinisikan nilai k = 1. Disini kita membuat function fit untuk melakukan training data. function predict untuk melakukan prediksi data dengan menghitung nilai tertinggi pada kemiripan kalimat. function convert tag untuk convert tag yang diberikan oleh nltk.pos_tag. function doc_to_synsets untuk melakukan tokenize pada setiap kata, lalu mencari synsets pada setiap kata. function similiarity_score untuk menghitung nilai pada 2 kalimat dengan menggunakan synset mereka. function document_similarity untuk mencari kemiripan antara text 1 dan text 2.

class KNN_NLC_Classifer():
    def __init__(self, k=1, distance_type = 'path'):
        self.k = k
        self.distance_type = distance_type

    # This function is used for training
    def fit(self, x_train, y_train):
        self.x_train = x_train
        self.y_train = y_train

    # This function runs the K(1) nearest neighbour algorithm and
    # returns the label with closest match. 
    def predict(self, x_test):
        self.x_test = x_test
        y_predict = []

        for i in range(len(x_test)):
            max_sim = 0
            max_index = 0
            
            for j in range(self.x_train.shape[0]):
                temp = self.document_similarity(x_test[i], self.x_train[j])
                if temp > max_sim:
                    max_sim = temp
                    max_index = j
            y_predict.append(self.y_train[max_index])

        return y_predict

    def convert_tag(self, tag):
        """Convert the tag given by nltk.pos_tag to the tag used by wordnet.synsets"""
        tag_dict = {'N': 'n', 'J': 'a', 'R': 'r', 'V': 'v'}
        try:
            return tag_dict[tag[0]]
        except KeyError:
            return None


    def doc_to_synsets(self, doc):
        """
            Returns a list of synsets in document.
            Tokenizes and tags the words in the document doc.
            Then finds the first synset for each word/tag combination.
        If a synset is not found for that combination it is skipped.

        Args:
            doc: string to be converted

        Returns:
            list of synsets
        """
        tokens = word_tokenize(doc+' ')
        
        l = []
        tags = nltk.pos_tag([tokens[0] + ' ']) if len(tokens) == 1 else nltk.pos_tag(tokens)
        
        for token, tag in zip(tokens, tags):
            syntag = self.convert_tag(tag[1])
            syns = wn.synsets(token, syntag)
            if (len(syns) > 0):
                l.append(syns[0])
        return l  
    
    def similarity_score(self, s1, s2, distance_type = 'path'):
        """
        Calculate the normalized similarity score of s1 onto s2
        For each synset in s1, finds the synset in s2 with the largest similarity value.
        Sum of all of the largest similarity values and normalize this value by dividing it by the
        number of largest similarity values found.

        Args:
            s1, s2: list of synsets from doc_to_synsets

        Returns:
            normalized similarity score of s1 onto s2
        """
        s1_largest_scores = []

        for i, s1_synset in enumerate(s1, 0):
            max_score = 0
            for s2_synset in s2:
                if distance_type == 'path':
                    score = s1_synset.path_similarity(s2_synset, simulate_root = False)

                    if score != None:
                      if score > max_score:
                          max_score = score
                else:
                    score = s1_synset.wup_similarity(s2_synset) 

                    if score != None:
                      if score > max_score:
                          max_score = score
            
            if max_score != 0:
                s1_largest_scores.append(max_score)
        
        mean_score = np.mean(s1_largest_scores)
                
        return mean_score  

    def document_similarity(self,doc1, doc2):
        """Finds the symmetrical similarity between doc1 and doc2"""

        synsets1 = self.doc_to_synsets(doc1)
        synsets2 = self.doc_to_synsets(doc2)
          
        return (self.similarity_score(synsets1, synsets2) + self.similarity_score(synsets2, synsets1)) / 2

Setelah kita membuat model KNN untuk melakukan text classification, sekarang kita bisa langsung mencoba model tersebut dengan menjalankan code berikut.

doc1 = 'I like rains'
doc2 = 'I like showers'

x = KNN_NLC_Classifer()

print("Test Similarity Score: ", x.document_similarity(doc1, doc2))

Pada ke dua dokumen tersebut terdapat nilai kemiripannya yaitu 0.69. Sekarang kita akan mencoba menggunakan dataset cuaca. Disini kita akan mengambil dataset menggunakan pandas, lalu merename colom pada dataset tersebut. Setelah itu, kita lakukan encoding pada label answer. Terakhir kita tampilkan 5 data teratas pada dataset.

# 1. Importing the dataset
#we'll use the demo dataset available at Watson NLC Classifier Demo.
FILENAME = "https://raw.githubusercontent.com/watson-developer-cloud/natural-language-classifier-nodejs/master/training/weather_data_train.csv"          

dataset = pd.read_csv(FILENAME, header = None)

dataset.rename(columns = {0:'text', 1:'answer'}, inplace = True)

dataset['output'] = np.where(dataset['answer'] == 'temperature', 1,0)
Num_Words = dataset.shape[0]

print(dataset.head())
print("\nSize of input file is ", dataset.shape)

Disini kita lakukan tahapan text preprocessing yaitu stopword removal dan lemmatization. Setelah itu, kita definisikan nilai X dan y. Untuk penjelasan mengenai text preprocessing kalian bisa baca artikel berikut.

import re
nltk.download('stopwords')
s = stopwords.words('english')

#add additional stop words
s.extend(['today', 'tomorrow', 'outside', 'out', 'there'])
ps = nltk.wordnet.WordNetLemmatizer()

for i in range(dataset.shape[0]):
    review = re.sub('[^a-zA-Z]', ' ', dataset.loc[i,'text'])
    review = review.lower()
    review = review.split()
    review = [ps.lemmatize(word) for word in review if not word in s]
    review = ' '.join(review)
    dataset.loc[i, 'text'] = review

X_train = dataset['text']
y_train = dataset['output']

print("Below is the sample of training text after removing the stop words")
print(dataset['text'][:10])

Setelah tahapan text preprocessing, kita akan lanjut melatih text tersebut ke dalam model KNN yang telah kita buat. Kemudian jika proses latih data selesai, kita akan melakukan prediksi data menggunakan text testing yang kita dibuat di baris 5. Kita lakukan tahapan text processing pada text testing dan terakhir kita lakukan tahapan prediksi.

# 4. Train the Classifier
classifier = KNN_NLC_Classifer(k=1, distance_type='path')
classifier.fit(X_train, y_train)

final_test_list = ['will it rain', 'Is it hot outside?' , 'What is the expected high for today?' , 
                   'Will it be foggy tomorrow?', 'Should I prepare for sleet?',
                     'Will there be a storm today?', 'do we need to take umbrella today',
                    'will it be wet tomorrow', 'is it humid tomorrow', 'what is the precipitation today',
                    'is it freezing outside', 'is it cool outside', "are there strong winds outside",]
                 
test_corpus = []

for i in range(len(final_test_list)):
    review = re.sub('[^a-zA-Z]', ' ', final_test_list[i])
    review = review.lower()
    review = review.split()

    review = [ps.lemmatize(word) for word in review if not word in s]
    review = ' '.join(review)
    test_corpus.append(review)

y_pred_final = classifier.predict(test_corpus)

output_df = pd.DataFrame(data = {'text': final_test_list, 'code': y_pred_final})
output_df['answer'] = np.where(output_df['code']==1, 'Temperature','Conditions')

print(output_df)

Selamat kita telah berhasil membuat text classification dengan KNN atau K Nearest Neighbors. Jika masih terdapat kesalahan atau error kalian bisa tulis pada kolom komentar dibawah ini.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top