Logo Zephyrnet

Hiểu về trang bị quá mức trong ConvNets

Ngày:

Giới thiệu

Trang bị quá mức trong ConvNets là một thách thức trong mạng lưới thần kinh và học sâu, trong đó mô hình học quá nhiều từ dữ liệu huấn luyện, dẫn đến hiệu suất kém trên dữ liệu mới. Hiện tượng này đặc biệt phổ biến trong các kiến ​​trúc thần kinh phức tạp, có thể mô hình hóa các mối quan hệ phức tạp. Giải quyết vấn đề trang bị quá mức trong Convnet là rất quan trọng để xây dựng các mô hình mạng nơ-ron đáng tin cậy. Bài viết này cung cấp hướng dẫn để hiểu và giảm thiểu tình trạng trang bị quá mức, kiểm tra các nguyên nhân gốc rễ như độ phức tạp của mô hình, dữ liệu huấn luyện hạn chế và các tính năng gây nhiễu. Nó cũng thảo luận về các kỹ thuật để ngăn chặn việc trang bị quá mức, chẳng hạn như chiến lược tăng cường dữ liệu và các phương pháp chính quy hóa.

Tôi khuyên bạn nên đọc những bài viết này để hiểu cơ bản về trang bị quá mức, trang bị không đầy đủsự đánh đổi phương sai thiên vị.

Mục tiêu học tập

  • Hiểu nguyên nhân, hậu quả và kịch bản của việc trang bị quá mức trong ConvNet.
  • Giải thích các đường cong học tập để phát hiện quá mức và thiếu phù hợp trong các mô hình mạng lưới thần kinh.
  • Tìm hiểu các kỹ thuật khác nhau để giảm thiểu tình trạng trang bị quá mức, chẳng hạn như dừng sớm, bỏ học, chuẩn hóa hàng loạt, chính quy hóa và tăng cường dữ liệu.
  • Thực hiện các kỹ thuật này bằng cách sử dụng TensorFlow và Keras để đào tạo ConvNets trên bộ dữ liệu CIFAR-10.
  • Phân tích tác động của các kỹ thuật khác nhau đến hiệu suất và tổng quát hóa mô hình.

Mục lục

Các tình huống phổ biến về trang bị quá mức trong ConvNet

Chúng ta hãy xem xét một số trường hợp phổ biến về trang bị quá mức trong ConvNet:

Kịch bản 1: Mô hình có độ phức tạp cao và thiếu dữ liệu

Việc sử dụng một mô hình rất phức tạp, chẳng hạn như mạng lưới thần kinh sâu, trên một tập dữ liệu nhỏ có thể dẫn đến tình trạng trang bị quá mức. Mô hình có thể ghi nhớ các ví dụ huấn luyện thay vì học mẫu chung. Ví dụ, việc đào tạo một mạng lưới thần kinh sâu chỉ có vài trăm hình ảnh cho một nhiệm vụ phức tạp như nhận dạng hình ảnh có thể dẫn đến tình trạng trang bị quá mức.

Hậu quả

Mô hình có thể hoạt động rất tốt trên dữ liệu huấn luyện nhưng không khái quát hóa được dữ liệu mới, chưa được nhìn thấy, dẫn đến hiệu suất kém trong các ứng dụng trong thế giới thực.

Làm thế nào để giải quyết vấn đề này?

Nhận thêm dữ liệu đào tạo, Thực hiện tăng cường hình ảnh để khái quát hóa tập dữ liệu của chúng tôi. Bắt đầu với một mô hình ít phức tạp hơn và nếu dung lượng ít hơn thì hãy tăng độ phức tạp lên. 

Kịch bản 2: Đào tạo quá mức

Việc đào tạo liên tục một mô hình trong quá nhiều kỷ nguyên có thể dẫn đến tình trạng trang bị quá mức. Khi mô hình nhìn thấy dữ liệu huấn luyện nhiều lần, nó có thể bắt đầu ghi nhớ dữ liệu đó thay vì tìm hiểu các mẫu cơ bản.

Hậu quả

Hiệu suất của mô hình có thể ổn định hoặc thậm chí suy giảm trên dữ liệu không nhìn thấy khi nó ngày càng trở nên chuyên biệt cho tập huấn luyện.

