Xây dựng mạng nơ-ron cách mạng (CNN) để tăng cường thị lực máy tính

1. Trước khi bắt đầu

Trong lớp học lập trình này, bạn sẽ tìm hiểu cách sử dụng CNN để cải thiện các mô hình phân loại hình ảnh của mình.

Điều kiện tiên quyết

Lớp học mã này xây dựng dựa trên công việc đã hoàn thành trong hai phần trả trước trước, Xây dựng mô hình thị giác máy tính, trong đó chúng tôi giới thiệu một số mã mà bạn sẽ sử dụng ở đây, cũng như Lớp học kết hợp và thực hiện nhóm mã, trong đó chúng tôi giới thiệu lượt chuyển đổi và nhóm.

Kiến thức bạn sẽ học được

  • Cách cải thiện thị lực máy tính và độ chính xác thông qua tính năng chuyển đổi

Sản phẩm bạn sẽ tạo ra

  • Các lớp để cải thiện mạng nơ-ron của bạn

Bạn cần có

Bạn có thể tìm thấy mã cho phần còn lại của lớp học lập trình chạy trong Colab.

Bạn cũng cần cài đặt TensorFlow và các thư viện bạn đã cài đặt trong lớp học lập trình trước đó.

2. Cải thiện độ chính xác của thị lực máy tính bằng số lượt chuyển đổi

Giờ đây, bạn đã biết cách nhận dạng hình ảnh thời trang bằng Mạng nơron sâu (DNN) chứa 3 lớp – lớp đầu vào (dưới dạng dữ liệu đầu vào), lớp đầu ra (ở dạng hình ảnh đầu ra mong muốn) và lớp ẩn. Bạn đã thử nghiệm với một số thông số ảnh hưởng đến độ chính xác cuối cùng, chẳng hạn như các kích thước khác nhau của lớp ẩn và số lượng kỷ nguyên đào tạo.

Để thuận tiện, hãy xem lại toàn bộ mã. Chạy thử nghiệm và ghi lại độ chính xác của thử nghiệm được in ở cuối.

import tensorflow as tf
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images/255.0
test_images=test_images/255.0
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5)
test_loss, test_accuracy = model.evaluate(test_images, test_labels)
print ('Test loss: {}, Test accuracy: {}'.format(test_loss, test_accuracy*100))

Có thể độ chính xác của bạn là khoảng 89% khi đào tạo và 87% khi xác thực. Bạn có thể làm điều đó tốt hơn nữa bằng cách sử dụng lượt chuyển đổi để thu hẹp nội dung của hình ảnh để tập trung vào các chi tiết cụ thể và riêng biệt.

Nếu bạn đã từng xử lý hình ảnh bằng một bộ lọc, thì lượt chuyển đổi sẽ rất quen thuộc.

Nói ngắn gọn, bạn chụp một mảng (thường là 3x3 hoặc 5x5) và chuyển mảng đó lên trên hình ảnh. Bằng cách thay đổi pixel cơ bản dựa trên công thức trong ma trận đó, bạn có thể thực hiện các thao tác như phát hiện biên. Ví dụ: thông thường, hệ thống xác định cạnh 3x3 để phát hiện cạnh, trong đó ô ở giữa là 8 và tất cả các vùng lân cận đều là -1. Trong trường hợp này, đối với mỗi pixel, bạn sẽ nhân giá trị của pixel đó với 8, sau đó trừ đi giá trị của mỗi vùng lân cận. Làm như vậy cho mọi pixel và bạn sẽ kết thúc với một hình ảnh mới được cải thiện các cạnh.

Điều này là hoàn hảo cho thị giác máy tính bởi vì các tính năng nâng cao như cạnh giúp máy tính phân biệt một mục với một mục khác. Hơn nữa, lượng thông tin cần thiết ít hơn nhiều vì bạn sẽ chỉ đào tạo về các tính năng được đánh dấu.

Đó là khái niệm của Mạng nơron cách mạng. Thêm một số lớp để thực hiện chuyển đổi trước khi bạn có các lớp dày đặc và sau đó thông tin đi tới các lớp đông đúc trở nên tập trung hơn và có thể chính xác hơn.

3. Thử nhập mã

Chạy mã sau. Đó là mạng nơ-ron như trước, nhưng lần này với các lớp cách mạng được thêm vào trước. Việc này sẽ mất nhiều thời gian hơn, nhưng hãy xem xét tác động đối với độ chính xác:

