<jupyter_start><jupyter_text>PCA on Fashion MNIST Dataset  Part 1 : Importing Libraries and Dataset

Pada langkah ini, kita import beberapa libraries yang akan digunakan beserta dataset ```fashion-mnist```.<jupyter_code>import numpy as np
import pandas as pd
import sklearn
import matplotlib.pyplot as plt
import seaborn as sns
import time

import tensorflow as tf
from tensorflow import keras
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.fashion_mnist.load_data()<jupyter_output><empty_output><jupyter_text>Agar lebih mengenal dataset ini, mari kita lihat shape dari masing-masing komponen.<jupyter_code>print('x_train shape:', x_train.shape)
print('y_train shape:', y_train.shape)
print('x_test shape:', x_test.shape)
print('y_test shape:', y_test.shape)<jupyter_output>x_train shape: (60000, 28, 28)
y_train shape: (60000,)
x_test shape: (10000, 28, 28)
y_test shape: (10000,)<jupyter_text>Detil dari dataset ini dapat dilihat pada dokumentasi https://keras.io/api/datasets/fashion_mnist/. Berdasarkan paparan di atas, data training kita adalah sebanyak 60 000 dan berisi gambar berukuran 28x28 pixel. 

Setiap pixel nilainya adalah 0 sampai 255, seperti yang dijelaskan Pak Arko di kelas minggu lalu. Oleh sebab itu, dengan kata lain, dataset kita memiliki 28*28 = 784 'feature columns'. 

Mari kita lihat beberapa contoh dari dataset ini.<jupyter_code>plt.imshow(x_train[0])
print('Label dari gambar ini adalah:', y_train[0])
plt.imshow(x_train[120])
print('Label dari gambar ini adalah:', y_train[120])<jupyter_output>Label dari gambar ini adalah: 5<jupyter_text>Seperti yang terkandung dalam namanya, dataset ini berisi gambar 'fashion images' dan memiliki label 0 sampai 9. Apabila kita membaca dokumentasi dengan baik, maka kita mengetahui bahwa label-label nomor tersebut adalah sebagai berikut.

- Label 0: T-Shirt (Kaos)
- Label 1: Trouser (Celana Panjang)
- Label 2: Pullover (Kaos Lengan Panjang)
- Label 3: Dress (Gaun)
- Label 4: Coat (Jaket, Sweater, dll)
- Label 5: Sandal
- Label 6: Shirt (Kemeja)
- Label 7: Sneaker (Sepatu)
- Label 8: Bag (Tas)
- Label 9: Ankle Boot (Sepatu Boots)<jupyter_code>dictionary = {0:'T-Shirt', 1:'Trouser', 2:'Pullover', 3:'Dress', 4:'Coat', 5:'Sandal', 6:'Shirt',
              7:'Sneaker', 8:'Bag', 9:'Boots'}
x_train_flat = x_train.reshape(60000,784)
x_test_flat = x_test.reshape(10000,784)<jupyter_output><empty_output><jupyter_text>Part 2 : Decision Tree using Non-PCA Data

Mari kita terlebih dahulu memeriksa seberapa akurat dan seberapa lama waktu yang digunakan untuk melatih algoritma decision tree pada dataset kita sebelum dilakukan PCA.

Sebelumnya, saya telah melakukan regresi logistik, namun tidak kunjung konvergen.<jupyter_code>from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

def dectree(x_train, y_train, x_test, y_test, return_pred = False):
  dt = DecisionTreeClassifier()
  start = time.time()
  dt.fit(x_train, y_train)
  end = time.time()

  duration = end-start
  accuracy = accuracy_score(y_test, dt.predict(x_test))

  if return_pred == False:
    return duration, accuracy
  else:
    return duration, accuracy, dt.predict(x_test)
duration_raw, accuracy_raw = dectree(x_train_flat, y_train,
                                    x_test_flat, y_test)
print('Time elapsed:', duration_raw, 'seconds.')
print('Model accuracy:', accuracy_raw, 'percent.')<jupyter_output>Time elapsed: 60.015379428863525 seconds.
Model accuracy: 0.7901 percent.<jupyter_text>Part 2 : PCA with 95% Explained Variance

Setiap model machine learning berupaya untuk menjelaskan 'variance' dari dataset. Variance dalam hal ini diartikan sebagai seberapa 'bervariasi'/'berubah'nya dataset. Secara intuisi, 'variance' ini adalah 'informasi' dari dataset tersebut.

PCA mengupayakan agar kita mereduksi dimensi dari dataset, namun masih mempertahankan 'variance' dari dataset tersebut. Kita ingin mereduksi dataset kita namun masih mempertahankan sebanyak mungkin 'informasi' semula.

Berapa bagian (biasanya dalam persen) dari 'informasi' yang ingin dipertahankan disebut 'explained variance'.<jupyter_code>from sklearn.decomposition import PCA

