Báo cáo học liệu
Mua học liệu
Mua học liệu:
-
Số dư ví của bạn: 0 coin - 0 Xu
-
Nếu mua học liệu này bạn sẽ bị trừ: 2 coin\Xu
Để nhận Coin\Xu, bạn có thể:
Simple Neural Network on MNIST SVIP
Nội dung này do giáo viên tự biên soạn.
Tài liệu này từ nguồn:
https://becominghuman.ai/simple-neural-network-on-mnist-handwritten-digit-dataset-61e47702ed25
Hôm nay tôi chia sẻ dự án đơn giản của mình liên quan đến việc triển khai mạng neuron cho bài toán phân loại. Như được hiển thị trong tiêu đề của bài viết này, tôi sẽ thực hiện phân loại trên tập dữ liệu Chữ số viết tay MNIST.
Lưu ý: Phần code đầy đủ có ở cuối bài viết này.
Điều đầu tiên cần làm là import các thư viện cần thiết. Ở đây tôi sử dụng NumPy để xử lý ma trận số, Matplotlib để hiển thị hình ảnh và Keras để xây dựng mô hình mạng Neuron. Ngoài ra, tập dữ liệu MNIST cũng được lấy từ Keras.
import numpy as np
import matplotlib.pyplot as plt
from keras.layers import Dense, Flatten
from keras.models import Sequential
from keras.utils import to_categorical
from keras.datasets import mnist
Tiếp theo, chúng ta tập dữ liệu bằng cách sử dụng đoạn mã sau. Lưu ý rằng việc này có thể mất một chút thời gian, đặc biệt nếu đây là lần đầu tiên bạn làm việc với tập dữ liệu MNIST. Sau khi chạy đoạn mã bên dưới, chúng ta sẽ có 4 biến là X_train , y_train , X_test và y_test , trong đó X là kí hiệu cho hình ảnh và y là nhãn ảnh (chữ số 0, 1, ..., 9). Dữ liệu huấn luyện và kiểm tra này lần lượt bao gồm 60000 và 10000 hình ảnh, trong đó tất cả những hình ảnh đó đều có cùng kích thước (28 x 28 pixel).
# Load MNIST handwritten digit data
(X_train, y_train), (X_test, y_test) = mnist.load_data()
Bạn có thể kiểm tra những con số tôi đã đề cập ở trên (số lượng ảnh của tập huấn luyện và tập kiểm tra) bằng cách sử dụng đoạn mã sau:
print(X_train.shape)
print(X_test.shape)
Kết quả đầu ra sẽ giống như thế này:
(60000, 28, 28)
(10000, 28, 28)
Dòng trên là 60000 ảnh, mỗi ảnh có kích thước 28 x 28 (chiều cao và chiều rộng của ảnh).
Bạn cũng có thể thử in ra kích thước của nhãn lớp (y) như sau:
print(y_train.shape)
print(y_test.shape)
Kết quả như sau:
(60000,)
(10000,)
Các giá trị của nhãn lớp được lưu trữ trong mảng 1 chiều vì về cơ bản tất cả các nhãn được biểu diễn dưới dạng một số. Tuy nhiên, kiểu biểu diễn nhãn này không phải là kiểu mà mạng neuron mong đợi, vì vậy chúng ta cần biến kiểu biểu diễn này thành kiểu biểu diễn dạng vecto on-hot coding trước khi huấn luyện mô hình (chúng ta sẽ thảo luận về vấn đề này sau).
Cho đến thời điểm này, bạn có thể đang thắc mắc hình ảnh Chữ số MNIST trông như thế nào. Vì vậy, bây giờ tôi muốn hiển thị 5 hình ảnh đầu tiên trong tập dữ liệu bằng cách sử dụng mã sau:
# Display some images
fig, axes = plt.subplots(ncols=5, sharex=False,
sharey=True, figsize=(10, 4))
for i in range(5):
axes[i].set_title(y_train[i])
axes[i].imshow(X_train[i], cmap='gray')
axes[i].get_xaxis().set_visible(False)
axes[i].get_yaxis().set_visible(False)
plt.show()
Sau khi chạy đoạn mã, bạn sẽ có đầu ra như sau:
Các hình ảnh trên hiển thị chữ số viết bằng tay (X) cùng với nhãn (y) phía trên mỗi hình ảnh.
Như tôi đã nói trước đó, bây giờ chúng ta sẽ biến tất cả các nhãn thành biểu diễn dạng one-hot coding. Việc này có thể được thực hiện dễ dàng bằng cách sử dụng hàm to_categorical() từ mô-đun Keras. Trước khi sử dụng hàm này vào chương trình chính của chúng ta, tôi sẽ giải thích một chút về cách hoạt động của hàm này. Vì vậy, trong ví dụ bên dưới, tôi sẽ tìm ra cách biểu diễn one-hot coding cho nhãn lớp có nhãn là 3 trong đó tổng số lớp là 10.
to_categorical(3, num_classes=10)
Kết quả là:
array([0., 0., 0., 1., 0., 0., 0., 0., 0., 0.], dtype=float32)
Ở đây bạn có thể thấy rằng đầu ra là một mảng đơn giản có các giá trị toàn bằng 0 ngoại trừ giá trị của chỉ số 3. Và thế là xong. Sự biểu diễn như vậy được gọi là one-hot coding. Bây giờ, điều chúng tôi muốn làm trong chương trình của mình là mã hóa tất cả các nhãn lớp (cho cả y_train và y_test ), việc này có thể được thực hiện bằng cách sử dụng mã sau:
# Convert y_train into one-hot format temp = [] for i in range(len(y_train): temp.append(to_categorical(y_train[i], num_classes=10)) y_train = np.array(temp)# Convert y_test into one-hot format temp = [] for i in range(len(y_test)): temp.append(to_categorical(y_test[i], num_classes=10)) y_test = np.array(temp)
Bây giờ chúng ta có thể kiểm tra hình dạng mới của y_train và y_test.print(y_train.shape)
print(y_test.shape)
Nếu tất cả các nhãn mục tiêu đã ở dạng biểu diễn one-hot coding, thì kết quả ra sẽ trông giống như thế này:
(60000, 10)
(10000, 10)
Được rồi, tính đến thời điểm này, chúng ta đã có hình dạng nhãn lớp phù hợp. Bây giờ chúng ta có thể bắt đầu tạo mô hình mạng neuron bằng Keras.
Điều đầu tiên cần làm là khởi tạo một mô hình tuần tự. Sau đó, chúng ta có thể thêm các tầng vào chuỗi mô hình tuần tự đó. Ở đây tôi bắt đầu mô hình mạng neuron với một tầng vào (input layer) với 784 giá trị, mỗi giá trị là 1 pixel (duỗi ảnh 2 chiều 28 x 28 pixel thành vecto có 784 pixel). Tiếp theo, chúng ta kết nối 784 giá trị này với 5 neuron ở tầng thứ 2 (second layer, còn gọi là tầng ẩn hidden layer) với hàm kích hoạt sigmoid. Trên thực tế, bạn có thể tự do chọn số lượng neuron bất kỳ cho tầng này, nhưng vì tôi muốn làm cho mô hình Mạng neuron trở nên đơn giản và đào tạo nhanh chóng nên tôi chỉ chọn 5 neuron cho tầng thứ hai này. Bạn có thể thêm một số tầng nữa tùy ý. Kết nối giữa tầng trước và tầng tầng tiếp theo là kết nối đầy đủ (dense), tức là tất cả các neuron ở tầng trước đều có liên kết với một neuron ở tầng sau. Cuối cùng là tầng ra (output layer) với hàm kích hoạt softmax với 10 neuron vì bài toán phân loại của chúng ta có 10 lớp khác nhau. Mỗi một neuron ở tầng ra đại diện cho một nhãn lớp (từ 0 đến 9).
# Create simple Neural Network model
model = Sequential()
model.add(Flatten(input_shape=(28,28)))
model.add(Dense(5, activation='sigmoid'))
model.add(Dense(10, activation='softmax'))
Chúng ta cũng có thể sử dụng mã bên dưới để xem chi tiết về kiến trúc của mình:
model.summary()
Kết quả cho biết chi tiết về các lớp bên trong mạng neuron
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
flatten_1 (Flatten) (None, 784) 0
_________________________________________________________________
dense_1 (Dense) (None, 5) 3925
_________________________________________________________________
dense_2 (Dense) (None, 10) 60
=================================================================
Total params: 3,985
Trainable params: 3,985
Non-trainable params: 0
Sau khi có cấu trúc mô hình mạng neuron, chúng ta cần compile nó với đoạn mã sau:
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc'])
Đoạn mã khia báo rằng chúng ta sử dụng hàm cross-entropy làm hàm mất mát thông tin (hàm này đo khoảng cách giữa 2 phân bố xác suất, thông thường phân bố thứ nhất là dạng biểu diễn one-hot coding như nói ở trên, gọi là đầu ra mong đợi của mô hình, còn phân bố thứ hai là giá trị của các neuron ở tầng ra output layer của mô hình). Tiếp theo, chúng ta sử dụng thuật toán tối ưu hóa Adam vì đây cũng là trình tối ưu hóa tốt nhất cho hầu hết các trường hợp. Cuối cùng, chúng tôi cần khai báo hàm đánh giá mô hình, ở đây dùng độ đo accuracy (tỉ lệ chính xác) để đo lường hiệu suất của mô hình phân loại của chúng ta.
Bây giờ hãy đến phần thú vị: huấn luyện mạng neuron! Vì vậy, về cơ bản, việc huấn luyện một mô hình rất đơn giản vì những gì chúng ta cần làm chỉ là chạy phương thức fit().
model.fit(X_train, y_train, epochs=5,
validation_data=(X_test,y_test))
Và nó sẽ hiển thị chi tiết quá trình huấn luyện như thế này:
Train on 60000 samples, validate on 10000 samples
Epoch 1/5
60000/60000 [==============================] - 10s 170us/step - loss: 1.5269 - acc: 0.5605 - val_loss: 1.1787 - val_acc: 0.6808
Epoch 2/5
60000/60000 [==============================] - 10s 169us/step - loss: 1.0848 - acc: 0.6741 - val_loss: 0.9602 - val_acc: 0.7235
Epoch 3/5
60000/60000 [==============================] - 10s 172us/step - loss: 0.9469 - acc: 0.7269 - val_loss: 0.8891 - val_acc: 0.7506
Epoch 4/5
60000/60000 [==============================] - 10s 173us/step - loss: 0.8878 - acc: 0.7409 - val_loss: 0.8795 - val_acc: 0.7650
Epoch 5/5
60000/60000 [==============================] - 10s 172us/step - loss: 0.8525 - acc: 0.7542 - val_loss: 0.8133 - val_acc: 0.7737
Theo kết quả đầu ra ở trên, chúng ta có thể thấy rằng độ chính xác ngày càng tăng (cả trên tập dữ liệu huấn luyện và và tập dữ liệukiểm tra) trong quy trình huấn luyện 5 lần lặp. Tôi nghĩ kết quả này khá tốt vì chỉ với mô hình Neural Network tương đối đơn giản chúng ta mới có thể đạt được độ chính xác xấp xỉ 75%, mặc dù kết quả này vẫn có thể được cải thiện.
Bây giờ chúng ta có thể thử thực hiện dự đoán trên một số hình ảnh được lưu trữ trong biến kiểm tra X _ của chúng ta.
predictions = model.predict(X_test)
print(predictions)
Tuy nhiên, kết quả có thể gây khó hiểu vì nó hiển thị kết quả giống như sau:
1.5031 1.5031 934e- 02...1.5586615e-
05 [ 1.384] 2285e- 03 4.1633844e - 05 1.8185675e-03 ... 4.7475308e-02 2.2819310e-02 3.5299832e-01] [5.5582732e-02 3.3888221e-04 9.7544789e-03 ... 2.3180246e-04 2.1919 787e- 01 4.4040084e-03] [ 1.2986362e-03 1.9049346e-03 4.7103435e-02 ... 5.5095553e-04 1.4519393e-03 3.0362308e-03]]
Vì vậy, trên thực tế, hình dạng đầu ra này là (10000, 10) trong đó nó lưu trữ giá trị xác suất phân loại của từng mẫu. Chạy đoạn mã sau để tìm ra dự đoán cuối cùng của mô hình:
predictions = np.argmax(predictions, axis=1)
print(predictions)
Sau đó nó cho kết quả như sau (đây là dự đoán của từng mẫu thử):
[7 2 1 ... 4 5 6]
Cuối cùng, bằng cách sử dụng đoạn mã bên dưới, chúng ta có thể thử in một số hình ảnh cùng với dự đoán của nó:
fig, axes = plt.subplots(ncols=10, sharex=False,
sharey=True, figsize=(20, 4))
for i in range(10):
axes[i].set_title(predictions[i])
axes[i].imshow(X_test[i], cmap='gray')
axes[i].get_xaxis().set_visible(False)
axes[i].get_yaxis().set_visible(False)
plt.show()
Kết quả trông như thế này:
Hình ảnh đầu ra ở trên hiển thị 10 hình ảnh thử nghiệm đầu tiên cùng với các dự đoán của nó phía trên mỗi hình ảnh chữ số đó. Bạn có thể thấy ở đó hầu hết những chữ viết tay đó đều được phân loại chính xác. Chỉ có bức ảnh thứ 9 (từ bên trái) là mẫu bị phân loại sai vì lẽ ra nó phải là số năm (tôi nghĩ vậy) nhưng nó được dự đoán là số bốn.
Dưới đây là toàn văn mã chương trình của bài viết này.
import numpy as np import matplotlib.pyplot as plt from keras.layers import Dense, Flatten from keras.models import Sequential from keras.utils import to_categorical from keras.datasets import mnist # Load MNIST handwritten digit data (X_train, y_train), (X_test, y_test) = mnist.load_data() print(X_train.shape) print(X_test.shape) print(y_train.shape) print(y_test.shape) # Display some images fig, axes = plt.subplots(ncols=5, sharex=False, sharey=True, figsize=(10, 4)) for i in range(5): axes[i].set_title(y_train[i]) axes[i].imshow(X_train[i], cmap='gray') axes[i].get_xaxis().set_visible(False) axes[i].get_yaxis().set_visible(False) plt.show() to_categorical(3, num_classes=10) # Convert y_train into one-hot format temp = [] for i in range(len(y_train)): temp.append(to_categorical(y_train[i], num_classes=10)) y_train = np.array(temp) # Convert y_test into one-hot format temp = [] for i in range(len(y_test)): temp.append(to_categorical(y_test[i], num_classes=10)) y_test = np.array(temp) print(y_train.shape) print(y_test.shape) # Create simple Neural Network model model = Sequential() model.add(Flatten(input_shape=(28,28))) model.add(Dense(5, activation='sigmoid')) model.add(Dense(10, activation='softmax')) model.summary() model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc']) model.fit(X_train, y_train, epochs=5, validation_data=(X_test,y_test)) predictions = model.predict(X_test) print(predictions) predictions = np.argmax(predictions, axis=1) print(predictions) fig, axes = plt.subplots(ncols=10, sharex=False, sharey=True, figsize=(20, 4)) for i in range(10): axes[i].set_title(predictions[i]) axes[i].imshow(X_test[i], cmap='gray') axes[i].get_xaxis().set_visible(False) axes[i].get_yaxis().set_visible(False) plt.show()
Bạn có thể đánh giá bài học này ở đây