Làm thế nào để giải quyết vấn đề này?

Sử dụng tính năng dừng sớm để tránh mô hình bị quá khớp và lưu mô hình tốt nhất. 

Kịch bản 3: Bỏ qua việc chính quy hóa

Các kỹ thuật chính quy hóa, chẳng hạn như chính quy hóa L1 hoặc L2, được sử dụng để ngăn chặn việc trang bị quá mức bằng cách xử phạt các mô hình phức tạp. Việc bỏ qua hoặc điều chỉnh các tham số chính quy hóa không đúng cách có thể dẫn đến tình trạng trang bị quá mức.

Hậu quả

Mô hình có thể trở nên quá phức tạp và không thể khái quát hóa tốt dữ liệu mới, dẫn đến hiệu suất kém bên ngoài tập huấn luyện.

Làm thế nào để giải quyết vấn đề này?

Thực hiện chính quy hóa, xác thực chéo, điều chỉnh siêu tham số. 

Công suất của mô hình là gì?

Năng lực của một mô hình đề cập đến kích thước và độ phức tạp của các mẫu mà nó có thể học. Đối với mạng lưới thần kinh, điều này phần lớn sẽ được xác định bởi số lượng tế bào thần kinh và cách chúng được kết nối với nhau. Nếu có vẻ như mạng của bạn chưa phù hợp với dữ liệu, bạn nên thử tăng dung lượng của mạng.

Bạn có thể tăng dung lượng của mạng bằng cách làm cho mạng rộng hơn (nhiều đơn vị hơn cho các lớp hiện có) hoặc bằng cách làm cho mạng sâu hơn (thêm nhiều lớp hơn). Các mạng rộng hơn có thời gian dễ dàng hơn để tìm hiểu các mối quan hệ tuyến tính hơn, trong khi các mạng sâu hơn thích các mối quan hệ phi tuyến hơn. Cái nào tốt hơn chỉ phụ thuộc vào tập dữ liệu.

Giải thích các đường cong học tập

Keras cung cấp khả năng đăng ký các cuộc gọi lại khi đào tạo một mô hình học sâu. Một trong những lệnh gọi lại mặc định được đăng ký khi đào tạo tất cả các mô hình học sâu là lệnh gọi lại Lịch sử. Nó ghi lại số liệu đào tạo cho từng kỷ nguyên. Điều này bao gồm sự mất mát và độ chính xác (đối với các vấn đề phân loại) cũng như sự mất mát và độ chính xác đối với tập dữ liệu xác thực nếu được đặt.

Đối tượng lịch sử được trả về từ các lệnh gọi tới hàm fit() dùng để huấn luyện mô hình. Số liệu được lưu trữ trong từ điển trong lịch sử thành viên của đối tượng được trả về.

Ví dụ: bạn có thể liệt kê các số liệu được thu thập trong một đối tượng lịch sử bằng cách sử dụng đoạn mã sau sau khi đào tạo mô hình:

# list all data in history
print(history.history.keys())

Đầu ra:

['độ chính xác', 'mất mát', 'val_chính xác', 'val_loss']

Loại thông tin

Bạn có thể nghĩ thông tin trong dữ liệu huấn luyện có hai loại:

  • Tín hiệu: Tín hiệu là phần khái quát hóa, phần có thể giúp mô hình của chúng ta đưa ra dự đoán từ dữ liệu mới.
  • Tiếng ồn: Tiếng ồn là phần chỉ đúng với dữ liệu huấn luyện; tiếng ồn là tất cả các biến động ngẫu nhiên đến từ dữ liệu trong thế giới thực hoặc tất cả các mẫu ngẫu nhiên, không mang tính thông tin thực sự không thể giúp mô hình đưa ra dự đoán. Tiếng ồn là bộ phận có thể trông hữu ích nhưng thực sự không phải vậy.

Khi đào tạo một mô hình, chúng tôi đã lập biểu đồ về sự mất mát trên tập huấn luyện theo từng kỷ nguyên. Để làm điều này, chúng tôi cũng sẽ thêm một biểu đồ dữ liệu xác thực. Chúng tôi gọi những đồ thị này là đường cong học tập. Để đào tạo các mô hình deep learning một cách hiệu quả, chúng ta cần có khả năng diễn giải chúng.

