Đây là bài thứ 2 trong chuỗi bài viết về Image Classification với thư viện Tensorflow. Sau khi đọc và làm theo Bài 1 thử nghiệm độ chính xác thì các bạn đã giải thuật này rất là hiệu quả.
Bài này sẽ hướng dẫn cách thực thi code Python trên Windows 10 do copy code trên Notebook về không sử dụng được ngay. Khi viết bài này mình sử dụng GPU NVIDIA RTX 2060 để tăng tốc training và predict. Nếu máy bạn không có GPU hoặc laptop thì chạy rất là chậm, có thể gấp 6-20 lần thời gian.
Chuẩn bị
- Python 3.7.3: miễn là Python 3.6 trở lên là được, cài xong thì restart máy
- CUDA 10.1 trở lên
Cài đặt Tensorflow 2.3 vì máy mình cài CUDA 10.1, nếu bạn muốn cài Tensorflow 2.6 trở lên thì phải cài CUDA 11.1.
pip install tensorflow-gpu==2.3
Nếu máy không có GPU thì cài bằng lệnh
pip install tensorflow==2.3
Cài các package khác:
matplotlib==3.4.3
numpy==1.18.5
Pillow==8.3.2
Download hình ảnh về và giải nén vào folder flower_photos, trong folder này có 5 folder chứa 5 loài hoa
https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz
Source code
Save nội dung bên dưới vào file image_classification.py
[bg_collapse view=”button-orange” color=”#4a4949″ expand_text=”image_classification.py” collapse_text=”image_classification.py” ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
import sys import matplotlib.pyplot as plt import numpy as np import os import PIL import tensorflow as tf import fnmatch tf.config.experimental.list_physical_devices('GPU') from tensorflow import keras from tensorflow.keras import layers from tensorflow.keras.models import Sequential def GetFileName(filePath): fileName = os.path.basename(filePath) return fileName def GetDirName(fullpath): return GetFileName(fullpath) def FindFileInDir(dirPath, pattern, fullPath=True, searchChildDir=False): result = [] for fullpathDir, subdirs, files in os.walk(dirPath): isChildDir = len(fullpathDir) > len(dirPath) if(not searchChildDir and isChildDir): continue currentDirName = GetDirName(fullpathDir) for fileName in files: if fnmatch.fnmatch(fileName, pattern): if(fullPath): result.append(os.path.join(fullpathDir, fileName)) else: result.append(os.path.join(currentDirName, fileName)) return result data_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "flower_photos") imgPaths = FindFileInDir(data_dir, "*.jpg", False, True) image_count = len(imgPaths) # roses = FindFileInDir(os.path.join(data_dir, 'roses'), "*.jpg") # print(str(roses[0])) # img = PIL.Image.open(str(roses[0])) #img.show() batch_size = 32 img_height = 180 img_width = 180 train_ds = tf.keras.preprocessing.image_dataset_from_directory( data_dir, validation_split=0.2, subset="training", seed=123, image_size=(img_height, img_width), batch_size=batch_size) val_ds = tf.keras.preprocessing.image_dataset_from_directory( data_dir, validation_split=0.2, subset="validation", seed=123, image_size=(img_height, img_width), batch_size=batch_size) class_names = train_ds.class_names print(class_names) plt.figure(figsize=(10, 10)) for images, labels in train_ds.take(1): for i in range(9): ax = plt.subplot(3, 3, i + 1) plt.imshow(images[i].numpy().astype("uint8")) plt.title(class_names[labels[i]]) plt.axis("off") for image_batch, labels_batch in train_ds: print(image_batch.shape) print(labels_batch.shape) break AUTOTUNE = tf.data.experimental.AUTOTUNE train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE) val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE) normalization_layer = layers.experimental.preprocessing.Rescaling(1./255) normalized_ds = train_ds.map(lambda x, y: (normalization_layer(x), y)) image_batch, labels_batch = next(iter(normalized_ds)) first_image = image_batch[0] # Notice the pixels values are now in `[0,1]`. print(np.min(first_image), np.max(first_image)) num_classes = 5 model = Sequential([ layers.experimental.preprocessing.Rescaling(1./255, input_shape=(img_height, img_width, 3)), layers.Conv2D(16, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Conv2D(32, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Conv2D(64, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Flatten(), layers.Dense(128, activation='relu'), layers.Dense(num_classes) ]) model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy']) model.summary() epochs=10 history = model.fit( train_ds, validation_data=val_ds, epochs=epochs ) acc = history.history['accuracy'] val_acc = history.history['val_accuracy'] loss = history.history['loss'] val_loss = history.history['val_loss'] epochs_range = range(epochs) plt.figure(figsize=(8, 8)) plt.subplot(1, 2, 1) plt.plot(epochs_range, acc, label='Training Accuracy') plt.plot(epochs_range, val_acc, label='Validation Accuracy') plt.legend(loc='lower right') plt.title('Training and Validation Accuracy') plt.subplot(1, 2, 2) plt.plot(epochs_range, loss, label='Training Loss') plt.plot(epochs_range, val_loss, label='Validation Loss') plt.legend(loc='upper right') plt.title('Training and Validation Loss') #plt.show() data_augmentation = keras.Sequential( [ layers.experimental.preprocessing.RandomFlip("horizontal", input_shape=(img_height, img_width, 3)), layers.experimental.preprocessing.RandomRotation(0.1), layers.experimental.preprocessing.RandomZoom(0.1), ] ) plt.figure(figsize=(10, 10)) for images, _ in train_ds.take(1): for i in range(9): augmented_images = data_augmentation(images) ax = plt.subplot(3, 3, i + 1) plt.imshow(augmented_images[0].numpy().astype("uint8")) plt.axis("off") model = Sequential([ data_augmentation, layers.experimental.preprocessing.Rescaling(1./255), layers.Conv2D(16, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Conv2D(32, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Conv2D(64, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Dropout(0.2), layers.Flatten(), layers.Dense(128, activation='relu'), layers.Dense(num_classes) ]) model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy']) model.summary() epochs = 15 history = model.fit( train_ds, validation_data=val_ds, epochs=epochs ) acc = history.history['accuracy'] val_acc = history.history['val_accuracy'] loss = history.history['loss'] val_loss = history.history['val_loss'] epochs_range = range(epochs) plt.figure(figsize=(8, 8)) plt.subplot(1, 2, 1) plt.plot(epochs_range, acc, label='Training Accuracy') plt.plot(epochs_range, val_acc, label='Validation Accuracy') plt.legend(loc='lower right') plt.title('Training and Validation Accuracy') plt.subplot(1, 2, 2) plt.plot(epochs_range, loss, label='Training Loss') plt.plot(epochs_range, val_loss, label='Validation Loss') plt.legend(loc='upper right') plt.title('Training and Validation Loss') #plt.show() sunflower_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/592px-Red_sunflower.jpg" sunflower_path = tf.keras.utils.get_file('Red_sunflower', origin=sunflower_url) img = keras.preprocessing.image.load_img( sunflower_path, target_size=(img_height, img_width) ) img_array = keras.preprocessing.image.img_to_array(img) img_array = tf.expand_dims(img_array, 0) # Create a batch model.save("model_flower.h5") new_model = tf.keras.models.load_model('model_flower.h5') predictions = new_model.predict(img_array) score = tf.nn.softmax(predictions[0]) print( "This image most likely belongs to {} with a {:.2f} percent confidence." .format(class_names[np.argmax(score)], 100 * np.max(score)) ) os.remove(sunflower_path) |
Sau đó chạy file bằng lệnh dưới là ra kết quả
python image_classification.py
Sử dụng hình ảnh bên dưới để dự đoán
Kết quả dự đoán là dandelion (hoa Bồ Công Anh) với 80% confident
Giải thích source code
- Bước 1: import các thư viện cần thiết
- Bước 2: load ảnh và chia thành 2 bộ: 80% ảnh cho training set và 20% ảnh cho bộ valid set
- Bước 3: setup các tham số dùng để training
- Bước 4: khởi tạo model Neural Network với nhiều layers
- Bước 5: compile model
- Bước 6: optimize model bằng Dropout để giảm thời gian xử lý
- Bước 7: training model
- Bước 8: predict hình ảnh
8 bước trên có các bước trước khi training khá phức tạp, các bạn đón đọc các bài tiếp theo để nắm được nguyên lý.
Sự khác biệt giữa code Python ở trên với code trong Notebook
Đoạn code ở trên đã được chỉnh sửa nhiều để có thể chạy trên Windows 10.
- Không download ảnh trong code nữa, user download về sẵn
- Thay thế hàm load files ảnh
- Thêm code save model tại dòng: model.save(“model_flower.h5”)
- Thêm code load model tại dòng: new_model = tf.keras.models.load_model(‘model_flower.h5’)
- Thêm code xóa ảnh đã predict tại dòng: os.remove(sunflower_path)
Chúc các bạn thành công. Còn không thành công? Contact me with detail on the website footer.