Tìm hiểu cách sử dụng Random Forest, một thuật toán học tổng hợp mạnh mẽ, để phân loại hình ảnh bằng OpenCV và Python.
Chủ đề xung quanh thuật toán Rừng ngẫu nhiên đã được Jason Brownlee giải thích rõ ràng trong các hướng dẫn này [1, 2], nhưng trước tiên hãy bắt đầu bằng việc tóm tắt một số điểm quan trọng nhất:
Trước tiên, chúng ta sẽ sử dụng tập dữ liệu tiền giấy được sử dụng trong hướng dẫn này.
Bộ dữ liệu tiền giấy là một bộ dữ liệu tương đối đơn giản liên quan đến việc dự đoán tính xác thực của một tờ tiền nhất định. Tập dữ liệu chứa 1.372 hàng, mỗi hàng biểu thị một vectơ đặc trưng bao gồm bốn số đo khác nhau được trích xuất từ ảnh tiền giấy, cộng với nhãn lớp tương ứng của nó (xác thực hoặc không).
Các giá trị trong mỗi vectơ đặc trưng tương ứng như sau:
Có thể tải xuống tập dữ liệu từ Kho lưu trữ máy học UCI.
Như trong hướng dẫn của Jason, chúng ta sẽ tải tập dữ liệu, chuyển đổi số chuỗi của nó thành số float và phân chia nó thành các tập huấn luyện và kiểm tra:
# Function to load the dataset
def load_csv(filename):
file = open(filename, "rt")
lines = reader(file)
dataset = list(lines)
return dataset
# Function to convert a string column to float
def str_column_to_float(dataset, column):
for row in dataset:
row[column] = float32(row[column].strip())
# Load the dataset from text file
data = load_csv('Data/data_banknote_authentication.txt')
# Convert the dataset string numbers to float
for i in range(len(data[0])):
str_column_to_float(data, i)
# Convert list to array
data = array(data)
# Separate the dataset samples from the ground truth
samples = data[:, :4]
target = data[:, -1, newaxis].astype(int32)
# Split the data into training and testing sets
x_train, x_test, y_train, y_test = ms.train_test_split(samples, target, test_size=0.2, random_state=10)
Thư viện OpenCV triển khai hàm RTrees_create trong mô-đun ml, hàm này sẽ cho phép chúng ta tạo một cây quyết định trống:
# Create an empty decision tree
rtree = ml.RTrees_create()
Tất cả các cây trong rừng sẽ được huấn luyện với cùng các giá trị tham số, mặc dù trên các tập con khác nhau của tập dữ liệu huấn luyện. Các giá trị tham số mặc định có thể được tùy chỉnh, nhưng trước tiên hãy làm việc với cách triển khai mặc định. Chúng ta sẽ sớm quay lại việc tùy chỉnh các giá trị tham số này trong phần tiếp theo:
# Train the decision tree
rtree.train(x_train, ml.ROW_SAMPLE, y_train)
# Predict the target labels of the testing data
_, y_pred = rtree.predict(x_test)
# Compute and print the achieved accuracy
accuracy = (sum(y_pred.astype(int32) == y_test) / y_test.size) * 100
print('Accuracy:', accuracy[0], '%')
Accuracy: 96.72727272727273 %
Chúng tôi đã đạt được độ chính xác cao khoảng 96,73% bằng cách sử dụng triển khai mặc định thuật toán Rừng ngẫu nhiên trên tập dữ liệu tiền giấy.
Danh sách mã đầy đủ như sau:
from csv import reader
from numpy import array, float32, int32, newaxis
from cv2 import ml
from sklearn import model_selection as ms
# Function to load the dataset
def load_csv(filename):
file = open(filename, "rt")
lines = reader(file)
dataset = list(lines)
return dataset
# Function to convert a string column to float
def str_column_to_float(dataset, column):
for row in dataset:
row[column] = float32(row[column].strip())
# Load the dataset from text file
data = load_csv('Data/data_banknote_authentication.txt')
# Convert the dataset string numbers to float
for i in range(len(data[0])):
str_column_to_float(data, i)
# Convert list to array
data = array(data)
# Separate the dataset samples from the ground truth
samples = data[:, :4]
target = data[:, -1, newaxis].astype(int32)
# Split the data into training and testing sets
x_train, x_test, y_train, y_test = ms.train_test_split(samples, target, test_size=0.2, random_state=10)
# Create an empty decision tree
rtree = ml.RTrees_create()
# Train the decision tree
rtree.train(x_train, ml.ROW_SAMPLE, y_train)
# Predict the target labels of the testing data
_, y_pred = rtree.predict(x_test)
# Compute and print the achieved accuracy
accuracy = (sum(y_pred.astype(int32) == y_test) / y_test.size) * 100
print('Accuracy:', accuracy[0], '%')
Hãy cân nhắc việc áp dụng Rừng ngẫu nhiên cho các hình ảnh từ tập dữ liệu chữ số của OpenCV.
Tập dữ liệu chữ số vẫn còn tương đối đơn giản. Tuy nhiên, các vectơ đặc trưng mà chúng tôi sẽ trích xuất từ hình ảnh của nó bằng phương pháp HOG sẽ có số chiều cao hơn (81 đặc điểm) so với các vectơ trong tập dữ liệu tiền giấy. Vì lý do này, chúng ta có thể coi tập dữ liệu chữ số tương đối khó làm việc hơn so với tập dữ liệu tiền giấy.
Trước tiên, chúng tôi sẽ điều tra cách triển khai mặc định của thuật toán Rừng ngẫu nhiên đối phó với dữ liệu có chiều cao hơn:
from digits_dataset import split_images, split_data
from feature_extraction import hog_descriptors
from numpy import array, float32
from cv2 import ml
# Load the digits image
img, sub_imgs = split_images('Images/digits.png', 20)
# Obtain training and testing datasets from the digits image
digits_train_imgs, digits_train_labels, digits_test_imgs, digits_test_labels = split_data(20, sub_imgs, 0.8)
# Convert the image data into HOG descriptors
digits_train_hog = hog_descriptors(digits_train_imgs)
digits_test_hog = hog_descriptors(digits_test_imgs)
# Create an empty decision tree
rtree_digits = ml.RTrees_create()
# Predict the target labels of the testing data
_, digits_test_pred = rtree_digits.predict(digits_test_hog)
# Compute and print the achieved accuracy
accuracy_digits = (sum(digits_test_pred.astype(int) == digits_test_labels) / digits_test_labels.size) * 100
print('Accuracy:', accuracy_digits[0], '%')
Accuracy: 81.0 %
Chúng tôi thấy rằng việc triển khai mặc định trả về độ chính xác là 81%.
Sự giảm độ chính xác này so với mức đạt được trên tập dữ liệu tiền giấy có thể cho thấy rằng khả năng triển khai mặc định của mô hình có thể không đủ để tìm hiểu mức độ phức tạp của dữ liệu nhiều chiều hơn mà chúng tôi hiện đang làm việc.
Hãy điều tra xem liệu chúng ta có thể cải thiện độ chính xác hay không bằng cách thay đổi:
Khi điều chỉnh các tham số trên, hãy nhớ rằng việc tăng số lượng cây có thể tăng khả năng của mô hình trong việc nắm bắt được nhiều chi tiết phức tạp hơn trong dữ liệu huấn luyện; nó cũng sẽ tăng thời gian dự đoán một cách tuyến tính và làm cho mô hình dễ bị khớp quá mức. Do đó, hãy điều chỉnh các thông số một cách thận trọng.
Nếu chúng ta thêm vào các dòng sau sau khi tạo cây quyết định trống, chúng ta có thể tìm thấy các giá trị mặc định của độ sâu của cây cũng như các tiêu chí kết thúc:
print('Default tree depth:', rtree_digits.getMaxDepth())
print('Default termination criteria:', rtree_digits.getTermCriteria())
Default tree depth: 5
Default termination criteria: (3, 50, 0.1)
Theo cách này, chúng ta có thể thấy rằng, theo mặc định, mỗi cây trong rừng có độ sâu (hoặc số cấp) bằng 5, trong khi số lượng cây và độ chính xác mong muốn được đặt thành 50 và 0,1, tương ứng. Giá trị đầu tiên được trả về bởi phương thức getTermCriteria đề cập đến type của tiêu chí chấm dứt đang được xem xét, trong đó giá trị 3 chỉ định việc chấm dứt dựa trên cả TERM_CRITERIA_MAX_ITER và TERM_CRITERIA_EPS.
Bây giờ hãy thử thay đổi các giá trị được đề cập ở trên để điều tra ảnh hưởng của chúng đến độ chính xác của dự đoán. Danh sách mã như sau:
from digits_dataset import split_images, split_data
from feature_extraction import hog_descriptors
from numpy import array, float32
from cv2 import ml, TERM_CRITERIA_MAX_ITER, TERM_CRITERIA_EPS
# Load the digits image
img, sub_imgs = split_images('Images/digits.png', 20)
# Obtain training and testing datasets from the digits image
digits_train_imgs, digits_train_labels, digits_test_imgs, digits_test_labels = split_data(20, sub_imgs, 0.8)
# Convert the image data into HOG descriptors
digits_train_hog = hog_descriptors(digits_train_imgs)
digits_test_hog = hog_descriptors(digits_test_imgs)
# Create an empty decision tree
rtree_digits = ml.RTrees_create()
# Read the default parameter values
print('Default tree depth:', rtree_digits.getMaxDepth())
print('Default termination criteria:', rtree_digits.getTermCriteria())
# Change the default parameter values
rtree_digits.setMaxDepth(15)
rtree_digits.setTermCriteria((TERM_CRITERIA_MAX_ITER + TERM_CRITERIA_EPS, 100, 0.01))
# Train the decision tree
rtree_digits.train(digits_train_hog.astype(float32), ml.ROW_SAMPLE, digits_train_labels)
# Predict the target labels of the testing data
_, digits_test_pred = rtree_digits.predict(digits_test_hog)
# Compute and print the achieved accuracy
accuracy_digits = (sum(digits_test_pred.astype(int) == digits_test_labels) / digits_test_labels.size) * 100
print('Accuracy:', accuracy_digits[0], ‘%')
Accuracy: 94.1 %
Chúng ta có thể thấy rằng các giá trị tham số mới được đặt sẽ nâng độ chính xác của dự đoán lên 94,1%.
Các giá trị tham số này đang được đặt tùy ý ở đây để minh họa cho ví dụ này. Tuy nhiên, chúng tôi luôn khuyên bạn nên thực hiện một cách tiếp cận có hệ thống hơn để điều chỉnh các tham số của mô hình và điều tra xem mỗi tham số ảnh hưởng đến hiệu suất của nó như thế nào.