Đường cong học tập

Trong hình trên, chúng ta có thể thấy rằng tổn thất huấn luyện giảm khi các kỷ nguyên tăng lên, nhưng tổn thất xác thực ban đầu giảm và tăng khi mô hình bắt đầu thu được nhiễu có trong tập dữ liệu. Bây giờ chúng ta sẽ xem cách tránh trang bị quá mức trong ConvNets thông qua các kỹ thuật khác nhau. 

Các phương pháp tránh trang bị quá mức

Bây giờ chúng ta đã thấy một số tình huống và cách diễn giải đường cong học tập để phát hiện tình trạng trang bị quá mức. Hãy xem một số phương pháp để tránh trang bị quá mức trong mạng nơ-ron:

Phương pháp 1: Sử dụng nhiều dữ liệu hơn

Việc tăng kích thước tập dữ liệu của bạn có thể giúp mô hình khái quát hóa tốt hơn vì nó có nhiều ví dụ đa dạng hơn để học hỏi. Mô hình sẽ tìm các mẫu quan trọng có trong tập dữ liệu và bỏ qua nhiễu khi mô hình nhận ra các mẫu (nhiễu) cụ thể đó không có trong tất cả tập dữ liệu.

Phương pháp 2: Dừng sớm

Dừng sớm là một kỹ thuật được sử dụng để ngăn chặn việc trang bị quá mức bằng cách theo dõi hiệu suất của mô hình trên tập hợp xác thực trong quá trình đào tạo. Quá trình đào tạo bị dừng khi hiệu suất trên bộ xác thực bắt đầu suy giảm, cho thấy mô hình đang bắt đầu quá phù hợp. Thông thường, một bộ xác nhận riêng biệt được sử dụng để theo dõi hiệu suất và quá trình đào tạo sẽ bị dừng khi hiệu suất không được cải thiện trong một số kỷ nguyên được chỉ định.

Trang bị thiếu và trang bị quá mức

Phương pháp 3: Bỏ học

Chúng tôi biết rằng việc trang bị quá mức là do mạng học các mẫu (nhiễu) giả trong dữ liệu huấn luyện. Để nhận ra những mẫu giả này, mạng thường sẽ dựa vào sự kết hợp trọng số rất cụ thể, một loại “âm mưu” về trọng số. Quá cụ thể nên chúng có xu hướng mong manh: loại bỏ một cái và âm mưu sẽ tan vỡ.

Đây là ý tưởng đằng sau việc bỏ học. Để phá vỡ những âm mưu này, chúng tôi loại bỏ ngẫu nhiên một phần đơn vị đầu vào của lớp trong mỗi bước huấn luyện, khiến mạng khó tìm hiểu các mẫu giả đó trong dữ liệu huấn luyện hơn nhiều. Thay vào đó, nó phải tìm kiếm các mô hình chung, rộng, có mô hình trọng số có xu hướng mạnh mẽ hơn. 

Bạn cũng có thể coi việc bỏ học giống như việc tạo ra một loại mạng lưới. Các dự đoán sẽ không còn được thực hiện bởi một mạng lớn nữa mà thay vào đó là một ủy ban gồm các mạng nhỏ hơn. Các cá nhân trong ủy ban có xu hướng mắc nhiều loại sai lầm khác nhau, nhưng đồng thời họ cũng đúng, làm cho toàn thể ủy ban trở nên tốt hơn bất kỳ cá nhân nào. (Nếu bạn quen thuộc với các khu rừng ngẫu nhiên như một tập hợp các cây quyết định thì đó cũng là ý tưởng tương tự.)

Trang bị quá mức trong ConvNets

Phương pháp 4: Chuẩn hóa hàng loạt

Phương pháp đặc biệt tiếp theo mà chúng ta sẽ xem xét sẽ thực hiện “chuẩn hóa theo lô” (hoặc “chuẩn mực theo đợt”), có thể giúp điều chỉnh quá trình đào tạo chậm hoặc không ổn định.

