<jupyter_start><jupyter_text>Website Classification  Import Library & Load File<jupyter_code>import pandas as pd
import numpy as np

import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

import warnings
warnings.filterwarnings("ignore")
from google.colab import drive
drive.mount('/content/drive/', force_remount = True)
dataset = '/content/drive/My Drive/website_classification.csv'
data = pd.read_csv(dataset)
data.head(5)<jupyter_output><empty_output><jupyter_text>Explore Dataset<jupyter_code>#Drop kolom Unnamed: 0 dan website url karena tidak dibutuhkan dalam model
df= data.drop(['Unnamed: 0', 'website_url'], axis= 1)
df
#Cek apakah terdapat missing record
df.isnull().sum()
#Menghitung jumlah masing-masing nilai unik dari kolom Category
df.Category.value_counts()
#Mengetahui informasi dalam dataframe
df.info()
#Melihat susunan/jumlah Rows dan Columns pada dataframe
df.shape
#Mengetahui jumlah nilai unik dari kolom 'cleaned_website_text'
df.cleaned_website_text.nunique()<jupyter_output><empty_output><jupyter_text>CleaningDari jumlah kolom dengan nilai unik kolom terdapat perbedaan jumlah. Ini menandakan bahwa terdapat duplikasi data pada kolom 'cleaned_website_text'. Data duplikat akan dihapus.<jupyter_code>#Menghapus data duplikat pada kolom 'cleaned_website_text'
clean_df = df.drop_duplicates(subset='cleaned_website_text').reset_index(drop=True)
clean_df.shape
clean_df<jupyter_output><empty_output><jupyter_text>Data Preparation<jupyter_code>import nltk
nltk.download(['stopwords', 'punkt', 'averaged_perceptron_tagger',
               'universal_tagset'], quiet=True)
from nltk.tokenize import word_tokenize
#Mengambil kata dengan tipe 'NOUN' menggunakan post_tag, tokenize, universal_tagset
filtered_words = []
for i in range(clean_df.shape[0]):
  tagged = nltk.pos_tag(word_tokenize(clean_df.cleaned_website_text[i]),
                        tagset='universal')
  filtered_words.append(' '.join([word_tag[0] for word_tag in tagged if word_tag[1]=='NOUN']))
#Menambahkan 'filtered_words' ke dalam clean_df dataframe
clean_df['filtered_words'] = filtered_words
clean_df.head()
#Menghitung jumlah kata unik dalam seluruh dokumen
from collections import Counter

array_text = ' '.join(clean_df['filtered_words'].values)
array_text = array_text.split()

word_count = Counter(array_text)
len(word_count)<jupyter_output><empty_output><jupyter_text>Split Train Test<jupyter_code>from sklearn import preprocessing
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, accuracy_score, precision_score 
from sklearn.metrics import mean_absolute_error as mae, recall_score, f1_score, log_loss
from sklearn.feature_extraction.text import TfidfVectorizer
#TFIDF Vectorizer, mengukur bobot dengan mengambil 1500 dari 43574 variasi kata sebagai features
tfidf = TfidfVectorizer(sublinear_tf=True, min_df=5,
                        stop_words = 'english', max_features = 1500)
feat = tfidf.fit_transform(clean_df.filtered_words)
#Mendefinisikan features X dan mengkonversi hasil vektorisasi TFIDF ke dalam dataframe
X = pd.DataFrame(feat.toarray(), columns=tfidf.get_feature_names())
X
#Mendefinisikan label y dan mengkonversi kolom 'Category' berbentuk string agar menjadi integer
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
y = le.fit_transform(clean_df.Category)
y
#Train test split
X_train, X_test, y_train, y_test = train_test_split(X,y,train_size=0.7,random_state=0)<jupyter_output><empty_output><jupyter_text>Balancing Data<jupyter_code>#Melihat jumlah tiap label dengan menggunakan visualisasi
labels = list(clean_df['Category'].value_counts().index)

def showcountplot(plotuse,text=None,showtext = False):
    if text==None:
        text = []
    plt.figure(figsize=(15,5))
    ax = sns.countplot(plotuse,facecolor=(0, 0, 0, 0),
                       linewidth=1,
                       edgecolor=sns.color_palette("husl",4),
                       order = plotuse.value_counts().index)
    #Set a title
    ax.set_title(f"Count Plot of {plotuse.name}")
    #Create text
    for index,value in enumerate(plotuse.value_counts()):
        if text == []:
            ax.set_xticklabels("")
        else:
            ax.set_xticklabels(text,rotation=90) 
    #Show our plot
    plt.show()

