Sử dụng CNN trong bài toán nhận dạng mặt người ( Phần 2 )



  • Ở 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:

    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 :thinking:

    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!
    Nguồn: Viblo


Hãy đăng nhập để trả lời
 

Có vẻ như bạn đã mất kết nối tới LaptrinhX, vui lòng đợi một lúc để chúng tôi thử kết nối lại.