Với mạng nơ-ron, nói chung, bạn nên đặt tất cả dữ liệu của mình theo một thang đo chung, có thể bằng thứ gì đó như StandardScaler hoặc MinMaxScaler của scikit-learn. Lý do là SGD sẽ thay đổi trọng số mạng tương ứng với mức độ kích hoạt mà dữ liệu tạo ra. Các tính năng có xu hướng tạo ra các kích hoạt có kích thước rất khác nhau có thể tạo ra hành vi huấn luyện không ổn định.

Bây giờ, nếu việc chuẩn hóa dữ liệu trước khi đưa vào mạng là tốt thì có lẽ việc chuẩn hóa trong mạng cũng sẽ tốt hơn! Trên thực tế, chúng ta có một loại lớp đặc biệt có thể thực hiện việc này, lớp chuẩn hóa hàng loạt. Lớp chuẩn hóa hàng loạt xem xét từng lô khi nó xuất hiện, đầu tiên chuẩn hóa lô với giá trị trung bình và độ lệch chuẩn riêng, sau đó cũng đưa dữ liệu lên một thang đo mới với hai tham số thay đổi tỷ lệ có thể huấn luyện được. Trên thực tế, Batchnorm thực hiện một kiểu điều chỉnh lại quy mô đầu vào của nó.

Thông thường, batchnorm được thêm vào để hỗ trợ quá trình tối ưu hóa (mặc dù đôi khi nó cũng có thể giúp dự đoán hiệu suất). Các mô hình có batchnorm có xu hướng cần ít kỷ nguyên hơn để hoàn thành quá trình đào tạo. Hơn nữa, batchnorm cũng có thể khắc phục nhiều vấn đề khác nhau có thể khiến quá trình đào tạo bị “kẹt”. Hãy cân nhắc thêm tính năng chuẩn hóa hàng loạt vào mô hình của bạn, đặc biệt nếu bạn gặp khó khăn trong quá trình đào tạo.

Phương pháp 5: Chính quy hóa L1 và L2

Chính quy hóa L1 và L2 là các kỹ thuật được sử dụng để ngăn chặn việc trang bị quá mức bằng cách xử phạt các trọng số lớn trong mạng lưới thần kinh. Chính quy hóa L1 thêm một số hạng phạt vào hàm mất mát tỷ lệ với giá trị tuyệt đối của các trọng số. Nó khuyến khích sự thưa thớt về trọng số và có thể dẫn đến việc lựa chọn tính năng. Chính quy hóa L2, còn được gọi là giảm trọng số, thêm một số hạng phạt tỷ lệ với bình phương của các trọng số vào hàm mất mát. Nó ngăn không cho trọng lượng trở nên quá lớn và khuyến khích việc phân bổ trọng lượng được trải đều hơn.

Sự lựa chọn giữa chính quy hóa L1 và L2 thường phụ thuộc vào vấn đề cụ thể và các thuộc tính mong muốn của mô hình.

Việc chính quy hóa L1/L2 có giá trị lớn sẽ khiến mô hình không học nhanh và đạt đến trạng thái ổn định trong quá trình học khiến mô hình không phù hợp. 

Phương pháp 6: Tăng cường dữ liệu

Cách tốt nhất để cải thiện hiệu suất của mô hình học máy là huấn luyện nó trên nhiều dữ liệu hơn. Mô hình càng phải học hỏi nhiều ví dụ thì càng có khả năng nhận ra sự khác biệt nào trong hình ảnh quan trọng và điểm nào không. Nhiều dữ liệu hơn giúp mô hình khái quát hóa tốt hơn.

Một cách dễ dàng để có thêm dữ liệu là sử dụng dữ liệu bạn đã có. Nếu chúng tôi có thể chuyển đổi hình ảnh trong tập dữ liệu của mình theo cách duy trì lớp (ví dụ: phân loại Chữ số MNIST nếu chúng tôi thử tăng thêm 6 thì sẽ khó phân biệt giữa 6 và 9), chúng tôi có thể dạy trình phân loại của mình bỏ qua các loại biến đổi đó. Ví dụ: việc ô tô quay mặt sang trái hay phải trong ảnh không làm thay đổi thực tế rằng đó là Ô tô chứ không phải Xe tải. Vì vậy, nếu chúng tôi tăng cường dữ liệu huấn luyện của mình bằng các hình ảnh bị lật, bộ phân loại của chúng tôi sẽ biết rằng “trái hoặc phải” là sự khác biệt mà nó nên bỏ qua.