showcountplot(clean_df["Category"],text=labels,showtext=True)
#Melakukan balancing data dengan algoritma SMOTE + TomekLinks
from imblearn.combine import SMOTETomek

st = SMOTETomek()
X_st, y_st = st.fit_resample(X_train, y_train)
print("SMOTE + TomekLinks")
print(f"Shape dari y: {len(y_st)}, dimana jumlah : {Counter(y_st)}")<jupyter_output>SMOTE + TomekLinks
Shape dari y: 1306, dimana jumlah : Counter({14: 82, 5: 82, 4: 82, 1: 82, 8: 82, 11: 82, 10: 82, 3: 82, 6: 82, 0: 82, 15: 81, 7: 81, 9: 81, 12: 81, 2: 81, 13: 81})<jupyter_text>Training<jupyter_code>from sklearn.naive_bayes import MultinomialNB
from sklearn.ensemble import RandomForestClassifier
#Training and test model Random Forest (Balanced)
random_forest = RandomForestClassifier(random_state=0)
learnerRF = random_forest.fit(X_st, y_st)
Y_predRF = random_forest.predict(X_test)

score_rf = round(random_forest.score(X_st, y_st), 3)
accuracy_rf = round(accuracy_score(y_test,Y_predRF), 3)
precision_rf = round(precision_score(y_test, Y_predRF,average='weighted'), 3)
recall_rf = round(recall_score(y_test, Y_predRF,average='weighted'), 3)
f1_rf = round(f1_score(y_test,Y_predRF,average='weighted'), 3)
#Training and test dari model Multinomial Naive Bayes (Balanced)
nb = MultinomialNB()
learnerNB = nb.fit(X_st, y_st)
Y_pred = nb.predict(X_test) 

score_nb = round(nb.score(X_st, y_st), 3)
accuracy_nb = round(accuracy_score(y_test,Y_pred), 3)
precision_nb = round(precision_score(y_test, Y_pred,average='weighted'), 3)
recall_nb = round(recall_score(y_test, Y_pred,average='weighted'), 3)
f1_nb = round(f1_score(y_test,Y_pred,average='weighted'), 3)<jupyter_output><empty_output><jupyter_text>Result<jupyter_code>#Menampilkan hasil matrix score dalam dataframe
results = pd.DataFrame({
    'model': [ 'Random Forest', 'Multinomial Naive Bayes'],
    'train_score': [ score_rf, score_nb],
    'accuracy_score': [accuracy_rf, accuracy_nb],
    'precision': [precision_rf, precision_nb],
    'recall': [recall_rf, recall_nb],
    'f1_score': [f1_rf, f1_nb],
    'mean_absolute_error': [mae(y_test, Y_predRF), mae(y_test, Y_pred)],
    })
result_df = results.sort_values(by='accuracy_score', ascending=False)
result_df = result_df.reset_index(drop=True)
result_df
#Match hasil Label Encoder dengan nilai pada Category
y1 = le.inverse_transform(y_st)
label = pd.DataFrame(data={'Label_Encoder':y_st, 'Category':y1})
label_df = label.drop_duplicates()
label_df = label_df.sort_values(by='Label_Encoder', ascending=True)
label_df = label_df.reset_index(drop=True)
label_df
#Menampilkan confusiom matrix dari hasil test Random Forest
cm_rf = confusion_matrix(y_test, Y_predRF)
plt.subplots(figsize=(12,8))
sns.heatmap(pd.DataFrame(cm_rf), annot=True, cmap="YlGnBu",
            fmt='g', yticklabels=label_df['Category'])
plt.title('Confusion Matrix for Random Forest')
plt.ylabel('Actual Label')
plt.xlabel('Predicted Label')
plt.show()
#Menampilkan confusion matrix dari hasil test Naive Bayes
cm_nb = confusion_matrix(y_test, Y_pred)
plt.subplots(figsize=(12,8))
sns.heatmap(pd.DataFrame(cm_nb), annot=True,fmt='g',
            yticklabels=label_df['Category'])
plt.title('Confusion Matrix for Naive Bayes')
plt.ylabel('Actual Label')
plt.xlabel('Predicted Label')
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1120074054482941, 'fraction_numerical': 0.015868817773075906, 'mean_word_length': 6.3072463768115945, 'pattern_counts': {'":': 0, '<': 32, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '551957', 'license': 'MIT', 'n_tokens_mistral': 2928, 'n_tokens_neox': 2730, 'n_words': 580, 'path': 'Website_Classification.ipynb', 'repo_name': 'revinarnan/website-classification', 'size': '7562'}