Sử dụng CNN trong bài toán nhận dạng mặt người ( Phần 2 )
Bài đăng này đã không được cập nhật trong 6 năm
Ở phần trước mình đã giới thiệu qua về thuật toán CNN, phần này hãy cùng áp dụng nó vào bài toán nhận dạng mặt người.
Cài đặt môi trường
Để thực hiện, mọi người cần cài đặt môi trường như sau:
- Python 3.6: https://www.python.org/downloads/
- pip3:
sudo apt install python3-pip
- NumPy, Pandas, Matplotlib, Scikit-Learn:
pip3 install --upgrade matplotlib numpy pandas scipy scikit-learn
- opencv3: http://embedonix.com/articles/image-processing/installing-opencv-3-1-0-on-ubuntu/
- Tensorflow: https://www.tensorflow.org/install/install_linux
Chuẩn bị dataset và tạo tập train + test
Về cơ bản, chúng ta sẽ chia tập dữ liệu thành 2 tệp, 1 tệp gồm các ảnh có xuất hiện mặt người, tệp còn lại bao gồm các ảnh không có mặt người. Bạn có thể tham khảo dataset có chứa mặt người tại đây: https://www.kaggle.com/c/challenges-in-representation-learning-facial-expression-recognition-challenge/data Sau khi đã chuẩn bị xong dataset, tiến hành tạo tập train + test:
import tensorflow as tf
import cv2,os
import numpy as np
from sklearn import preprocessing
from sklearn.model_selection import train_test_split
n_classes=2
path_pos='data/Face/Positive' # tập dữ liệu chứa mặt người
path_neg='data/Face/Negative' # tập dữ liệu không chứa mặt người
def read_data(path,label):
images = []
labels = []
dirs = os.listdir( path )
for files in dirs:
file_name=path+"/"+files
image = cv2.imread(file_name,0)
image=np.reshape(image, 40*100)
images.append(image)
labels.append(label)
return images, labels
images_pos,labels_pos=read_data(path_pos,1)
images_neg,labels_neg=read_data(path_neg,0)
images=images_pos+images_neg
labels=labels_pos+labels_neg
x_train, x_test,y_train,y_test = train_test_split(images, labels,test_size=0.1, random_state=41)
x_train=np.asarray(x_train)
y_train=np.asarray(y_train)
Thiết lập mạng CNN
Thông thường, một CNN gồm một stack các convolutional module, mỗi một module thực hiện việc extract feature. Mỗi module cũng bao gồm một convolutional layer theo sau là một pooling layer. Module convolutional cuối cùng bao gồm một hoặc nhiều các dense layer thực hiện việc phân lớp. Layer dense cuối cùng trong một CNN bao gồm một single node cho mỗi một lớp cụ thể trong model (tất cả các class khả thi mà model có thể dự đoán được). Với mỗi một node, ta sử dụng hàm kích hoạt softmax để generate ra giá trị predict (từ 0 - 1). Cụ thể như sau:
def conv_net(x):
x = tf.reshape(x, shape=[-1, 28, 28, 1]) # input layer, image size input có kích thước 28x28
conv1 = tf.layers.conv2d(x, 32, 5, activation=tf.nn.relu,padding="SAME") # convolutional layer 1
conv1 = tf.layers.max_pooling2d(conv1, 2, 2,padding="SAME") # pooling layer 1
conv2 = tf.layers.conv2d(conv1, 64, 5, activation=tf.nn.relu,padding="SAME") # convolutional layer 2
conv2 = tf.layers.max_pooling2d(conv2, 2, 2,padding="SAME") # pooling layer 2
# tạo dense layer
fc1 = tf.contrib.layers.flatten(conv2)
fc1 = tf.layers.dense(fc1, 512,activation=tf.nn.relu)
out = tf.layers.dense(fc1, num_classes,name="output")
return out
Như vậy, ta đã tạo được một hàm chung cho việc xây dựng mạng CNN. Tiếp theo, ta sẽ optimize mạng CNN bằng Adam optimizer:
Tìm correct và accuracy để đánh giá độ chính xác của mạng CNN.
x = tf.placeholder(tf.float32, [None, n_input],name="x")
y = tf.placeholder(tf.int32, [None],name="y")
pred = conv_net(x)
xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=pred, labels=y)
cost = tf.reduce_mean(xentropy)
optimizer = tf.train.AdamOptimizer()
training_op=optimizer.minimize(cost)
correct = tf.nn.in_top_k(pred, y, 1)
accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))
init = tf.global_variables_initializer()
Thực hiện optimize
# Parameters
learning_rate = 0.001
batch_size = 20
display_step = 10
num_steps=200
# Network Parameters
n_input = 4000
num_classes=2
def random_batch(x_train, y_train, batch_size):
rnd_indices = np.random.randint(0, len(x_train), batch_size)
x_batch = x_train[rnd_indices]
y_batch = y_train[rnd_indices]
return x_batch, y_batch
saver = tf.train.Saver()
sess= tf.Session()
sess.run(init)
for step in range(1, num_steps+1):
batch_x, batch_y = random_batch(x_train, y_train, batch_size)
sess.run(training_op, feed_dict={x: batch_x, y: batch_y})
if step % display_step == 0 or step == 1:
acc = sess.run( accuracy, feed_dict={x: x_train,y: y_train})
print('Step:',step, ', Accuracy:',acc)
print("Optimization Finished!")
Kết quả sau khi optimize:
- Step: 1 , Accuracy: 0.525926
- Step: 10 , Accuracy: 0.898413
- Step: 20 , Accuracy: 0.660317
- Step: 30 , Accuracy: 0.857143
- Step: 40 , Accuracy: 0.928042
- Step: 50 , Accuracy: 0.967196
- Step: 60 , Accuracy: 0.982011
- Step: 70 , Accuracy: 0.98836
- Step: 80 , Accuracy: 0.991534
- Step: 90 , Accuracy: 0.991534
- Step: 100 , Accuracy: 0.990476
- Step: 110 , Accuracy: 0.991534
- Step: 120 , Accuracy: 0.990476
- Step: 130 , Accuracy: 0.996825
- Step: 140 , Accuracy: 0.997884
- Step: 150 , Accuracy: 1.0
- Step: 160 , Accuracy: 0.998942
- Step: 170 , Accuracy: 0.997884
- Step: 180 , Accuracy: 0.998942
- Step: 190 , Accuracy: 1.0
- Step: 200 , Accuracy: 1.0
- Optimization Finished!
Vì mình thực hiện demo optimize nên để các param thấp nên optimize đạt kết quả cao, trong thực tế, lượng data lớn đòi hỏi batch_size
, step
rất lớn
Test model vừa train
from skimage.transform import pyramid_gaussian
from skimage.io import imread
from skimage.feature import hog
from sklearn.externals import joblib
import cv2
import matplotlib.pyplot as plt
from mns import nms,sliding_window
import numpy as np
from sklearn import preprocessing
%matplotlib inline
path="data/Face/Test/3.png" # đường dẫn ảnh muốn test
im1=cv2.imread(path)
im = imread(path, as_grey=False)
scale = 0
downscale=1.25
min_wdw_sz = (384, 256) # window size
step_size = (10, 10)
detections = []
for im_scaled in pyramid_gaussian(im, downscale=downscale):
cd = []
if im_scaled.shape[0] < min_wdw_sz[1] or im_scaled.shape[1] < min_wdw_sz[0]:
break
for (x, y, im_window) in sliding_window(im_scaled, min_wdw_sz, step_size):
if im_window.shape[0] != min_wdw_sz[1] or im_window.shape[1] != min_wdw_sz[0]:
continue
image=np.reshape(im_window, 256*384)
x_test=[]
x_test.append(image)
x_test=np.asarray(x_test)
y_test=sess.run(index,feed_dict={X: x_test})
y_conf=sess.run(conf,feed_dict={X: x_test})
pred=np.asarray(y_test)[0]
conf_value=y_conf.reshape(-1)[pred]
if pred == 1:
print("detection location",x,y)
detections.append((x, y, conf_value,
int(min_wdw_sz[0]*(downscale**scale)),
int(min_wdw_sz[1]*(downscale**scale))))
cd.append(detections[-1])
scale+=1
clone = im1.copy()
k=10000
for (x_tl, y_tl, _, w, h) in detections:
print(str(k))
s_file='data/tmp/FalsePos/neg'+str(k)+'.pgm'
k=k+1
cv2.rectangle(im1, (x_tl, y_tl), (x_tl+w, y_tl+h), (0, 0, 255), thickness=2)
img=clone[y_tl:y_tl+h,x_tl:x_tl+w]
cv2.imwrite(s_file,img)
plt.imshow(cv2.cvtColor(im1, cv2.COLOR_BGR2RGB))
plt.show()
threshold=.3
detections = nms(detections, threshold)
for (x_tl, y_tl, _, w, h) in detections:
cv2.rectangle(clone, (x_tl, y_tl), (x_tl+w,y_tl+h), (0, 0, 255), thickness=2)
plt.imshow(cv2.cvtColor(clone, cv2.COLOR_BGR2RGB))
plt.show()
Kết
Thay vì cố gắng lập hồ sơ xác minh chính xác khuôn mặt, dự án này là một minh chứng cho khái niệm để chứng minh quá trình đào tạo một mạng lưới hiện có cho một mục tiêu khác. Chúng tôi đã có thể lấy một mô hình được đào tạo trước về bộ dữ liệu liên quan và điều chỉnh nó theo một nhiệm vụ mà chúng tôi chọn. Trong quá trình này, chúng tôi có thể tiết kiệm được hàng tuần hoặc thậm chí hàng tháng trong thời gian phát triển và đào tạo. Chúng ta đã thấy chúng ta có thể giữ lại tất cả các tham số của mỗi lớp, ngoại trừ lớp cuối cùng, tạo ra một lớp đầu ra mới và đào tạo một lớp không đông lạnh duy nhất để đạt được hiệu quả trên khuôn mặt với mô hình được đào tạo ban đầu để phân biệt giữa 1000 đối tượng. Hơn nữa, chúng tôi khám phá thành công khái niệm tăng cường dữ liệu bằng cách chuyển đổi hình ảnh và chúng tôi có thể sử dụng TensorBoard để hiểu đồ thị tính toán (hoặc ít nhất là xem biểu đồ) và để quan sát các đường cong đào tạo đã xác nhận việc sử dụng dữ liệu của chúng tôi. Có nhiều bước bổ sung cho dự án này để cải thiện độ chính xác. Những người có nhiều khả năng nhất có thể có tác động đáng kể là thu thập dữ liệu đào tạo có nhãn hơn hoặc đào tạo nhiều lớp của mạng. Cả hai đều dễ thực hiện nhưng tốn nhiều thời gian. Bây giờ, dự án này phục vụ để xác nhận phương pháp thích ứng cho sự phát triển của CNN.
Quá trình thích ứng này cho thấy một ứng dụng công nghiệp, trong đó một công ty có nhiều khả năng sử dụng một mô hình hiệu suất cao hiện có hơn là bắt đầu từ một slate sạch vì sự phát triển và đào tạo nguồn lực cần thiết cho công việc như vậy. Hơn nữa, học sâu là một lĩnh vực hợp tác, nơi các khám phá mới nhất thiết yếu xây dựng những phát hiện trước đây và các ứng dụng mới cho mạng nơ-ron hiện có phát sinh từ sự chia sẻ. Những ý tưởng tuyệt vời chết chóc một cách độc lập, và chỉ bằng cách cộng tác với các thực thể khác nhau trên khắp các lĩnh vực mà sự đổi mới trên thế giới có thể được phát triển. Trong cách suy nghĩ đó, hãy sử dụng, chia sẻ và điều chỉnh mã này theo bất kỳ cách nào mà bạn thấy phù hợp!
All rights reserved