import tensorflow as tf
print(tf.__version__)
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images.reshape(60000, 28, 28, 1)
training_images=training_images / 255.0
test_images = test_images.reshape(10000, 28, 28, 1)
test_images=test_images / 255.0
model = tf.keras.models.Sequential([
  tf.keras.layers.Conv2D(64, (3, 3), activation='relu', input_shape=(28, 28, 1)),
  tf.keras.layers.MaxPooling2D(2, 2),
  tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
  tf.keras.layers.MaxPooling2D(2,2),
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.summary()
model.fit(training_images, training_labels, epochs=5)
test_loss, test_accuracy = model.evaluate(test_images, test_labels)
print ('Test loss: {}, Test accuracy: {}'.format(test_loss, test_accuracy*100))

Dữ liệu đó có thể tăng lên đến 93% và dữ liệu đào tạo là 91%.

Bây giờ, hãy thử chạy chiến dịch để có thêm kỷ nguyên – giả sử khoảng 20 giai đoạn – và khám phá kết quả. Mặc dù kết quả đào tạo có vẻ thực sự tốt, nhưng kết quả xác thực có thể thực sự giảm xuống do một hiện tượng được gọi là tăng cường.

Tình trạng cung cấp quá nhiều thông tin xảy ra khi mạng tìm hiểu dữ liệu từ quá trình huấn luyện một cách quá hiệu quả, nên sẽ chỉ nhận ra dữ liệu đó, do đó sẽ kém hiệu quả hơn khi xem dữ liệu khác trong những tình huống chung chung hơn. Ví dụ: nếu bạn chỉ luyện tập giày cao gót, thì mạng có thể rất hiệu quả trong việc xác định giày cao gót, nhưng giày thể thao có thể khiến bạn khó hiểu.

Xem lại mã và xem từng bước tạo lượt chuyển đổi.

4. Thu thập dữ liệu

Bước đầu tiên là thu thập dữ liệu.

Bạn sẽ nhận thấy rằng có sự thay đổi ở đây và dữ liệu đào tạo cần được định hình lại. Điều đó bởi vì lượt chuyển đổi đầu tiên dự kiến một yếu tố duy nhất chứa mọi thứ, nên thay vì 60.000 mục 28x28x1 trong danh sách, bạn sẽ có danh sách 4D duy nhất là 60.000x28x28x1 và hình ảnh thử nghiệm cũng giống như vậy. Nếu bạn không làm điều đó, thì bạn sẽ gặp lỗi khi huấn luyện vì số lượt chuyển đổi không nhận dạng được hình dạng.

import tensorflow as tf
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images.reshape(60000, 28, 28, 1)
training_images = training_images/255.0
test_images = test_images.reshape(10000, 28, 28, 1)
test_images = test_images/255.0

5. Xác định mô hình

Tiếp theo, hãy xác định mô hình của bạn. Thay vì thêm lớp đầu vào ở trên cùng, bạn sẽ thêm một lớp cách mạng. Thông số là:

  • Số lượt chuyển đổi mà bạn muốn tạo. Một giá trị như 32 là điểm khởi đầu tốt.
  • Kích thước của ma trận cách mạng, trong trường hợp này là lưới 3x3.
  • Chức năng kích hoạt sử dụng, trong trường hợp này là relu.
  • Trong lớp đầu tiên, hình dạng của dữ liệu đầu vào.

Bạn sẽ theo dõi lượt chuyển đổi bằng một lớp gộp tối đa. Lớp này được thiết kế để nén hình ảnh, trong khi vẫn duy trì nội dung của các tính năng được làm nổi bật bằng lượt chuyển đổi. Bằng cách chỉ định (2,2) cho nhóm tối đa, hiệu quả là giảm kích thước của hình ảnh xuống hệ số 4. Nó tạo ra một mảng pixel 2x2 và chọn giá trị pixel lớn nhất, biến 4 pixel thành 1. Công cụ này lặp lại phép tính này trên toàn bộ hình ảnh, và sau đó thực hiện một nửa số pixel ngang và giảm một nửa số pixel dọc.

Bạn có thể gọi model.summary() để xem kích thước và hình dạng của mạng. Xin lưu ý rằng sau mỗi lớp gộp tối đa, kích thước hình ảnh sẽ giảm theo cách sau:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_2 (Conv2D)            (None, 26, 26, 64)        640       
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 13, 13, 64)        0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 11, 11, 64)        36928     
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
flatten_2 (Flatten)          (None, 1600)              0         
_________________________________________________________________
dense_4 (Dense)              (None, 128)               204928    
_________________________________________________________________
dense_5 (Dense)              (None, 10)                1290      
=================================================================

Mã đầy đủ của CNN:

model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D(2, 2),
#Add another convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2, 2),
#Now flatten the output. After this you'll just have the same DNN structure as the non convolutional version
tf.keras.layers.Flatten(),
#The same 128 dense layers, and 10 output layers as in the pre-convolution example:
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])

6. Biên dịch và đào tạo mô hình

Biên dịch mô hình, gọi phương pháp Fit để thực hiện việc đào tạo và đánh giá sự mất mát cũng như độ chính xác của bộ thử nghiệm.

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5)
test_loss, test_acc = model.evaluate(test_images, test_labels)
print ('Test loss: {}, Test accuracy: {}'.format(test_loss, test_acc*100))

7. Hình ảnh hóa lượt chuyển đổi và nhóm

Mã này hiển thị cho bạn các lượt chuyển đổi bằng hình ảnh. print (test_labels[:100]) hiển thị 100 nhãn đầu tiên trong nhóm thử nghiệm và bạn có thể thấy rằng các nhãn ở chỉ mục 0, chỉ mục 23 và chỉ mục 28 đều có cùng giá trị (9). Họ đều là giày. Hãy xem kết quả của việc chạy cuộc cách mạng trên mỗi mạng và bạn sẽ bắt đầu thấy các tính năng phổ biến giữa chúng. Bây giờ, khi DNN đang đào tạo về dữ liệu đó, nó hoạt động với ít thông tin hơn rất nhiều và có thể tìm thấy điểm chung giữa các đôi giày dựa trên sự kết hợp cách mạng và kết hợp đó.

print(test_labels[:100])
[9 2 1 1 6 1 4 6 5 7 4 5 7 3 4 1 2 4 8 0 2 5 7 9 1 4 6 0 9 3 8 8 3 3 8 0 7
 5 7 9 6 1 3 7 6 7 2 1 2 2 4 4 5 8 2 2 8 4 8 0 7 7 8 5 1 1 2 3 9 8 7 0 2 6
 2 3 1 2 8 4 1 8 5 9 5 0 3 2 0 6 5 3 6 7 1 8 0 1 4 2]

Giờ đây, bạn có thể chọn một số hình ảnh tương ứng cho các nhãn đó và hiển thị giao diện của các hình ảnh đó khi chuyển đổi. Vì vậy, trong mã sau, FIRST_IMAGE, SECOND_IMAGETHIRD_IMAGE là tất cả các chỉ số cho giá trị 9, một giày ống mắt cá chân.

import matplotlib.pyplot as plt
f, axarr = plt.subplots(3,4)
FIRST_IMAGE=0
SECOND_IMAGE=23
THIRD_IMAGE=28
CONVOLUTION_NUMBER = 6
from tensorflow.keras import models
layer_outputs = [layer.output for layer in model.layers]
activation_model = tf.keras.models.Model(inputs = model.input, outputs = layer_outputs)
for x in range(0,4):
  f1 = activation_model.predict(test_images[FIRST_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[0,x].imshow(f1[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[0,x].grid(False)
  f2 = activation_model.predict(test_images[SECOND_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[1,x].imshow(f2[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[1,x].grid(False)
  f3 = activation_model.predict(test_images[THIRD_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[2,x].imshow(f3[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[2,x].grid(False)

Và bạn sẽ thấy một điều như sau, trong đó lượt chuyển đổi đang lấy bản chất của phần đế giày, phát hiện hiệu quả điều đó như một đặc điểm chung trên tất cả các đôi giày.

6c9109SSO640a1ec.png

8. Bài tập

Bài tập 1

Hãy thử chỉnh sửa lượt chuyển đổi. Thay đổi số lượt chuyển đổi từ 32 thành 16 hoặc 64. Điều này có tác động gì đến độ chính xác và thời gian đào tạo?

Bài tập 2

Xóa lượt chuyển đổi cuối cùng. Điều này có tác động gì đến độ chính xác hoặc thời gian đào tạo?

Bài tập 3

Thêm lượt chuyển đổi khác. Điều đó có tác động gì?

Bài tập 4

Xóa tất cả các lượt chuyển đổi, trừ lượt chuyển đổi đầu tiên. Điều đó có tác động gì? Hãy thử nghiệm.

9. Xin chúc mừng

Bạn đã tạo CNN đầu tiên! Để tìm hiểu cách nâng cao thêm mô hình thị giác máy tính của bạn, hãy chuyển sang Sử dụng mạng nơron cách mạng (CNN) với hình ảnh phức tạp.