Và đó là toàn bộ ý tưởng đằng sau việc tăng cường dữ liệu: thêm vào một số dữ liệu giả bổ sung trông khá giống dữ liệu thật và trình phân loại của bạn sẽ cải thiện. 

Hãy nhớ rằng, chìa khóa để tránh trang bị quá mức là đảm bảo mô hình của bạn có khả năng khái quát hóa tốt. Luôn kiểm tra hiệu suất mô hình của bạn trên tập xác thực, không chỉ tập huấn luyện.

Thực hiện các phương pháp trên với dữ liệu

Hãy cùng chúng tôi khám phá các bước thực hiện cho các phương pháp trên:

Bước 1: Tải các thư viện cần thiết

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras import datasets, layers, models
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.callbacks import ModelCheckpoint
import keras
from keras.preprocessing import image
from keras import models, layers, regularizers
from tqdm import tqdm
import warnings
warnings.filterwarnings(action='ignore')

Bước 2: Tải tập dữ liệu và tiền xử lý

#Here all the images are in the form of a numpy array
cifar10 = tf.keras.datasets.cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
x_train = x_train / 255.0
x_test = x_test / 255.0

Bước 3: Học tập dữ liệu

x_train.shape, y_train.shape, x_test.shape, y_test.shape 

Đầu ra:

Đầu ra
np.unique(y_train)

Đầu ra:

Đầu ra
#These labels are in the order and taken from the documentaion
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
               'dog', 'frog', 'horse', 'ship', 'truck']

Bước 4: Trực quan hóa hình ảnh từ bộ dữ liệu

def show_image(IMG_INDEX):
    plt.imshow(x_train[20] ,cmap=plt.cm.binary)
    plt.xlabel(class_names[y_train[IMG_INDEX][0]])
    plt.show()
show_image(20)
Trang bị quá mức trong ConvNets
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.AveragePooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.AveragePooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10))
model.summary()

Bây giờ chúng ta hãy Khởi tạo siêu tham số và biên dịch mô hình với trình tối ưu hóa, hàm mất mát và số liệu đánh giá.


train_hyperparameters_config={'optim':keras.optimizers.Adam(learning_rate=0.001),
                             'epochs':20,
                              'batch_size':16
                             }
model.compile(optimizer=train_hyperparameters_config['optim'],
                  loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                  metrics=['accuracy'])

Bước 6: Mô hình đào tạo

history = model.fit(x_train, y_train, 
                        epochs=train_hyperparameters_config['epochs'], 
                        batch_size=train_hyperparameters_config['batch_size'], 
                        verbose=1,
                        validation_data=(x_test, y_test))

Bước 7: Đánh giá mô hình

Những thứ này sẽ cho chúng ta biết thông tin có trong đối tượng lịch sử và chúng ta sử dụng những thông tin đó để tạo ra các đường cong thông tin của mình.

print(history.history.keys()) 
def learning_curves(history):
# Plotting Accuracy
    plt.figure(figsize=(14, 5))  # Adjust the figure size as needed
    plt.subplot(1, 2, 1)  # Subplot with 1 row, 2 columns, and index 1
    plt.plot(history.history['accuracy'], label='train_accuracy', marker='s', markersize=4)
    plt.plot(history.history['val_accuracy'], label='val_accuracy', marker='*', markersize=4)
    plt.xlabel('Epoch')
    plt.ylabel('Accuracy')
    plt.legend(loc='lower right')

    # Plotting Loss
    plt.subplot(1, 2, 2)  # Subplot with 1 row, 2 columns, and index 2
    plt.plot(history.history['loss'], label='train_loss', marker='s', markersize=4)
    plt.plot(history.history['val_loss'], label='val_loss', marker='*', markersize=4)
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    plt.legend(loc='lower right')

    plt.show()
learning_curves(history)
Trang bị quá mức trong ConvNets

