Dicoding: Machine Learning Untuk Pemula¶
Learning Path : Data Scientist
Project name : Rock, Paper and Scrissor
= Name : Maulana Kavaldo / LinkedIn
= Email : alkav.maulana@gmail.com
= ID Dicoding : maulanakavaldo
= Github
Import Library¶
In [ ]:
import os
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.losses import SparseCategoricalCrossentropy
from tensorflow.keras.callbacks import ModelCheckpoint
from tensorflow.keras.losses import categorical_crossentropy
from tensorflow.keras.callbacks import EarlyStopping
import time
In [ ]:
print('Versi tensorflow: ', tf.__version__)
Versi tensorflow: 2.13.0
Import Dataset¶
In [ ]:
!wget --no-check-certificate \
https://github.com/dicodingacademy/assets/releases/download/release/rockpaperscissors.zip \
-O /tmp/rockpaperscissors.zip
--2023-09-29 00:24:56-- https://github.com/dicodingacademy/assets/releases/download/release/rockpaperscissors.zip Resolving github.com (github.com)... 140.82.114.3 Connecting to github.com (github.com)|140.82.114.3|:443... connected. HTTP request sent, awaiting response... 302 Found Location: https://objects.githubusercontent.com/github-production-release-asset-2e65be/391417272/7eb836f2-695b-4a46-9c78-b65867166957?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20230929%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230929T002456Z&X-Amz-Expires=300&X-Amz-Signature=93b25c0a445562c85fab033a11d78bff9b86b392301a4f983a38c9ae5341d789&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=391417272&response-content-disposition=attachment%3B%20filename%3Drockpaperscissors.zip&response-content-type=application%2Foctet-stream [following] --2023-09-29 00:24:56-- https://objects.githubusercontent.com/github-production-release-asset-2e65be/391417272/7eb836f2-695b-4a46-9c78-b65867166957?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20230929%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230929T002456Z&X-Amz-Expires=300&X-Amz-Signature=93b25c0a445562c85fab033a11d78bff9b86b392301a4f983a38c9ae5341d789&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=391417272&response-content-disposition=attachment%3B%20filename%3Drockpaperscissors.zip&response-content-type=application%2Foctet-stream Resolving objects.githubusercontent.com (objects.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ... Connecting to objects.githubusercontent.com (objects.githubusercontent.com)|185.199.108.133|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 322873683 (308M) [application/octet-stream] Saving to: ‘/tmp/rockpaperscissors.zip’ /tmp/rockpapersciss 100%[===================>] 307.92M 135MB/s in 2.3s 2023-09-29 00:24:59 (135 MB/s) - ‘/tmp/rockpaperscissors.zip’ saved [322873683/322873683]
In [ ]:
# melakukan ekstraksi pada file zip
import zipfile,os
local_zip = '/tmp/rockpaperscissors.zip'
zip_ref = zipfile.ZipFile(local_zip, 'r')
zip_ref.extractall('/tmp')
zip_ref.close()
base_dir = '/tmp/rockpaperscissors/rps-cv-images'
ImageDataGenerator untuk Augmentasi Gambar¶
In [ ]:
# Inisialisasi ImageDataGenerator untuk augmentasi gambar
datagen = ImageDataGenerator(
rescale=1.0/255.0,
rotation_range=20,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
validation_split=0.4 # Pembagian dataset menjadi training dan validation set(40%)
)
# Memuat dataset menggunakan ImageDataGenerator
train_generator = datagen.flow_from_directory(
base_dir,
target_size=(150, 150),
batch_size=32,
class_mode='categorical',
subset='training'
)
validation_generator = datagen.flow_from_directory(
base_dir,
target_size=(150, 150),
batch_size=32,
class_mode='categorical',
subset='validation'
)
Found 1314 images belonging to 3 classes. Found 874 images belonging to 3 classes.
Model Sequential¶
In [ ]:
# Membangun model Sequential
model = Sequential([
Conv2D(32, (3, 3), activation='relu', input_shape=(150, 150, 3)),
MaxPooling2D(2, 2),
Conv2D(64, (3, 3), activation='relu'),
MaxPooling2D(2, 2),
Conv2D(128, (3, 3), activation='relu'),
MaxPooling2D(2, 2),
Flatten(), # Meratakan (Flatten) data sebelum masuk ke lapisan tersembunyi
Dense(512, activation='relu'), # Hidden layer pertama
Dense(256, activation='relu'), # Hidden layer kedua
Dropout(0.5),
Dense(3, activation='softmax') # 3 kelas: Rock, Paper, Scissors
])
# Compile model dengan optimizer dan loss function
model.compile(optimizer=Adam(learning_rate=0.001),
loss=categorical_crossentropy,
metrics=['accuracy'])
# Menghentikan pelatihan ketika accuracy didapat 95% (min_delta=0.05)
early_stopping = EarlyStopping(monitor='accuracy', min_delta=0.05, patience=5, mode='max', verbose=1)
# Simpan waktu awal sebelum pelatihan dimulai
start_time = time.time()
# Melatih model
history = model.fit(
train_generator,
steps_per_epoch=32, #len(train_generator),
epochs=100,
validation_data=validation_generator,
validation_steps=len(validation_generator),
callbacks=[early_stopping] # callback menghentikan pelatihan ketika sudah tercapai
)
Epoch 1/100 32/32 [==============================] - 98s 3s/step - loss: 1.0924 - accuracy: 0.4024 - val_loss: 1.0509 - val_accuracy: 0.4519 Epoch 2/100 32/32 [==============================] - 107s 3s/step - loss: 1.0345 - accuracy: 0.4648 - val_loss: 0.9812 - val_accuracy: 0.5675 Epoch 3/100 32/32 [==============================] - 87s 3s/step - loss: 1.0066 - accuracy: 0.5141 - val_loss: 0.8090 - val_accuracy: 0.7460 Epoch 4/100 32/32 [==============================] - 84s 3s/step - loss: 0.7176 - accuracy: 0.6992 - val_loss: 0.5163 - val_accuracy: 0.8249 Epoch 5/100 32/32 [==============================] - 86s 3s/step - loss: 0.5108 - accuracy: 0.8018 - val_loss: 0.5388 - val_accuracy: 0.7826 Epoch 6/100 32/32 [==============================] - 109s 3s/step - loss: 0.5773 - accuracy: 0.7432 - val_loss: 0.5802 - val_accuracy: 0.7380 Epoch 7/100 32/32 [==============================] - 86s 3s/step - loss: 0.4229 - accuracy: 0.8451 - val_loss: 0.2649 - val_accuracy: 0.9119 Epoch 8/100 32/32 [==============================] - 112s 4s/step - loss: 0.2429 - accuracy: 0.9238 - val_loss: 0.1786 - val_accuracy: 0.9428 Epoch 9/100 32/32 [==============================] - 87s 3s/step - loss: 0.2234 - accuracy: 0.9245 - val_loss: 0.2058 - val_accuracy: 0.9497 Epoch 10/100 32/32 [==============================] - 85s 3s/step - loss: 0.1887 - accuracy: 0.9416 - val_loss: 0.1378 - val_accuracy: 0.9588 Epoch 11/100 32/32 [==============================] - 107s 3s/step - loss: 0.1825 - accuracy: 0.9434 - val_loss: 0.1310 - val_accuracy: 0.9622 Epoch 12/100 32/32 [==============================] - 84s 3s/step - loss: 0.1480 - accuracy: 0.9598 - val_loss: 0.1899 - val_accuracy: 0.9474 Epoch 13/100 32/32 [==============================] - 104s 3s/step - loss: 0.1970 - accuracy: 0.9336 - val_loss: 0.1878 - val_accuracy: 0.9291 Epoch 13: early stopping
In [ ]:
# Simpan model
model.save('rps_model.keras')
Waktu Pelatihan Model yang Diperlukan¶
In [ ]:
# Hitung total waktu pelatihan
end_time = time.time()
training_time_seconds = end_time - start_time
# dari detik ke menit
training_time_minutes = training_time_seconds / 60
print(f"Total waktu pelatihan: {training_time_minutes:.2f} menit")
Total waktu pelatihan: 26.43 menit
Plot Akurasi dan Loss pada Set Pelatihan dan Validasi¶
In [ ]:
import plotly.graph_objs as go
import plotly.express as px
# Plot akurasi pada set pelatihan dan validasi
trace1 = go.Scatter(x=list(range(1, len(history.history['accuracy']) + 1)),
y=history.history['accuracy'],
mode='lines',
name='Akurasi Pelatihan')
trace2 = go.Scatter(x=list(range(1, len(history.history['val_accuracy']) + 1)),
y=history.history['val_accuracy'],
mode='lines',
name='Akurasi Validasi')
layout1 = go.Layout(title='Akurasi Pelatihan dan Validasi',
xaxis=dict(title='Epoch'),
yaxis=dict(title='Akurasi'))
fig1 = go.Figure(data=[trace1, trace2], layout=layout1)
# Plot loss pada set pelatihan dan validasi
trace3 = go.Scatter(x=list(range(1, len(history.history['loss']) + 1)),
y=history.history['loss'],
mode='lines',
name='Loss Pelatihan')
trace4 = go.Scatter(x=list(range(1, len(history.history['val_loss']) + 1)),
y=history.history['val_loss'],
mode='lines',
name='Loss Validasi')
layout2 = go.Layout(title='Loss Pelatihan dan Validasi',
xaxis=dict(title='Epoch'),
yaxis=dict(title='Loss'))
fig2 = go.Figure(data=[trace3, trace4], layout=layout2)
fig1.show()
fig2.show()
Menguji Model Machine Learning¶
In [ ]:
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing import image
from google.colab import files
from IPython.display import Image, display
import numpy as np
# Load model yang telah dilatih
model = load_model('rps_model.keras')
In [ ]:
# Mengunggah gambar
uploaded_image = files.upload()
# Mengambil nama file gambar yang diunggah
image_files = list(uploaded_image.keys())
if len(image_files) == 0:
print("Tidak ada gambar yang diunggah.")
else:
# Mengambil gambar pertama (jika ada banyak gambar yang diunggah)
uploaded_image_path = image_files[0]
# Memuat dan memproses gambar yang akan diprediksi
img = image.load_img(uploaded_image_path, target_size=(150, 150))
img_array = image.img_to_array(img)
img_array = np.expand_dims(img_array, axis=0)
img_array /= 255.0 # Normalisasi
# Menampilkan gambar yang diunggah
display(Image(uploaded_image_path))
# Melakukan prediksi
prediction = model.predict(img_array)
class_idx = np.argmax(prediction)
# Menampilkan hasil prediksi
if class_idx == 0:
print("Paper")
elif class_idx == 1:
print("Rock")
else:
print("Scissors")
Saving glL1mPYeHM552bV4.png to glL1mPYeHM552bV4.png
1/1 [==============================] - 0s 116ms/step Rock
In [ ]:
# Mengunggah gambar
uploaded_image = files.upload()
# Mengambil nama file gambar yang diunggah
image_files = list(uploaded_image.keys())
if len(image_files) == 0:
print("Tidak ada gambar yang diunggah.")
else:
# Mengambil gambar pertama (jika ada banyak gambar yang diunggah)
uploaded_image_path = image_files[0]
# Memuat dan memproses gambar yang akan diprediksi
img = image.load_img(uploaded_image_path, target_size=(150, 150))
img_array = image.img_to_array(img)
img_array = np.expand_dims(img_array, axis=0)
img_array /= 255.0 # Normalisasi
# Menampilkan gambar yang diunggah
display(Image(uploaded_image_path))
# Melakukan prediksi
prediction = model.predict(img_array)
class_idx = np.argmax(prediction)
# Menampilkan hasil prediksi
if class_idx == 0:
print("Paper")
elif class_idx == 1:
print("Rock")
else:
print("Scissors")
Saving ywXiLajxMzhy7BST.png to ywXiLajxMzhy7BST (1).png
1/1 [==============================] - 0s 43ms/step Paper
In [ ]:
# Mengunggah gambar
uploaded_image = files.upload()
# Mengambil nama file gambar yang diunggah
image_files = list(uploaded_image.keys())
if len(image_files) == 0:
print("Tidak ada gambar yang diunggah.")
else:
# Mengambil gambar pertama (jika ada banyak gambar yang diunggah)
uploaded_image_path = image_files[0]
# Memuat dan memproses gambar yang akan diprediksi
img = image.load_img(uploaded_image_path, target_size=(150, 150))
img_array = image.img_to_array(img)
img_array = np.expand_dims(img_array, axis=0)
img_array /= 255.0 # Normalisasi
# Menampilkan gambar yang diunggah
display(Image(uploaded_image_path))
# Melakukan prediksi
prediction = model.predict(img_array)
class_idx = np.argmax(prediction)
# Menampilkan hasil prediksi
if class_idx == 0:
print("Paper")
elif class_idx == 1:
print("Rock")
else:
print("Scissors")
Saving fYsFOMTEQ0VIy1Ma.png to fYsFOMTEQ0VIy1Ma.png
1/1 [==============================] - 0s 43ms/step Scissors