pca_95 = PCA(0.95)
start_time = time.time()
pca_95.fit(x_train_flat)
x_train_pca_95 = pca_95.transform(x_train_flat)
x_test_pca_95 = pca_95.transform(x_test_flat)
finish_time = time.time()
print('PCA Fit and Transform finished in', finish_time - start_time, 'seconds.')
print('Hanya tersisa:', pca_95.n_components_, 'feature columns setelah dlakukan PCA.')
print('PCA kali ini berhasil mereduksi dataset sebanyak', (1-(pca_95.n_components_/784))*100, 'persen')
duration_pca, accuracy_pca = dectree(x_train_pca_95, y_train,
                                    x_test_pca_95, y_test)
print('Time elapsed:', duration_pca, 'seconds.')
print('Model accuracy:', accuracy_pca, 'percent.')<jupyter_output>Time elapsed: 48.150229692459106 seconds.
Model accuracy: 0.7592 percent.<jupyter_text>Part 3 : PCA with 90% Explained Variance + Scaling<jupyter_code>from sklearn.preprocessing import StandardScaler

ss = StandardScaler().fit(x_train_flat)
x_train_scale = ss.transform(x_train_flat)
x_test_scale = ss.transform(x_test_flat)
pca_90s = PCA(0.90)
start_time = time.time()
pca_90s.fit(x_train_scale)
x_train_pca_90s = pca_90s.transform(x_train_scale)
x_test_pca_90s = pca_90s.transform(x_test_scale)
finish_time = time.time()
print('PCA Fit and Transform finished in', finish_time - start_time, 'seconds.')
print('Hanya tersisa:', pca_90s.n_components_, 'feature columns setelah dlakukan PCA.')
print('PCA kali ini berhasil mereduksi dataset sebanyak', (1-(pca_90s.n_components_/784))*100, 'persen')
duration_pcas, accuracy_pcas, pca_90s_prediction = dectree(x_train_pca_90s, y_train,
                                    x_test_pca_90s, y_test, True)
print('Time elapsed:', duration_pcas, 'seconds.')
print('Model accuracy:', accuracy_pcas, 'percent.')<jupyter_output>Time elapsed: 32.58561372756958 seconds.
Model accuracy: 0.7635 percent.<jupyter_text>Part 4 : Conclusion

Berdasarkan ketiga percobaan di atas, kita mendapatkan hasil sebagai berikut.

| Dec. Tree Preprocessing | Duration for PCA | Duration to Train Model | Total Duration | Accuracy | Data Size Reduced |
| --- | --- | --- | --- | --- | --- |
| No PCA | 0 seconds | 64 seconds | 64 seconds | 78% | 0% |
| PCA 0.95 Without Scaling | 11.69 seconds | 48.4 seconds | 60 seconds | 75% | 76.15% |
| PCA 0.90 With Scaling | 11.19 seconds | 33.55 seconds | 45 seconds | 76% | 82.53% |

 Kesimpulan yang didapatkan:
- PCA + Scaling, meski 'hanya' 90% explained variance, berhasil mengurangi kolom sebanyak 82.53% (dari 784 ke 137), dan mengurangi waktu total training dari 64 detik ke 45 detik. 
- Akurasi dari Decision Tree Model yang dilakukan PCA + Scaling terlebih dahulu hanya berkurang sedikit dari model tanpa PCA.
- Oleh sebab itu, dapat didemonstrasikan kegunaan melakukan PCA dan Scaling dalam memproses data.  Checking the Wrongly Classified Images

Sebagai tahap akhir, mari kita lihat beberapa gambar yang salah diklasifikasikan oleh metode PCA 90% + Scaling.<jupyter_code>comparison = pd.DataFrame((pca_90s_prediction, y_test)).transpose()
comparison.columns = ['Prediction Label', 'Test Label']
Diff = list()
for i in range(len(comparison['Prediction Label'])):
  if comparison['Prediction Label'][i] == comparison['Test Label'][i]:
    Diff.append(0)
  else:
    Diff.append(1)

comparison['Diff'] = Diff
comparison[comparison['Diff'] == 1].head(5)<jupyter_output><empty_output><jupyter_text>Berarti, gambar pada index 12, 21, 23, 25, dan 28 adalah contoh gambar-gambar yang salah diklasifikasikan.<jupyter_code>def explain(index):
  print('-------------------')
  print('Gambar untuk index:', index)
  plt.imshow(x_test[index])
  plt.show()
  print('Decision Tree + PCA90 memprediksi bahwa ini adalah gambar', dictionary[comparison['Prediction Label'][index]])
  print('Seharusnya, ini adalah gambar', dictionary[y_test[index]])
  print('-------------------')
wrong_index = [12,21,23,25,28]
for i in wrong_index:
  explain(i)<jupyter_output>-------------------
Gambar untuk index: 12
{'fraction_non_alphanumeric': 0.10937117690237338, 'fraction_numerical': 0.03963787619280646, 'mean_word_length': 4.91534008683068, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 31, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '539771', 'license': 'Apache-2.0', 'n_tokens_mistral': 3289, 'n_tokens_neox': 2960, 'n_words': 795, 'path': 'PCA_Fashion_Mnist_Grady.ipynb', 'repo_name': 'Radvian/pca-fashion-mnist', 'size': '8174'}