Theo đà phát triển của công nghệ, ứng dụng trí tuệ nhân tạo luôn là xu hướng công nghệ tương lai mà các hãng công nghệ trên toàn thế giới đua nhau sáng tạo, nó là nền tảng cốt lõi của cu
Giới thiệu đề tài
Lý do chọn đề tài
Như ta đã biết, thời đại hiện nay là thời đại internet, là thời đại của sự bùng nổ thông tin, khi mà tất cả mọi người trên thế giới đều sống trên một thế giới phẳng, đặc biệt là hiện nay khi đang diễn ra cuộc cách mạng công nghiệp 4.0 thì lượng thông tin ngày càng nhiều, việc phân loại chúng trở nên khó khăn Ở bất kỳ một tổ chức nào, với bất kỳ một mô hình hay quy mô nào cũng đều có những nhu cầu về lưu trữ và khai thác thông tin Đã có nhiều hệ thống phân loại tin tức để ra quyết định.
Việc phân loại tin tức đã đem lại nhiều thành tựu nhất định, cụ thể như:
• Xác định được xu thế của cộng đồng mạng khí mà cộng đồng này chiếm ngày càng đông trong xã hội, qua đó xác định được xu thế về mặt ngắn hạn của xã hội, hỗ trợ cho người sử dụng đưa ra các quyết định phù hợp.
• Việc phân loại tin tức cũng được ứng dụng trên các website thương mại nhằm nắm bắt được xu thế tiêu dùng của người sử dụng.
Một trong những thuật toán để ứng dụng công việc ứng dụng trong nhận diện khuôn mặt là xác định khuôn mặt đó là thuật toán SVM – Support Vector Machine.
Thuật toán này có ưu điểm: Xử lý trên không gian số chiều cao: SVM là một công cụ tính toán hiệu quả trong không gian chiều cao, trong đó đặc biệt áp dụng cho các bài toán phân loại văn bản và phân tích quan điểm nơi chiều có thể cực kỳ lớn.Tiết kiệm bộ nhớ.
Vai trò và ý nghĩa của đề tài
Mục đích nghiên cứu của đề tài
Nghiên cứu và đề xuất các phương pháp phân loại văn bản theo chủ đề dựa trên thuật toán SVM – Support Vector Machine.
- Tích hợp các giải pháp ứng dụng vào một hệ thống và đánh giá hiệu quả. Ý nghĩa khoa học thực tiễn của đề tài
- Đóng góp về mặt phương pháp luận và thực nghiệm vào lĩnh vực phân loại văn bản, một nhánh nghiên cứu của xử lý ngôn ngữ tự nhiên.
- Cải tiến chất lượng hệ thống phân loại văn bản hiện có để nâng cao quản lý xu thế của tin tức.
Mục tiêu và nhiệm vụ
- Mục tiêu chính của đề tài là Ứng dụng thuật toán SVM – Support Vector Machine vào hệ thống để xác định khuôn mặt.
- Nghiên cứu và cải thiện thuật toán SVM trong hệ thống phân loại tin tức. Nhiệm vụ:
- Thu thập dữ liệu mẫu.
- Nghiên cứu các phương pháp xác định khuôn mặt
- Phát biểu, phân tích và cài đặt giải thuật cho bài toán.
Mô hình SVM (Support Vector Machine)
Khái niệm
SVM là một thuật toán giám sát, nó có thể sử dụng cho cả việc phân loại hoặc đệ quy Tuy nhiên nó được sử dụng chủ yếu cho việc phân loại Trong thuật toán này, chúng ta vẽ đồi thị dữ liệu là các điểm trong n chiều ( ở đây n là số lượng các tính năng bạn có) với giá trị của mỗi tính năng sẽ là một phần liên kết Sau đó chúng ta thực hiện tìm "đường bay" (hyper-plane) phân chia các lớp Hyper-plane nó chỉ hiểu đơn giản là 1 đường thẳng có thể phân chia các lớp ra thành hai phần riêng biệt.
Hình 2.1.1 Mô tả khái niệm SVMSupport Vectors hiểu một cách đơn giản là các đối tượng trên đồ thị tọa độ quan sát, Support Vector Machine là một biên giới để chia hai lớp tốt nhất.
Lý thuyết
2.2.1 Bài toán tối ưu cho SVM
Giả sử rằng các cặp dữ liệu của training set là (x1,y1),(x2,y2),…,(xN,yN) (x1,y1),(x2,y2),…,(xN,yN) với vector xi ∈Rd thể hiện đầu vào của một điểm dữ liệu và yi là nhãn của điểm dữ liệu đó d là số chiều của dữ liệu và N là số điểm dữ liệu Giả sử rằng nhãn của mỗi điểm dữ liệu được xác định bởi yi= 1 (class 1) hoặc yi= −1 (class 2) giống như trong PLA.
Hình 2.2.1 Minh họa SVM với cặp dữ liệu training Giả sử rằng các điểm vuông xanh thuộc class 1, các điểm tròn đỏ thuộc class -1 và mặt wTx+b=w1x1+w2x2+b= 0 là mặt phân chia giữa hai classes Hơn nữa, class 1 nằm về phía dương, class -1 nằm về phía âm của mặt phân chia Nếu ngược lại, ta chỉ cần đổi dấu của w và b Chú ý rằng chúng ta cần đi tìm các hệ số w và b.
Ta quan sát thấy một điểm quan trọng sau đây: với cặp dữ liệu (xn,yn) bất kỳ, khoảng cách từ điểm đó tới mặt phân chia là: Điều này có thể dễ nhận thấy vì theo giả sử ở trên, yn luôn cùng dấu với phía của xnxn Từ đó suy ra ynyn cùng dấu với (wTxn+b), và tử số luôn là 1 số không âm.
Với mặt phần chia như trên, margin được tính là khoảng cách gần nhất từ 1 điểm tới mặt đó (bất kể điểm nào trong hai classes):
Margin = min Bài toán tối ưu trong SVM chính là bài toán tìm w và b sao cho margin này đạt giá trị lớn nhất :
(w,b) = arg max (w,b) {min } = arg max(w,b) {minYn (wTxn+b)}(1)
Việc giải trực tiếp bài toán này sẽ rất phức tạp, nhưng các bạn sẽ thấy có cách để đưa nó về bài toán đơn giản hơn.
Nhận xét quan trọng nhất là nếu ta thay hệ số w bởi kw và b bởi kb trong đó k là một hằng số dương thì mặt phân chia không thay đổi, tức khoảng cách từ từng điểm đến mặt phân chia không đổi, tức margin không đổi Dựa trên tính chất này, ta có thể giả sử:
Yn(wTxn+b)=1 Với những điểm nằm gần mặt phân chia nhất như hình dưới đây :
Hình 2.2.2 Minh họa SVM những điểm gần mặt phân chia nhất
Như vậy, với mọi n, ta có :
Yn (wTxn + b)>=1 Vậy bài toán tối ưu (1) có thể đưa về bài toán tối ưu có ràng buộc sau đây:
(w,b) = arg max(w,b) subject to :Yn(wTxn+b)≥1, ∀n=1,2,…,N(2) Bằng 1 biến đổi đơn giản ,ta có thể đưa bài toán này về bài toán dưới đây:
(w,b) = arg min(w,b) ||w||2 subject to: 1-yn(wTxn + b)≤0, ∀n=1,2,…,N
(3) Ở đây, chúng ta đã lấy nghịch đảo hàm mục tiêu, bình phương nó để được một hàm khả vi, và nhân với 1212 để biểu thức đạo hàm đẹp hơn.
Xác định class cho một điểm dữ liệu mới: Sau khi tìm được mặt phân cách wTx+b=0; wTx+b=0, class của bất kỳ một điểm nào sẽ được xác định đơn giản bằng cách:
Class(x) = sgn(wTx+b) Trong đó hàm sgn là hàm xác định dấu ,nhận giá trị 1 nếu đối số không âm và -1 nếu ngược lại.
Hình 2.2.3 Margin trong SVM Margin là khoảng cách giữa siêu phẳng đến 2 điểm dữ liệu gần nhất tương ứng với các phân lớp Trong ví dụ quả táo quả lê đặt trên mặt bán, margin chính là khoảng cách giữa cây que và hai quả táo và lê gần nó nhất Điều quan trọng ở đây đó là phương pháp SVM luôn cố gắng cực đại hóa margin này, từ đó thu được một siêu phẳng tạo khoảng cách xa nhất so với 2 quả táo và lê
Nhờ vậy,SVM có thể giảm thiểu việc phân lớp sai (misclassification) đối với điểm dữ liệu mới đưa vào.
Phép phân tích thành phần chính (Principal Components Analysis - PCA) là một thuật toán thống kê sử dụng cho phép biến đổi trực tiếp giao để biến một tập hợp dữ liệu từ một không gian nhiều chiều sang một không gian mới ít chiều hơn (2 hoặc
3) Chiều tối ưu hóa khả năng thể hiện sự biến thiên của dữ liệu
Phương pháp PCA cho nhận dạng mặt (eigenface): Mỗi ảnh có kích thước WxH (kích thước phổ biến là 128 × 128) sẽ được chuyển thành một vector cột có độ dài W*H (cho cả tập training và probe) (gọi là các vector Xi) Ở bước training, một vector trung bình của tất cả các ảnh training sẽ được tính (vector M), sau đó mỗi vector thuộc tập training sẽ bị mean-subtracted: Xi=Xi-M, ma trận hiệp phương sai được tính bằng
C = A’*A, trong đó A’ là ma trận chuyển vị của A và A = [X1, X2, …Xk] là ma trận với các cột là các vector Xi, k là số ảnh thuộc tập training (k@*n với CSDL ORL) A sẽ có kích thước là (W*H)xk, còn ma trận C sẽ có kích thước là kxk, do k nhỏ hơn W*H rất nhiều nên việc tính k vector riêng (eigenvectors) và giá trị riêng tương ứng (eigenvalues) của C là dễ Ta sẽ tìm được k giá trị riêng tương ứng với k vector riêng của C Các vector riêng được sắp xếp theo thứ tự giảm dần của các giá trị riêng tương ứng, việc sử dụng tất cả các vector riêng là không cần thiết nên chỉ có N (N viết hoa nhé) giá trị riêng đầu tiên tương ứng với N vector riêng được sử dụng (chính về thế nên phương pháp này được gọi là phân tích thành phần chính-Principal
Component Analysis) N vector riêng này sẽ tạo thành một ma trận có kích thước
(W*H)xN là ma trận của không gian con nhận được (ta gọi ma trận này là Cp) Tiếp đến các ảnh thuộc tập training (ở đây cũng là tập reference) sẽ được chiếu vào không gian con bằng phép nhân: Ap = Cp’ * A, tương tự các ảnh của tập probe sẽ được chiếu vào không gian con bằng phép nhân: Bp = Cp’*B Ap và Bp sẽ có kích thước tương ứng là NxNoTrain (NoTrain là số ảnh training, tức là bằng k) và Nx NoTest (NoTest là số ảnh của tập probe), nghĩa là mỗi ảnh tương ứng được biểu diễn bằng một vector cột Ở bước phân lớp, với mỗi ảnh thuộc tập probe, ta tìm ảnh thuộc tập training gần với nó nhất Ở bước này các hàm khoảng cách: euclidean, mahalanobis, cosine angle distance đều có thể sử dụng.
Thực chất, ở nguyên bản của phương pháp PCA ma trận C = A*A’, và có kích thước là (W*H)x(W*H), tức là một ma trận rất, rất lớn nên Mathew A Turk and Alex
P Pentland (tác giả của phương pháp eigenface) đã sử dụng một thủ thuật là tìm N vector riêng vi (i=1 N) và giá trị riêng của ma trận L=A’*A (dễ hơn do ma trận có kích thước nhỏ hơn) sau đó tính N vector riêng của C=A*A’ bằng công thức ui=A*vi.
Việc tìm các vector riêng của ma trận hiệp phương sai C (trên thực tế là với ma trận L) có hai cách: dùng phương pháp eigen decomposition (hàm eig của matlab) hoặc singular value decomposition-SVD (hàm svd của matlab), tuy nhiên svd có vẻ nhanh và cho kết quả tốt hơn so với eig.
Sau đây là bảng tỉ lệ kết quả nhận dạng (Rank-1 Recognition Rate-RR) với số ảnh huấn luyện cho mỗi đối tượng:
Số ảnh huấn luyện của mỗi đối tượng
Số ảnh nhận dạng của mỗi đối tượng
Tỉ lệ nhận dạng đúng
Kết quả thực nghiệm
Dữ liệu
- Dữ liệu đầu vào gồm 3 ảnh thành viên
Các thuật toán chạy chương trình
3.2.1 Thư viện chương trình và đọc đường dẫn đến dữ liệu ảnh
Thư viện đồ hoạ: cv2
Thư viện hệ thống: os
Thư viện toán học: numpy
Thư viện thuật toán học máy: sklearn
Nối đường dẫn đến folder “dataset/”
Trích xuất phần đặc trưng của tệp hình ảnh. data_slice = [70,195,78,172]
Thay đổi kích thước tỷ lệ để giảm kích thước mẫu. resize_ratio = 2.5
Thiết lập chiều cao (h) và chiều rộng (w) của hình ảnh. h = int((data_slice[1] - data_slice[0])/resize_ratio) w = int((data_slice[3] - data_slice[2])/resize_ratio) print("Image dimension after resize (h,w) :", h, w) n_sample = 0 #Số lượng mẫu ban đầu label_count = 0 #Số lượng nhãn ban đầu n_classes = 0 #Số lớp ban đầu
3.2.2 Đọc dữ liệu ảnh và trả về tất cả dữ liệu
#Hình ảnh phẳng Feature Vector
Y=[] target_names = [] #Mảng để lưu trữ tên của mỗi người for directory in os.listdir(path): for file in os.listdir(path+directory): img=cv2.imread(path+directory+"/"+file)
[data_slice[0]:data_slice[1], data_slice[2]:data_slice[3]] img=cv2.resize(img, (w,h)) img=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) featurevector=numpy.array(img).flatten()
Y.append(label_count) n_sample = n_sample + 1 target_names.append(directory) label_count=label_count+1
Thực hiện đọc file ảnh của từng người:
Hàm imread tải một hình ảnh từ tệp đã chỉ định và trả về nó.
Hàm resize thay đổi kích thước hình ảnh src đến kích thước đã chỉ định.
Hàm cvtColor chuyển đổi một hình ảnh đầu vào từ không gian màu ban đầu sang không gian màu BGR2GRAY (Dạng màu xám hoặc trắng đen).
X.append(featurevector) #Nối đối tượng vào cuối danh sách
Y.append(label_count) #Danh sách đối tượng đã được duyệt qua
Thực hiện đếm số lượng hình ảnh có trong thư mục được nối đến là “dataset/”. target_names.append(directory) label_count=label_count+1 Đưa ra tên đối tượng có tên là tên của thư mục. n_classes = len(target_names) # Chiều dài của mảng tên người
3.2.3 Chia thành tập huấn luyện và tập kiểm tra
Tách thành một tập huấn luyện và một tập kiểm tra bằng cách sử dụng k lần phân tầng.
X_train, X_test, y_train, y_test = train_test_split(
Tính toán PCA (Principal Components Analysis) trên tập dữ liệu khuôn mặt (được coi là tập dữ liệu chưa được gắn nhãn): trích xuất tính năng / giảm kích thước không được giám sát. print("Extracting the top %d eigenfaces from %d faces"
% (n_components, len(X_train))) t0 = time() pca = PCA(n_components=n_components, whiten=True).fit(X_train) print("done in %0.3fs" % (time() - t0)) eigenfaces = pca.components_.reshape((n_components, h, w))
Chiếu dữ liệu đầu vào trên cơ sở trực giao. t0 = time()
X_train_pca = pca.transform(X_train)
X_test_pca = pca.transform(X_test) print("done in %0.3fs" % (time() - t0))
3.2.4 Chức năng trợ giúp để vẽ một bộ sưu tập chân dung
Khai báo thư viện đồ thị plt import matplotlib.pyplot as plt
Tạo một hình mới hoặc kích hoạt một hình hiện có. plt.figure(figsize=(1.8 * n_col, 2.4 * n_row))
Căn chỉnh kích thước và vị trí của chân dung. plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.35)
Thêm một Trục vào hình hiện tại hoặc truy xuất một Trục hiện có. plt.subplot(n_row, n_col, i + 1)
Hiển thị hình ảnh chân dung và đánh số plt.imshow(images[i], cmap=plt.cm.gray) plt.title(titles[i], size)
Nhận hoặc đặt vị trí đánh dấu hiện tại và nhãn của trục x và y plt.xticks(()) plt.yticks(())
3.2.5 Thực hiện huấn luyện bằng SVM
Gắn bộ phân loại vào tập huấn luyện t0 = time() param_grid = {'C': [1e3, 5e3, 1e4, 5e4, 1e5],
Tìm kiếm toàn diện trên các giá trị tham số được chỉ định Các tham số của công cụ ước tính được sử dụng để áp dụng các phương pháp này được tối ưu hóa bằng cách tìm kiếm lưới được xác thực chéo trên lưới tham số. clf = GridSearchCV(SVC(kernel='rbf', class_weight='balanced'), param_grid, verbose=5) clf = clf.fit(X_train_pca, y_train)
Thời gian huấn luyện print("done in %0.3fs" % (time() - t0)) Đánh giá định lượng chất lượng mộ hình trên bộ kiểm tra. print("\n") print("Predicting people's names on the test set") t0 = time() y_pred = clf.predict(X_test_pca) # Gọi dự đoán trên công cụ ước tính với các tham số được tìm thấy tốt nhất print(clf.score(X_test_pca,y_test)) #Trả về điểm số trên dữ liệu đã huấn luyện print("done in %0.3fs" % (time() - t0)) # Thời gian đánh giá
Xây dựng một báo cáo văn bản hiển thị các số liệu phân loại chính. Tính toán ma trận nhầm lẫn để đánh giá độ chính xác của phân loại.
3.2.7 Dự đoán người dùng dựa trên mô hình
Nhận diện đối tượng đã được huấn luyện. Đường dẫn tới file ảnh của đối tượng cần nhận diện. test = [] testImage = "test/a (1).jpg" Đọc file ảnh của đối tượng testImage=cv2.imread(testImage)[data_slice[0]:data_slice[1], data_slice[2]:data_slice[3]]
# Đưa ảnh về kích thước theo mẫu testImage=cv2.resize(testImage, (w,h))
# Chuyển đổi màu ảnh sang COLOR_BGR2GRAY testImage=cv2.cvtColor(testImage, cv2.COLOR_BGR2GRAY)
# Tính toán khuôn mặt trong ảnh test.append(testImageFeatureVector)
# Chuyển đổi hình ảnh để giảm kích thước cho test testImagePCA = pca.transform(test)
# Đưa ra tên giống với bộ huấn luyện nhất testImagePredict=clf.predict(testImagePCA)
3.2.8 Dự đoán toàn bộ người dùng dựa trên mô hình
Kiểm tra độ chính xác khi nhận diện tất cả đối tượng đã được huấn luyện.
Nối đường dẫn đến thư mục “test/” Đọc file bằng đường dẫn đã nối. path_testdata = "test/" for file in os.listdir(path_testdata): test = [] Đưa ảnh về kích thước, màu sắc theo khuôn. filename=path_testdata + file testImage=cv2.imread(filename)[data_slice[0]:data_slice[1], data_slice[2]:data_slice[3]] testImage=cv2.resize(testImage, (w,h)) testImage=cv2.cvtColor(testImage, cv2.COLOR_BGR2GRAY) testImageFeatureVector=numpy.array(testImage).flatten()
Dự đoán tên đối tượng. test.append(testImageFeatureVector) testImagePCA = pca.transform(test) testImagePredict=clf.predict(testImagePCA)
3.2.9 Nhận diện khuôn mặt bằng camera
Khai báo thư viện cv2, thư viện numpy.
Khởi tạo đối tượng để truyền đường dẫn của file video, hàm VideoCapture để đọc frame từ file video.
Xác định các đặc điểm khuôn mặt bằng hàm CasacadeClassifier được viết sẵn. cap = cv2.VideoCapture(0) face_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_frontalface_default.xml ') cap.set(3,640)
Khai báo mảng test để kiểm tra khuôn mặt.
Khai báo mảng face để thực hiện xác định khuôn mặt.
Gọi phương thức read của cv2.VideoCapture để đọc frame tiếp theo từ file video. test = [] face = [] ret, frame = cap.read() xv, yv, cv = frame.shape
Kiểm tra khuôn mặt, trong khung hình nếu không tìm thấy khuôn mặt thì không thực hiện nhận diện, nếu có bắt đầu đo khuôn mặt. if ret == True :
Thực hiện xác định khuôn mặt.
Khi tìm thấy khuôn mặt sẽ cắt phần mặt của khuôn mặt để so sánh với hình sau khi đã huấn luyện và dự đoán tên của khuôn mặt. gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, 1.3, 5) for (x,y,wf,hf) in faces: cy, cx = y + (hf//2), x + (wf//2) max_len = max(max(hf//2,wf//2), 125) if (x - max_len) = xv or (y - max_len) = yv : continue face_crop = (frame[cy-max_len:cy+max_len, cx- max_len:cx+max_len]) face_crop = face_crop[data_slice[0]:data_slice[1], data_slice[2]:data_slice[3]]
Thực hiện nhận diện khuôn mặt. testImage = cv2.resize(face_crop, (w,h)) cv2.imshow('face',testImage) testImage=cv2.cvtColor(testImage, cv2.COLOR_BGR2GRAY) testImageFeatureVector=numpy.array(testImage).flatten() test.append(testImageFeatureVector) testImagePCA = pca.transform(test) testImagePredict=clf.predict(testImagePCA)
Tạo khung cho khuôn mặt frame = cv2.rectangle(frame,(x,y),(x+wf,y+hf),(255,51,255),2) frame = cv2.rectangle(frame,(x,y+hf),(x+wf,y+hf+30),
Hiển thị tên khuôn mặt. cv2.putText(frame, "Name : " + target_names[testImagePredict[0]], (x + x//10, y+hf+20), \ cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255),1)
Hiển thị phần cắt khuôn mặt. cv2.imshow('frame',frame)
Thoát chương trình nhận diện bằng CAMERA. Ấn phím ‘q’ để thoát khỏi chương trình. if cv2.waitKey(1) & 0xFF == ord('q'): break
3.2.10 Nhận diện khuôn mặt bằng hình ảnh
Khai báo thư viện time, dlib, plt.
# Đọc ảnh đầu vào fileName = './test/a (3).png' frame = cv2.imread(fileName)
# Khai báo việc sử dụng các hàm của dlib hog_face_detector = dlib.get_frontal_face_detector()
# Tính thời gian khi thực hiện xác định khuôn mặt start = time.time() faces_hog = hog_face_detector(frame, 1) end = time.time() print("Processing:",fileName) print("SVM Execution time: " + str(end-start))
# Thực hiện xác thực khuôn mặt test = []
# Vẽ một đường bao xung quanh các khuôn mặt được xác định ra bởi SVM for face in faces_hog: x = face.left() y = face.top() wi = face.right() - x he = face.bottom() - y
Vẽ khung khuôn mặt và khung tên của khuôn mặt. cv2.rectangle(frame, (x,y), (x+wi,y+he), (255,51,255), 2) cv2.rectangle(frame,(x,y+he),(x+wi,y+he+30),(255,51,255),-1)
Nhận diện khuôn mặt. fileName=cv2.imread(fileName)[data_slice[0]:data_slice[1], data_slice[2]:data_slice[3]] fileName=cv2.resize(fileName, (w,h)) fileName=cv2.cvtColor(fileName, cv2.COLOR_BGR2GRAY) fileNameFeatureVector=numpy.array(fileName).flatten() test.append(fileNameFeatureVector) fileNamePCA = pca.transform(test) fileNamePredict=clf.predict(fileNamePCA)
Hiển thị tên khuôn mặt. cv2.putText(frame, target_names[fileNamePredict[0]], (x, y+he+20), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,0), 2) frame = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB) print ("Predicted Name : " + target_names[fileNamePredict[0]])
Kết quả nhận diện khuôn mặt
Nhận diện bằng hình ảnh: