Xây dựng mô hình thị giác máy tính với TensorFlow

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

Trong lớp học lập trình này, bạn sẽ tạo một mô hình thị giác máy tính có thể nhận dạng các mặt hàng quần áo bằng TensorFlow.

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

  • Kiến thức vững chắc về Python
  • Kỹ năng lập trình cơ bản

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

Trong lớp học lập trình này, bạn sẽ:

  • Đào tạo một mạng nơ-ron để nhận dạng các bài viết về quần áo
  • Hoàn thành một loạt bài tập để hướng dẫn bạn thực hiện các thử nghiệm với các lớp khác nhau của mạng

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

  • Mạng nơron xác định các bài viết về quần áo

Bạn cần có

Nếu bạn chưa từng tạo mạng nơ-ron cho thị giác máy tính với TensorFlow, bạn có thể sử dụng Colaboratory, một môi trường dựa trên trình duyệt để chứa tất cả các phần phụ thuộc bắt buộ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.

Nếu không, ngôn ngữ chính mà bạn sẽ sử dụng cho các mô hình đào tạo là Python, vì vậy, bạn sẽ cần cài đặt ngôn ngữ này. Ngoài ra, bạn cũng cần có TensorFlow và thư viện NumPy. Bạn có thể tìm hiểu thêm và cài đặt TensorFlow tại đây. Cài đặt NumPy tại đây.

2. Bắt đầu lập trình

Trước tiên, hãy xem qua sổ tay Colab có thể thực thi.

Bắt đầu bằng cách nhập TensorFlow.

import tensorflow as tf
print(tf.__version__)

Bạn sẽ đào tạo một mạng nơron để nhận dạng các mặt hàng quần áo từ một tập dữ liệu phổ biến có tên là Thời trang MNIST. Nó chứa 70.000 mặt hàng quần áo thuộc 10 danh mục khác nhau. Mỗi mặt hàng đều có hình ảnh 28x28 màu xám. Bạn có thể xem một số ví dụ tại đây:

Các nhãn liên kết với tập dữ liệu là:

Nhãn

Mô tả

0

Mặc bên trong áo phông

1

Quần

2

Áo thun không tay

3

Váy

4

Áo khoác dài

5

Dép quai hậu

6

Áo sơ mi

7

Giày sneaker

8

Túi

9

Bốt cổ ngắn

Dữ liệu MNIST Fashion có trong API tf.keras.datasets. Tải như sau:

mnist = tf.keras.datasets.fashion_mnist

Việc gọi load_data trên đối tượng đó sẽ cung cấp cho bạn hai bộ danh sách: giá trị đào tạo và giá trị thử nghiệm, đại diện cho các hình ảnh hiển thị các mặt hàng quần áo và nhãn của các mặt hàng đó.

(training_images, training_labels), (test_images, test_labels) = mnist.load_data()

Những giá trị đó trông như thế nào? In một hình ảnh đào tạo và một nhãn đào tạo để xem. Bạn có thể thử nghiệm với các chỉ mục khác nhau trong mảng.

import matplotlib.pyplot as plt
plt.imshow(training_images[0])
print(training_labels[0])
print(training_images[0])

Bản in dữ liệu cho mục 0 sẽ có dạng như sau:

Bạn sẽ nhận thấy rằng tất cả các giá trị là số nguyên từ 0 đến 255. Khi đào tạo một mạng nơ-ron, sẽ dễ dàng xử lý tất cả các giá trị trong khoảng từ 0 đến 1, một quá trình có tên là chuẩn hóa. May mắn thay, Python cung cấp một cách dễ dàng để chuẩn hóa danh sách như vậy mà không cần lặp lại.

training_images  = training_images / 255.0
test_images = test_images / 255.0

Bạn cũng có thể muốn xem 42, một khởi động khác với khởi động ở chỉ mục 0.

Bây giờ, bạn có thể tự hỏi tại sao có hai tập dữ liệu – đào tạo và thử nghiệm.

Ý tưởng là việc có một tập dữ liệu để đào tạo và một tập dữ liệu khác mà mô hình này chưa gặp phải để xem mức độ hiệu quả của mô hình đó trong việc phân loại các giá trị. Sau cùng, khi hoàn tất, bạn sẽ muốn sử dụng mô hình với dữ liệu mà trước đây họ chưa từng thấy! Ngoài ra, nếu không có dữ liệu thử nghiệm riêng, bạn sẽ chỉ gặp rủi ro về việc mạng chỉ ghi nhớ dữ liệu đào tạo của mạng mà không tổng quát kiến thức của mạng.

3. Thiết kế mô hình

Bây giờ, hãy thiết kế mô hình. Bạn sẽ có ba lớp. Xem lần lượt từng lớp và khám phá các loại lớp khác nhau và các thông số được sử dụng cho từng lớp.

model = tf.keras.models.Sequential([tf.keras.layers.Flatten(), 
                                    tf.keras.layers.Dense(128, activation=tf.nn.relu), 
                                    tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
  • Sequential xác định một chuỗi các lớp trong mạng nơ-ron.
  • Flatten lấy một hình vuông và biến nó thành một vectơ một chiều.
  • Dense thêm một lớp nơ-ron.
  • Hàm Activation cho mỗi lớp thần kinh biết cần làm gì. Có rất nhiều tùy chọn, nhưng bây giờ hãy sử dụng các tùy chọn này:
  • Relu hiệu quả có nghĩa là nếu X lớn hơn 0, hãy trả về X, nếu không thì trả về 0. Thuộc tính này chỉ chuyển các giá trị từ 0 trở lên đến lớp tiếp theo trong mạng.
  • Softmax lấy một tập hợp giá trị và chọn giá trị lớn nhất một cách hiệu quả. Ví dụ: nếu đầu ra của lớp cuối cùng có dạng [0,1, 0,1, 0,05, 0,1, 9,5, 0,1, 0,05, 0,05, 0,05], thì bạn sẽ không phải sắp xếp giá trị lớn nhất — giá trị này trả về [0,0,0,0,1,0,0,0

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

Sau khi đã xác định được mô hình, việc tiếp theo bạn cần làm là xây dựng mô hình đó. Trước tiên, hãy tạo một mô hình bằng cách biên dịch mô hình đó với hàm optimizerloss, sau đó huấn luyện mô hình đó trên dữ liệu đào tạo và nhãn. Mục tiêu là để mô hình này xác định mối quan hệ giữa dữ liệu đào tạo và nhãn đào tạo. Sau đó, bạn muốn mô hình của mình xem dữ liệu tương tự như dữ liệu đào tạo, sau đó dự đoán dữ liệu sẽ trông như thế nào.

Lưu ý việc sử dụng metrics= làm thông số để cho phép TensorFlow báo cáo về độ chính xác của nội dung đào tạo bằng cách kiểm tra kết quả dự đoán so với các câu trả lời đã biết (nhãn).

model.compile(optimizer = tf.keras.optimizers.Adam(),
              loss = 'sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(training_images, training_labels, epochs=5)

Khi model.fit thực thi, bạn sẽ thấy độ mất độ chính xác:

Epoch 1/5
60000/60000 [=======] - 6s 101us/sample - loss: 0.4964 - acc: 0.8247
Epoch 2/5
60000/60000 [=======] - 5s 86us/sample - loss: 0.3720 - acc: 0.8656
Epoch 3/5
60000/60000 [=======] - 5s 85us/sample - loss: 0.3335 - acc: 0.8780
Epoch 4/5
60000/60000 [=======] - 6s 103us/sample - loss: 0.3134 - acc: 0.8844
Epoch 5/5
60000/60000 [=======] - 6s 94us/sample - loss: 0.2931 - acc: 0.8926

Khi mô hình được đào tạo xong, bạn sẽ thấy giá trị chính xác vào cuối kỷ nguyên cuối cùng. Số này có thể trông như 0,8926 như trên. Điều này cho bạn biết rằng mạng nơ-ron có độ chính xác khoảng 89% trong việc phân loại dữ liệu đào tạo. Nói cách khác, hệ thống này đã tìm ra sự trùng khớp mẫu giữa hình ảnh và các nhãn hoạt động 89% thời gian. Không tốt nhưng không tệ vì chỉ được đào tạo cho năm kỷ nguyên và hoàn thành nhanh chóng.

5. Thử nghiệm mô hình

Mô hình này sẽ hoạt động như thế nào đối với dữ liệu mà nó không thấy? Đó là lý do bạn đặt nhóm thử nghiệm. Bạn gọi model.evaluate và chuyển vào hai tập dữ liệu, sau đó báo cáo mất dữ liệu cho mỗi tập hợp. Hãy dùng thử:

model.evaluate(test_images, test_labels)

Và đây là kết quả:

10000/10000 [=====] - 1s 56us/sample - loss: 0.3365 - acc: 0.8789
[0.33648381242752073, 0.8789]

Ví dụ đó trả về độ chính xác .8789, nghĩa là chính xác khoảng 88%. (Bạn có thể có các giá trị hơi khác nhau.)

Như mong đợi, mô hình này không chính xác bằng dữ liệu không xác định như dữ liệu đã huấn luyện! Khi tìm hiểu thêm về TensorFlow, bạn sẽ tìm được cách cải thiện điều đó.

Để khám phá thêm, hãy thử các bài tập trong bước tiếp theo.

6. Bài tập khám phá

Bài tập 1

Đối với bài tập đầu tiên này, hãy chạy mã sau:

classifications = model.predict(test_images)
print(classifications[0])

Thao tác này sẽ tạo một tập hợp phân loại cho mỗi hình ảnh thử nghiệm, sau đó in mục đầu tiên trong các phân loại. Kết quả sau khi bạn chạy sẽ là một danh sách các số. Vì sao bạn cho rằng đó là kết quả và những con số đó thể hiện điều gì?

Hãy thử chạy print(test_labels[0]) và bạn sẽ nhận được 9 điểm. Điều đó có giúp bạn hiểu tại sao danh sách có hình thức như vậy không?

Đầu ra của mô hình là danh sách gồm 10 số. Những con số đó là xác suất mà giá trị đang được phân loại là nhãn tương ứng. Ví dụ: giá trị đầu tiên trong danh sách là xác suất quần áo thuộc lớp 0 và giá trị tiếp theo là lớp 1. Bạn có thể thấy rằng tất cả đều có xác suất rất thấp ngoại trừ một trường hợp. Ngoài ra, do Softmax, tất cả các xác suất trong danh sách sẽ cộng lại là 1.0.

Danh sách và các nhãn là 0 dựa trên, vì vậy, giày cổ chân có nhãn 9 có nghĩa là đó là thứ 10 của 10 lớp. Danh sách có phần tử thứ 10 có giá trị cao nhất có nghĩa là mạng nơ-ron đã dự đoán rằng mục mà lớp đang phân loại có khả năng cao nhất là khởi động mắt cá chân.

Bài tập 2

Xem các lớp trong mô hình của bạn. Hãy thử nghiệm với các giá trị khác nhau cho lớp dày đặc với 512 nơ-ron.

Bạn nhận được kết quả nào khác nhau khi thua cuộc và mất thời gian đào tạo? Tại sao bạn nghĩ đó là trường hợp của mình?

Ví dụ: nếu bạn tăng lên 1.024 nơron, bạn phải thực hiện nhiều phép tính hơn, làm chậm quá trình. Nhưng trong trường hợp này, tác động của những thay đổi này mang lại tác động tốt vì mô hình này chính xác hơn. Việc này không phải lúc nào cũng tốt hơn. Bạn có thể nhanh chóng đạt được luật giảm thiểu số lượt trả lại hàng.

Bài tập 3

Điều gì sẽ xảy ra nếu bạn xóa lớp Flatten(). Tại sao bạn nghĩ đó là trường hợp của mình?

Bạn nhận được lỗi về hình dạng của dữ liệu. Các chi tiết của lỗi này có vẻ mơ hồ ngay bây giờ, nhưng nó củng cố quy tắc chung rằng lớp đầu tiên trong mạng của bạn phải có hình dạng giống như dữ liệu của bạn. Hiện tại, dữ liệu của bạn là hình ảnh 28x28 và 28 lớp gồm 28 tế bào thần kinh sẽ không khả thi, vì vậy sẽ hợp lý hơn khi phân tách 28,28 thành 784x1.

Thay vì viết tất cả mã, hãy thêm lớp Flatten() vào đầu. Khi các mảng được tải vào mô hình sau, chúng sẽ tự động được làm phẳng cho bạn.

Bài tập 4

Hãy xem xét lớp (đầu ra) cuối cùng. Tại sao có 10 kết quả này? Điều gì sẽ xảy ra nếu bạn có số tiền khác với 10?

Hãy thử đào tạo mạng bằng 5. Bạn nhận được lỗi ngay khi phát hiện một giá trị không mong muốn. Một quy tắc chung khác – số lượng tế bào thần kinh trong lớp cuối cùng phải khớp với số lớp học mà bạn đang phân loại. Trong trường hợp này, đó là các chữ số từ 0 đến 9, vì vậy có 10 chữ số trong số đó và do đó bạn nên có 10 tế bào thần kinh trong lớp cuối cùng của mình.

Bài tập 5

Xem xét ảnh hưởng của các lớp bổ sung trong mạng. Điều gì sẽ xảy ra nếu bạn thêm một lớp khác giữa lớp có 512 và lớp cuối cùng có 10?

Không có ảnh hưởng đáng kể vì đây là dữ liệu tương đối đơn giản. Đối với dữ liệu phức tạp hơn nhiều, các lớp bổ sung thường cần thiết.

Bài tập 6

Trước khi đào tạo, bạn chuẩn hóa dữ liệu, từ giá trị từ 0 đến 255 thành giá trị từ 0 đến 1. Tác động của việc xóa nội dung đó sẽ như thế nào? Đây là mã hoàn chỉnh để thử lại (lưu ý rằng hai dòng chuẩn hóa dữ liệu).

Vì sao bạn cho rằng bạn nhận được các kết quả khác nhau? Có một câu trả lời tuyệt vời ở đây trên Stack Overflow.

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/255.0
#test_images=test_images/255.0
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(512, activation=tf.nn.relu),
  tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy')
model.fit(training_images, training_labels, epochs=5)
model.evaluate(test_images, test_labels)
classifications = model.predict(test_images)
print(classifications[0])
print(test_labels[0])

7. Khám phá các lệnh gọi lại

Trước đó, khi bạn tập luyện cho các kỷ nguyên mới, bạn gặp phải vấn đề và việc giảm sút có thể thay đổi. Bạn có thể mất một chút thời gian để chờ chương trình đào tạo làm việc đó và bạn có thể nghĩ rằng bạn có thể ngừng đào tạo khi đạt được giá trị mong muốn, chẳng hạn như độ chính xác 95%. Nếu bạn đạt được điều đó sau 3 kỷ nguyên, tại sao bạn phải chờ cho đến khi kết thúc nhiều kỷ nguyên hơn?

Giống như bất kỳ chương trình nào khác, bạn có lệnh gọi lại! Xem trong thực tế:

import tensorflow as tf

class myCallback(tf.keras.callbacks.Callback):
  def on_epoch_end(self, epoch, logs={}):
    if(logs.get('accuracy')>0.95):
      print("\nReached 95% accuracy so cancelling training!")
      self.model.stop_training = True

callbacks = myCallback()
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(512, activation=tf.nn.relu),
  tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5, callbacks=[callbacks])

8. Xin chúc mừng

Bạn đã xây dựng mô hình thị giác máy tính đầu tiên! Để tìm hiểu cách cải thiện các mô hình thị giác máy tính, hãy tiến hành Xây dựng lượt chuyển đổi và thực hiện nhóm.