Từ các đường cong, chúng ta có thể thấy rằng độ chính xác xác thực đạt đến mức ổn định sau kỷ nguyên thứ 4 và mô hình bắt đầu thu được nhiễu. Do đó, chúng tôi sẽ triển khai tính năng dừng sớm để tránh mô hình bị trang bị quá mức và khôi phục trọng số tốt nhất dựa trên val_loss. Chúng tôi sẽ sử dụng val_loss để theo dõi việc dừng sớm khi mạng thần kinh của chúng tôi cố gắng giảm tổn thất bằng cách sử dụng trình tối ưu hóa. Độ chính xác và độ chính xác của Xác thực phụ thuộc vào ngưỡng (Xác suất để phân tách các lớp - thường là 0.5 đối với phân loại nhị phân), vì vậy nếu tập dữ liệu của chúng tôi mất cân bằng thì chúng tôi sẽ lo lắng về việc mất trong hầu hết các trường hợp. 

Bước 8: Thực hiện dừng sớm

Vì chúng tôi không lo lắng về việc mô hình của mình sẽ quá phù hợp vì việc dừng sớm sẽ tránh cho mô hình của chúng tôi xảy ra. Đó là một lựa chọn tốt để chọn số lượng kỷ nguyên cao hơn và sự kiên nhẫn phù hợp. Bây giờ chúng ta sẽ sử dụng kiến ​​trúc mô hình tương tự và huấn luyện với lệnh gọi lại dừng sớm. 

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.AveragePooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.AveragePooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10))
model.summary()

# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 5,
    'epochs': 50,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)

def model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config):
    model.compile(optimizer=train_hyperparameters_config['optim'],
                      loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                      metrics=['accuracy'])
    ht = model.fit(x_train, y_train, 
                            epochs=train_hyperparameters_config['epochs'], 
                            batch_size=train_hyperparameters_config['batch_size'],
                            callbacks=[callback],
                            verbose=1,
                            validation_data=(x_test, y_test))
    return ht

ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)
learning_curves(ht)
Trang bị quá mức trong ConvNets

Để biết trọng lượng tốt nhất của chúng tôi mà mô hình đã thực hiện. 

print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Bước 9: Tăng độ phức tạp của mô hình

Vì mô hình của chúng tôi hoạt động không tốt và không phù hợp vì nó không thể thu thập đủ dữ liệu. Chúng ta nên tăng độ phức tạp của mô hình và đánh giá. 

model = models.Sequential()

model.add(layers.Conv2D(128, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(512, (3, 3), activation='relu', padding='same'))
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))
model.summary()
Đầu ra

Chúng ta có thể thấy có sự gia tăng trong tổng số thông số. Điều này sẽ giúp tìm ra các mối quan hệ phức tạp hơn trong mô hình của chúng tôi. Lưu ý: Tập dữ liệu của chúng tôi là hình ảnh 32X32; đây là những hình ảnh tương đối nhỏ. Do đó, việc sử dụng các mô hình phức tạp hơn ngay từ đầu chắc chắn sẽ quá phù hợp với mô hình, do đó chúng ta có xu hướng tăng độ phức tạp của mô hình một cách từ từ.

# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 5,
    'epochs': 50,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)
ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)

learning_curves(ht)
Trang bị quá mức trong ConvNets
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Từ các biểu đồ trên, chúng ta có thể nói rõ ràng rằng mô hình đang bị quá mức, do đó chúng ta sẽ sử dụng một phương pháp khác gọi là Chuẩn hóa loại bỏ và Chuẩn hóa hàng loạt.

Bước 10: Sử dụng các lớp bỏ học và các lớp chuẩn hóa hàng loạt

model = models.Sequential()

model.add(layers.Conv2D(128, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(512, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.3))

model.add(layers.Dense(128, activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.3))

model.add(layers.Dense(10, activation='softmax'))
model.summary()
Đầu ra
# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 5,
    'epochs': 50,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)
ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)
learning_curves(ht)
Trang bị quá mức trong ConvNets
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Từ các biểu đồ học tập, chúng ta có thể thấy rằng mô hình đang bị quá mức ngay cả với các lớp chuẩn hóa hàng loạt và lớp bỏ học. Do đó thay vì tăng độ phức tạp mà tăng số lượng bộ lọc. Chúng tôi sẽ thêm nhiều lớp chập hơn để trích xuất nhiều tính năng hơn.

Bước 11: Tăng các lớp chập

