Disusun oleh:

  1. Didik Nurdiyanto (231012000002)
  2. Tia Millenia Alvionita (231012000005)
  3. Defa Diyana (231012000108)


    Apa itu VGG16?

    VGG16 adalah salah satu arsitektur Convolutional Neural Network (CNN) yang terkenal, dikembangkan oleh Visual Geometry Group (VGG) di Universitas Oxford. Model ini memiliki 16 lapisan yang dapat dilatih (trainable layers), termasuk lapisan konvolusi dan lapisan fully connected. VGG16 dikenal karena kemampuannya menghasilkan hasil klasifikasi gambar yang akurat dalam berbagai aplikasi.




    Dalam dunia pertanian modern, teknologi terus berkembang untuk meningkatkan efisiensi dan akurasi dalam berbagai aspek, termasuk identifikasi varietas tanaman. Salah satu teknologi terkini yang dapat diimplementasikan adalah deep learning, khususnya dengan model VGG16. Artikel ini akan membahas bagaimana VGG16 dapat digunakan untuk klasifikasi varietas beras, memberikan wawasan tentang inovasi teknologi yang semakin mendukung dunia pertanian.

    Dalam konteks klasifikasi beras, VGG16 digunakan untuk mengenali karakteristik visual dari tiga varietas beras, misalnya:
    1. Varietas Beras Basmathi
    2. Varietas Beras IR 64
    3. Varietas Beras Ketan

    Mengapa VGG16 Cocok untuk Klasifikasi Varietas Beras?

    1. Kemampuan Ekstraksi Fitur yang Kuat
      VGG16 mampu menangkap detail halus dalam gambar, seperti bentuk dan tekstur butir beras.
    2. Generalisasi yang Baik
      Dengan dataset yang tepat, model ini dapat mengenali berbagai variasi dalam gambar meskipun terdapat noise atau perbedaan pencahayaan.
    3. Penerapan yang Mudah
      VGG16 tersedia di pustaka deep learning seperti TensorFlow dan PyTorch, sehingga implementasinya menjadi lebih sederhana.

    Langkah-Langkah Implementasi

    Penelitian pada repositori GitHub https://github.com/Vidi005/Klasifikasi-3-Varietas-Beras menerapkan model VGG16 untuk mengklasifikasikan tiga varietas beras. Proses dimulai dengan persiapan dataset gambar beras, yang kemudian dilatih menggunakan jaringan saraf convolutional (CNN) VGG16. Model ini dipilih karena keunggulannya dalam mengenali fitur visual pada gambar. Teknik pelatihan melibatkan augmentasi gambar untuk meningkatkan keberagaman data, diikuti dengan fine-tuning arsitektur VGG16 agar lebih efisien dalam klasifikasi varietas beras. Hasilnya, model berhasil mengenali perbedaan varietas berdasarkan ciri-ciri visual yang signifikan.

    Mengambil Dataset dari Drive yang telah di download dari Github
            from google.colab import drive
            drive.mount('/content/drive')
            
      Menghubungkan Google Drive ke lingkungan Google Colab. Saat perintah ini dijalankan, Google Colab akan meminta autentikasi pengguna melalui tautan ke akun Google. Setelah autentikasi berhasil, seluruh isi Google Drive pengguna akan dimount ke direktori /content/drive di Colab. Hal ini memungkinkan pengguna untuk mengakses, membaca, dan menulis file secara langsung di Google Drive, seolah-olah file tersebut berada di sistem file lokal. Semua file berada di dalam subdirektori /content/drive/My Drive/, sehingga pengguna dapat mengarahkan script atau operasi file mereka ke folder yang relevan di dalam Google Drive. 


      Perintah di atas adalah perintah bash yang dijalankan di lingkungan seperti Google Colab untuk menampilkan isi direktori menggunakan ls. Perintah ini memeriksa empat direktori berbeda di Google Drive yang terhubung ke Colab: direktori utama image, subdirektori train, subdirektori train/IR64, dan subdirektori test/IR64. Setiap perintah menggunakan escape character \ untuk menangani spasi dalam nama direktori seperti My Drive, memastikan akses ke folder dengan benar.


      Memasukan Fungsi Library


            from __future__ import absolute_import, division, print_function, unicode_literals
      
            try:
              # The %tensorflow_version magic only works in colab.
              %tensorflow_version 2.x
            except Exception:
              pass
      
            import numpy as np
            import math, os, sys
            import itertools
      
            import matplotlib.pyplot as plt
            plt.style.use('default')
            from scipy import ndimage
      
            from skimage import measure, morphology
            from skimage.io import imsave, imread
            from skimage.filters import threshold_otsu
            from skimage.transform import resize
      
            import tensorflow as tf
            from sklearn import svm, datasets
            from sklearn.metrics import confusion_matrix
            import pandas as pd
            

      Kode tersebut memvisualisasikan sebuah gambar dari dataset pelatihan menggunakan Matplotlib. Pertama, fungsi imread dari matplotlib.image digunakan untuk membaca file gambar yang berada di direktori /content/drive/My Drive/data/image/train/IR64/I60.jpg. Kemudian, plt.figure(figsize=(4,4)) membuat area kanvas untuk menampilkan gambar dengan ukuran 4x4 inci. Akhirnya, fungsi plt.imshow(image) menampilkan gambar yang telah dibaca. Kode ini membantu memastikan bahwa gambar dari dataset dapat diakses dan divisualisasikan dengan benar, yang berguna untuk inspeksi data sebelum digunakan dalam model machine learning.

      Memuat semua gambar ke memori


            #Memuat dataset pelatihan
            IMAGE_SIZE = 224
            BATCH_SIZE = 128
            base_dir = os.path.join('/content/drive/My Drive/data/image/train')
      
            datagen = tf.keras.preprocessing.image.ImageDataGenerator(
                rescale=1./255,
                validation_split=0.2)
      
            train_generator = datagen.flow_from_directory(
                base_dir,
                target_size=(IMAGE_SIZE, IMAGE_SIZE),
                batch_size=BATCH_SIZE,
                subset='training')
      
            val_generator = datagen.flow_from_directory(
                base_dir,
                target_size=(IMAGE_SIZE, IMAGE_SIZE),
                batch_size=BATCH_SIZE,
                subset='validation')
      
            #Memuat dataset pengujian
            X_test = []
            y_test = []
            labels = ['Basmathi', 'IR64', 'Ketan']
      
            for i,label in enumerate(labels):
                folder = os.path.join("/content/drive/My Drive/data/image/test",label)
                files = sorted(os.listdir(folder))
                files = [x for x in files if x.endswith(".jpg")]
                for k,file in enumerate(files):
                    image_path = os.path.join(folder, file)
      
                    image = imread(image_path)/255.
                    image = resize(image,(224,224))
                    X_test.append(image)
                    category = os.path.split(folder)[-1]
                    y_test.append(i)
      
            X_test = np.array(X_test)
            y_test = np.array(y_test)
      
            #Menampilkan bentuk dari masing-masing dataset
            for image_batch, label_batch in train_generator:
              break
            print("Bentuk array dari dataset train (pelatihan) adalah:", image_batch.shape,label_batch.shape)
            for image_batch, label_batch in val_generator:
              break
            print("Bentuk array dari dataset validation (validasi) adalah:", image_batch.shape,label_batch.shape)
            print("Bentuk array dari dataset test (pengujian) adalah:", X_test.shape,y_test.shape)
            


      Menyimpan Label


      Kode tersebut berguna untuk referensi label saat melakukan inferensi menggunakan model, terutama jika prediksi model menghasilkan indeks numerik (misalnya 0, 1, atau 2), sehingga Anda bisa mengetahui nama label yang sesuai.


      Menggunakan model VGG16

            IMG_SHAPE = (224, 224, 3)
            # Membuat model dasar (base model) dari pre-trained model VGG-16Net
            base_model = tf.keras.applications.VGG16(input_shape=IMG_SHAPE, include_top=False, weights='imagenet')
            

      Feature Extraction

      Menggunakan model pre-trained untuk ekstraksi fitur (feature extraction) adalah pendekatan umum saat bekerja dengan dataset kecil. Teknik ini memanfaatkan fitur yang telah dipelajari oleh model yang dilatih pada dataset besar dengan domain serupa. Caranya adalah dengan memanfaatkan model pre-trained sebagai basis, lalu menambahkan classifier baru di atasnya. Model pre-trained tersebut dibekukan sehingga bobotnya tidak diubah, sementara hanya bobot pada classifier baru yang diperbarui selama pelatihan. Dalam proses ini, lapisan konvolusional bertugas mengekstraksi semua fitur penting dari setiap gambar, dan classifier dilatih untuk menentukan kelas gambar berdasarkan fitur-fitur yang telah diekstraksi.



      Pelatihan

            import keras
            from keras import backend as K
            from keras.models import Sequential
            from keras import layers
            from keras.utils.np_utils import to_categorical
      
            from sklearn.model_selection import train_test_split
            
            y_test2 = to_categorical(y_test)
      	  X_test3, y_test3 = (X_test, y_test2)
      
            model = tf.keras.Sequential([
                base_model,    
                tf.keras.layers.Conv2D(32, 3, activation='relu'),
                #tf.keras.layers.Dropout(0.2),
                tf.keras.layers.GlobalAveragePooling2D(),
                tf.keras.layers.Dense(3, activation='softmax')
            ])
      
            model.compile("adam",loss="categorical_crossentropy",metrics=["acc"])
            model.summary()
            
            #from keras.callbacks import EarlyStopping, ModelCheckpoint
      
            #Menyimpan file model bobot yang terbaik selama pelatihan (dalam format keras ".h5")
            #ckpt = ModelCheckpoint("Klasifikasi Beras Tumpukan.h5", monitor='val_loss', verbose=1, save_best_only=True, save_weights_only=False, mode='auto', period=1)
            history = model.fit_generator(train_generator, epochs=10, validation_data=val_generator)
            #history = model.fit(x = X_train3, y = y_train3, batch_size=120, epochs= 100,validation_data=(X_valid3,y_valid3),callbacks = [ckpt])
      
            


      Menggambarkan Hasil Pelatihan


      	plt.plot(history.history["acc"],label="Akurasi Pelatihan")
      	plt.plot(history.history["val_acc"],label="Validasi Akurasi")
      	plt.legend()
      	plt.show()
      
      	plt.plot(history.history["loss"],label="Kesalahan Pelatihan")
      	plt.plot(history.history["val_loss"],label="Validasi Kesalahan")
      	plt.legend()
      	plt.show()
      


      Evaluasi

      	#Memeriksa matriks model
      	print(model.metrics_names)
      	#Evaluasi data test
      	print(model.evaluate(x= X_test3, y = y_test3)) 
      

      Confusion Matrix

          from sklearn.metrics import confusion_matrix
          from sklearn.utils.multiclass import unique_labels
      
          def plot_confusion_matrix(y_true, y_pred, classes,
                                normalize=False,
                                title=None,
                                cmap=plt.cm.Blues):
          """
          This function prints and plots the confusion matrix.
          Normalization can be applied by setting `normalize=True`.
          """
          if not title:
              if normalize:
                  title = 'Normalized confusion matrix'
              else:
                  title = 'Confusion matrix, without normalization'
      
          # Compute confusion matrix
          cm = confusion_matrix(y_true, y_pred)
          # Only use the labels that appear in the data
          #classes = classes[unique_labels(y_true, y_pred)]
          if normalize:
              cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
              print("Normalized confusion matrix")
          else:
              print('Confusion matrix, without normalization')
      
          print(cm)
      
          fig, ax = plt.subplots(figsize=(5,5))
          im = ax.imshow(cm, interpolation='nearest', cmap=cmap)
          #ax.figure.colorbar(im, ax=ax)
          # We want to show all ticks...
          ax.set(xticks=np.arange(cm.shape[1]),
                 yticks=np.arange(cm.shape[0]),
                 # ... and label them with the respective list entries
                 xticklabels=classes, yticklabels=classes,
                 title=title,
                 ylabel='Label Benar',
                 xlabel='Label Prediksi')
      
          # Rotate the tick labels and set their alignment.
          plt.setp(ax.get_xticklabels(), rotation=45, ha="right",
                   rotation_mode="anchor")
      
          # Loop over data dimensions and create text annotations.
          fmt = '.2f' if normalize else 'd'
          thresh = cm.max() / 2.
          for i in range(cm.shape[0]):
              for j in range(cm.shape[1]):
                  ax.text(j, i, format(cm[i, j], fmt),
                          ha="center", va="center",
                          color="white" if cm[i, j] > thresh else "black")
          fig.tight_layout()
          return ax
      
          np.set_printoptions(precision=2)
          plot_confusion_matrix(y_true, y_pred, classes=labels, normalize=True,title='Normalized confusion matrix')
      

      Menyimpan dan Konversi ke ".tflite" 

      Menyimpan model menggunakan tf.saved_model.save dan kemudian mengonversi model tersimpan ke format yang kompatibel tf lite.

      	saved_model_dir = 'save/model'
      	tf.saved_model.save(model, saved_model_dir)
      
      	converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
      	tflite_model = converter.convert()
      
      	with open('Klasifikasi_3_Varietas_Beras_VGG16Net.tflite', 'wb') as f:
      	  f.write(tflite_model)