Giảm tham số có thể huấn luyện nhưng tăng các lớp tích chập để trích xuất nhiều tính năng hơn.

model = models.Sequential()

model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(32, 32, 3)))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.2))

model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.3))

model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.4))

model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.5))

model.add(layers.Dense(10, activation='softmax'))

model.summary()
# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 5,
    'epochs': 50,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)
ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)
đầu ra
learning_curves(ht)
Trang bị quá mức trong ConvNets
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Từ kết quả đầu ra và đường cong học tập ở trên, chúng ta có thể suy ra rằng mô hình đã hoạt động rất tốt và tránh được tình trạng quá khớp. Độ chính xác đào tạo và độ chính xác xác nhận là rất gần. Trong trường hợp này, chúng ta sẽ không cần thêm phương pháp nào để giảm tình trạng trang bị quá mức. Tuy nhiên, chúng ta sẽ khám phá chính quy hóa L1/L2. 

Bước 12: Sử dụng chính quy L1/L2

from tensorflow.keras import regularizers

model = models.Sequential()

model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(32, 32, 3)))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same', kernel_regularizer=regularizers.l1(0.0005)))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.2))

model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same', kernel_regularizer=regularizers.l2(0.0005)))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.3))

model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.4))

model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu', kernel_regularizer=regularizers.l1_l2(0.0005, 0.0005)))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.5))
model.add(layers.Dense(10, activation='softmax'))

model.summary()
# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 7,
    'epochs': 70,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)
ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)
learning_curves(ht)
Trang bị quá mức trong ConvNets
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Bây giờ chúng ta có thể thấy rằng việc chính quy hóa L1/L2 ngay cả sau khi sử dụng điểm phạt thấp là 0.0001, đã khiến mô hình của chúng tôi không phù hợp tới 4%. Do đó, nên thận trọng sử dụng tất cả các phương pháp cùng nhau. Vì Chuẩn hóa và Chính quy hóa hàng loạt ảnh hưởng đến mô hình theo cách tương tự nên chúng tôi sẽ không cần chính quy hóa L1/L2. 

Bước 13: Tăng cường dữ liệu

Chúng tôi sẽ sử dụng ImageDataGenerator từ máy ảnh tensorflow.

# creates a data generator object that transforms images
datagen = ImageDataGenerator(
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')

# pick an image to transform
test_img = x_train[20]
img = image.img_to_array(test_img)  # convert image to numpy arry
img = img.reshape((1,) + img.shape)  # reshape image

i = 0

for batch in datagen.flow(img, save_prefix='test', save_format='jpeg'):  # this loops runs forever until we break, saving images to current directory with specified prefix
    plt.figure(i)
    plot = plt.imshow(image.img_to_array(batch[0]))
    i += 1
    if i > 4:  # show 4 images
        break

plt.show()
Trang bị quá mức trong ConvNets

Đây là bốn hình ảnh tăng cường và một hình ảnh gốc.

# Create an instance of the ImageDataGenerator
datagen = ImageDataGenerator(
    rotation_range=40,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,
    fill_mode='nearest'
)

# Create an iterator for the data generator
data_generator = datagen.flow(x_train, y_train, batch_size=32)

# Create empty lists to store the augmented images and labels
augmented_images = []
augmented_labels = []

# Loop over the data generator and append the augmented data to the lists
num_batches = len(x_train) // 32
progress_bar = tqdm(total=num_batches, desc="Augmenting data", unit="batch")

for i in range(num_batches):
    batch_images, batch_labels = next(data_generator)
    augmented_images.append(batch_images)
    augmented_labels.append(batch_labels)
    progress_bar.update(1)

progress_bar.close()

# Convert the lists to NumPy arrays
augmented_images = np.concatenate(augmented_images, axis=0)
augmented_labels = np.concatenate(augmented_labels, axis=0)

# Combine the original and augmented data
x_train_augmented = np.concatenate((x_train, augmented_images), axis=0)
y_train_augmented = np.concatenate((y_train, augmented_labels), axis=0)
đầu ra

Chúng tôi đã sử dụng thư viện tqdm để biết tiến trình mở rộng của chúng tôi.

x_train_augmented.shape, y_train_augmented.shape
Đầu ra

Đây là tập dữ liệu của chúng tôi sau khi tăng cường. Bây giờ hãy sử dụng tập dữ liệu này và huấn luyện mô hình của chúng tôi.

model = models.Sequential()

model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(32, 32, 3)))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.2))

model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.3))

model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.4))

model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.5))

model.add(layers.Dense(10, activation='softmax'))

model.summary()

# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 10,
    'epochs': 70,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)

ht=model_train(model, x_train_augmented, y_train_augmented, x_test, y_test, train_hyperparameters_config)


learning_curves(ht)
Trang bị quá mức trong ConvNets
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Chúng ta có thể thấy mô hình được khái quát hơn và tổn thất giảm đi. Chúng tôi cũng đã có được độ chính xác xác thực tốt hơn. Do đó việc tăng cường dữ liệu đã làm tăng độ chính xác của mô hình của chúng tôi. 

Kết luận

Trang bị quá mức là một vấn đề phổ biến trong học sâu, đặc biệt là với các kiến ​​trúc mạng thần kinh phức tạp như ConvNets. Những người thực hành có thể ngăn chặn tình trạng trang bị quá mức trong ConvNets bằng cách hiểu nguyên nhân cốt lõi của nó và nhận ra các tình huống xảy ra. Các kỹ thuật như dừng sớm, bỏ học, chuẩn hóa hàng loạt, chính quy hóa và tăng cường dữ liệu có thể giúp giảm thiểu vấn đề này. Việc triển khai các kỹ thuật này trên bộ dữ liệu CIFAR-10 cho thấy những cải thiện đáng kể về hiệu suất và tổng quát hóa mô hình. Nắm vững các kỹ thuật này và hiểu nguyên tắc của chúng có thể dẫn đến các mô hình mạng lưới thần kinh mạnh mẽ và đáng tin cậy.

Những câu hỏi thường gặp

Q1. Overfitting là gì và tại sao nó lại là vấn đề trong deep learning? 

A. Quá khớp xảy ra khi một mô hình học dữ liệu huấn luyện quá tốt, bao gồm cả các mẫu nhiễu và không liên quan, dẫn đến hiệu suất kém trên dữ liệu mới, chưa được nhìn thấy. Đó là một vấn đề vì các mô hình được trang bị quá mức không thể khái quát hóa một cách hiệu quả, hạn chế tiện ích thực tế của chúng.

Q2. Làm cách nào tôi có thể phát hiện tình trạng trang bị quá mức trong mô hình mạng thần kinh của mình?

Đáp. Bạn có thể phát hiện tình trạng trang bị quá mức trong ConvNets bằng cách diễn giải các đường cong học tập, biểu thị các số liệu đào tạo và xác thực (ví dụ: mất mát, độ chính xác) qua các kỷ nguyên. Nếu các chỉ số xác thực ngừng cải thiện hoặc bắt đầu xuống cấp trong khi các chỉ số đào tạo tiếp tục cải thiện thì đó là dấu hiệu của việc trang bị quá mức.

Q3. Dừng sớm là gì và nó giúp ngăn chặn việc trang bị quá mức như thế nào?

A. Dừng sớm là một kỹ thuật giám sát hiệu suất của mô hình trên tập xác thực trong quá trình đào tạo và dừng quá trình huấn luyện khi hiệu suất trên tập xác thực bắt đầu giảm, biểu thị quá mức. Nó giúp ngăn chặn mô hình bị trang bị quá mức bằng cách dừng quá trình đào tạo vào đúng thời điểm.

Q4. Việc tăng cường dữ liệu giúp giảm thiểu tình trạng trang bị quá mức như thế nào? 

A. Tăng cường dữ liệu là quá trình tạo ra dữ liệu đào tạo tổng hợp mới bằng cách áp dụng các phép biến đổi (ví dụ: lật, xoay, chia tỷ lệ) cho dữ liệu hiện có. Nó giúp mô hình khái quát hóa tốt hơn bằng cách hiển thị mô hình với các ví dụ đa dạng hơn, giảm nguy cơ trang bị quá mức trong ConvNets cho dữ liệu đào tạo hạn chế.

tại chỗ_img

Tin tức mới nhất

tại chỗ_img