Hướng dẫn dùng epoch training trong PHP


Hướng dẫn dùng epoch training trong PHP

Xin chào các bạn. Có lẽ sợ sếp là một bệnh thâm niên ở mỗi người làm văn phòng nói chung và đặc biệt là anh em IT nói riêng. Đã bao giờ bạn gặp phải tình huống rất oái oăm khi mà ngồi code cả buổi thì sếp chả ghé thăm, đến lúc vừa rảnh tay lên Youtube nghe nhạc một tý xíu thì sếp đến nhẹ nhàng vỗ vai và thủ thỉ vào tai bạn một câu nói 2 giây nhưng dài như thế kỉ ARE YOU CODING?. 😜😜😜 Thấu hiểu nỗi đau đó của anh em, hôm nay mình mạn phép hướng dẫn các bạn làm một ứng dụng rất hay ho đó là xử dụng AI và các mô hình Deep Learning để qua camera sẽ tự động phát hiện sếp sắp đến lại gần và rồi tự động chuyển ngay màn hình sang chế độ coding rất hữu dụng đặc biệt là cho anh em IT. Xin lưu ý mục đích của bài viết chỉ mang tính chất vui vẻ, giúp anh em cảm thấy đỡ áp lực sau những giờ làm việc căng thẳng. Hoàn toàn không cổ vũ cho việc mọi người làm việc riêng trong giờ làm.. OK chúng ta sẽ bắt đầu ngay thôi. Tuy nhiên trước tiên mời bạn xem thử demo dưới đây.

Bước 1: Cách tiếp cận bài toán

Đối với một bài toán mới chúng ta cần phải phân tích bài toán để tìm ra cách tiếp cận sao cho phù hợp. Tức là phân tích ra input và output của vấn đề. Đối với bài toán đã nêu ra, mục đích của chúng ta là phát hiện xem khi nào sếp đến (tất nhiên là dựa trên hình ảnh) vậy chắc chắn đầu vào của chúng ta sẽ từ một ảnh khuôn mặt, đầu ra cần phải xác định đó có phải là sếp hay không và nếu chúng ta xác định được đó là sếp thì thực hiện một xử lý nào đó (ví dụ như bật màn hình code lên thay vì màn hình đọc báo chẳng hạn). Vậy tựu chung lại chúng ta có thể tổng quát hóa các bước lại như sau:

  • Khoanh vùng được các khuôn mặt
  • Nhận ra xem khuôn mặt đó có giống sếp hay không
  • Nếu giống sếp thì bật màn hình code lên (như đang làm việc bình thường)
  • Nếu không phải sếp thì cứ đọc báo tiếp.

Hai bước sau thì đơn giản rồi phải không, bây giờ chúng ta sẽ bàn luận đến hai bước đầu tiên nhé. Tạm gác lại việc làm sao để khoanh vùng được mặt trong một bức ảnh bởi vì chúng ta không có quá nhiều thời gian. Hơn nữa bài toán này cũng khá quen thuộc nếu như các bạn chịu khó follow các topic về Deep Learning trên Viblo. Chuyển sang bước thứ hai, làm sao để biết được khuôn mặt được khoanh vùng có phải là sếp của mình hay không? Chúng ta cùng tìm hiểu hai cách tiếp cận cho vấn đề này nhé

Cách tiếp cận theo Face Verificiation

Hiểu đơn giản thì cách tiếp cận này sẽ đi trả lời câu hỏi:

Với một khuôn mặt này có giống với sếp mình hay không và nếu giống thì giống bao nhiêu phần trăm.

Ở đây chúng ta đơn thuần đi so sánh (compare) khuôn mặt mới với một khuôn mặt cũ đã có trong cơ sở dữ liệu (ví dụ các ảnh của sếp) xem hai bức ảnh này giống nhau bao nhiêu phần trăm. Thông thường bài toán này dẫn chúng ta đến một bài toán khác là làm thế nào để xác định được hai khuôn mặt này có giống nhau hay không. Như chúng ta đã biết máy tính chỉ hoạt động trên số, và tất cả cá giải thuật về Deep Learning cũng đều quy về việc xử lý trên không gian ma trận thực. Chính vì thế chúng ta cần một cách nào đó để mã hóa một ảnh của chúng ta thành vector gọi là embeding. Chúng ta có thể xem sơ đồ xử lý như sau:

Hướng dẫn dùng epoch training trong PHP

Trên hình chúng ta thấy nhiệm vụ của Face Embedding Model chính là chuyển đổi từ hình ảnh sang một vector số thực. Để làm được điều này thường người ta sử dụng mạng nơ ron với hàm loss là một Triplet loss. Mọi người có thể tìm hiểu thêm về kĩ thuật này trong các bài viết khác trên Viblo

Hiểu đơn giản đó là việc chúng ta đưa những ảnh có nội dung giống nhau lại gần nhau và ảnh có nội dung khác nhau ra xa nhau. Mọi người có thể tìm hiểu thêm về phương pháp này trên các bài viết về Deep Learning trên Viblo. Giờ chúng ta sẽ cùng tìm hiểu phương pháp tiếp theo.

Cách tiếp cận theo Face Recognition

Thay vì việc phải tính toán một độ tương tự và so sánh như cách tiếp cận đầu tiên, chúng ta sẽ định nghĩa một mô hình và câu trả lời output của nó chính là xác suất của khuôn mặt có phải là sếp hay không. Việc này được giải quyết khá đơn giản và hiệu quả bởi mạng nơ ron tích chập (CNN) chúng ta có thể thấy trong mô hình sau:

Hướng dẫn dùng epoch training trong PHP

Lúc này mạng của chúng ta có thể trả lời luôn câu hỏi rằng

Đây là ai? – Output là sếp hoặc không phải là sếp OK sau khi đã hiểu một vấn đề chúng ta sẽ tiến hành lựa chọn một trong hai phương pháp để tính toán. Trong bài viết này mình sẽ sử dụng phương pháp thứ hai và các bạn có thể thử cài đặt phương pháp thứ nhất xem sao. Mình nghĩ là không có nhiều khó khăn lắm đâu. OK chúng ta bắt đầu nhé

Bước 2: Chuẩn bị dữ liệu.

Đối với mỗi một bài toán Machine Learning nào đều cần phải chuẩn bị về mặt dữ liệu. Nếu không có dữ liệu thì sẽ không có gì cả 😋 Các bạn hãy thu thập các dữ liệu mặt của sếp mình, càng nhiều càng đa dạng càng tốt, Kiểu đa sắc thái như thế này là một nguồn dữ liệu rất quý giá.

Hướng dẫn dùng epoch training trong PHP

Sau đó thu thập dữ liệu của các loại mặt khác không phải là mặt của sếp mình cho tất cả vào một folder chẳng hạn. Lúc này chúng ta sẽ có hai folder có tổ chức như sau:

Hướng dẫn dùng epoch training trong PHP

Càng bạn lưu ý rằng nên thu thập nhiều ảnh một chút model sẽ chính xác hơn

Bước 3: Tiền xử lý dữ liệu

Đây là một bước khá quan trọng trong khi thực hiện một bài toán Deep Learning nào. Chúng ta đã biết rằng Garbage in – Garbage out chính vì thế nên việc đưa dữ liệu vào trong mô hình cũng cần phải được xử lý một cách kĩ lưỡng. Chúng ta có một vài thao tác xử lý dữ liệu như sau:

  • Resize image
  • Chuyển về gray scale (nếu cần)
  • Normalization image – chuẩn hóa ảnh giúp cho việc training được cải thiện về tốc độ và độ chính xác
  • Augumentation image – giúp sinh thêm các dữ liệu mới, làm giàu hơn tập dữ liệu đã có
  • Loại bỏ các dữ liệu nhiễu giúp mô hình không bị lệch
  • Cân bằng lại dữ liệu giúp cho mô hình học được tổng quát hơn

Trong bài viết này chúng ta sử dụng Keras và model Mobilenet để training nên các bước tiền xử lý dữ liệu này chúng ta sử dụng trực tiếp của Keras luôn. Tiến hành import các thư viện cần thiết:

Xin chào các bạn. Có lẽ sợ sếp là một bệnh thâm niên ở mỗi người làm văn phòng nói chung và đặc biệt là anh em IT nói riêng. Đã bao giờ bạn gặp phải tình huống rất oái oăm khi mà ngồi code cả buổi thì sếp chả ghé thăm, đến lúc vừa rảnh tay lên Youtube nghe nhạc một tý xíu thì sếp đến nhẹ nhàng vỗ vai và thủ thỉ vào tai bạn một câu nói 2 giây nhưng dài như thế kỉ ARE YOU CODING?. 😜😜😜 Thấu hiểu nỗi đau đó của anh em, hôm nay mình mạn phép hướng dẫn các bạn làm một ứng dụng rất hay ho đó là xử dụng AI và các mô hình Deep Learning để qua camera sẽ tự động phát hiện sếp sắp đến lại gần và rồi tự động chuyển ngay màn hình sang chế độ coding rất hữu dụng đặc biệt là cho anh em IT. Xin lưu ý mục đích của bài viết chỉ mang tính chất vui vẻ, giúp anh em cảm thấy đỡ áp lực sau những giờ làm việc căng thẳng. Hoàn toàn không cổ vũ cho việc mọi người làm việc riêng trong giờ làm.. OK chúng ta sẽ bắt đầu ngay thôi. Tuy nhiên trước tiên mời bạn xem thử demo dưới đây.

Bước 1: Cách tiếp cận bài toán

Đối với một bài toán mới chúng ta cần phải phân tích bài toán để tìm ra cách tiếp cận sao cho phù hợp. Tức là phân tích ra input và output của vấn đề. Đối với bài toán đã nêu ra, mục đích của chúng ta là phát hiện xem khi nào sếp đến (tất nhiên là dựa trên hình ảnh) vậy chắc chắn đầu vào của chúng ta sẽ từ một ảnh khuôn mặt, đầu ra cần phải xác định đó có phải là sếp hay không và nếu chúng ta xác định được đó là sếp thì thực hiện một xử lý nào đó (ví dụ như bật màn hình code lên thay vì màn hình đọc báo chẳng hạn). Vậy tựu chung lại chúng ta có thể tổng quát hóa các bước lại như sau:

Những việc làm hấp dẫn

  • Hướng dẫn dùng epoch training trong PHP

    Lập Trình Viên Python

    VNPT-ITHo Chi Minh, Ha Noi, Da Nang, Others$500 - $1,500

    Python
  • Hướng dẫn dùng epoch training trong PHP

    Front-End Developer

    InventisHo Chi Minh$1,000 - $2,000

    Front-End
  • Hướng dẫn dùng epoch training trong PHP

    Java Developer – Middle to Senior ($800 - $1600)

    CÔNG TY CỔ PHẦN EASTGATE SOFTWAREHa Noi$800 - $1,600

    Java
  • Khoanh vùng được các khuôn mặt
  • Nhận ra xem khuôn mặt đó có giống sếp hay không
  • Nếu giống sếp thì bật màn hình code lên (như đang làm việc bình thường)
  • Nếu không phải sếp thì cứ đọc báo tiếp.

Hai bước sau thì đơn giản rồi phải không, bây giờ chúng ta sẽ bàn luận đến hai bước đầu tiên nhé. Tạm gác lại việc làm sao để khoanh vùng được mặt trong một bức ảnh bởi vì chúng ta không có quá nhiều thời gian. Hơn nữa bài toán này cũng khá quen thuộc nếu như các bạn chịu khó follow các topic về Deep Learning trên Viblo. Chuyển sang bước thứ hai, làm sao để biết được khuôn mặt được khoanh vùng có phải là sếp của mình hay không? Chúng ta cùng tìm hiểu hai cách tiếp cận cho vấn đề này nhé

Cách tiếp cận theo Face Verificiation

Hiểu đơn giản thì cách tiếp cận này sẽ đi trả lời câu hỏi:

Với một khuôn mặt này có giống với sếp mình hay không và nếu giống thì giống bao nhiêu phần trăm.

Ở đây chúng ta đơn thuần đi so sánh (compare) khuôn mặt mới với một khuôn mặt cũ đã có trong cơ sở dữ liệu (ví dụ các ảnh của sếp) xem hai bức ảnh này giống nhau bao nhiêu phần trăm. Thông thường bài toán này dẫn chúng ta đến một bài toán khác là làm thế nào để xác định được hai khuôn mặt này có giống nhau hay không. Như chúng ta đã biết máy tính chỉ hoạt động trên số, và tất cả cá giải thuật về Deep Learning cũng đều quy về việc xử lý trên không gian ma trận thực. Chính vì thế chúng ta cần một cách nào đó để mã hóa một ảnh của chúng ta thành vector gọi là embeding. Chúng ta có thể xem sơ đồ xử lý như sau:

Hướng dẫn dùng epoch training trong PHP

Trên hình chúng ta thấy nhiệm vụ của Face Embedding Model chính là chuyển đổi từ hình ảnh sang một vector số thực. Để làm được điều này thường người ta sử dụng mạng nơ ron với hàm loss là một Triplet loss. Mọi người có thể tìm hiểu thêm về kĩ thuật này trong các bài viết khác trên Viblo

Hướng dẫn dùng epoch training trong PHP

- - - - - - - - - - - - - - - - - - - - Được tài trợ - - - - - - - - - - - - - - - - - - - -

Hướng dẫn dùng epoch training trong PHP

Hiểu đơn giản đó là việc chúng ta đưa những ảnh có nội dung giống nhau lại gần nhau và ảnh có nội dung khác nhau ra xa nhau. Mọi người có thể tìm hiểu thêm về phương pháp này trên các bài viết về Deep Learning trên Viblo. Giờ chúng ta sẽ cùng tìm hiểu phương pháp tiếp theo.

Cách tiếp cận theo Face Recognition

Thay vì việc phải tính toán một độ tương tự và so sánh như cách tiếp cận đầu tiên, chúng ta sẽ định nghĩa một mô hình và câu trả lời output của nó chính là xác suất của khuôn mặt có phải là sếp hay không. Việc này được giải quyết khá đơn giản và hiệu quả bởi mạng nơ ron tích chập (CNN) chúng ta có thể thấy trong mô hình sau:

Hướng dẫn dùng epoch training trong PHP

Lúc này mạng của chúng ta có thể trả lời luôn câu hỏi rằng

Đây là ai? – Output là sếp hoặc không phải là sếp OK sau khi đã hiểu một vấn đề chúng ta sẽ tiến hành lựa chọn một trong hai phương pháp để tính toán. Trong bài viết này mình sẽ sử dụng phương pháp thứ hai và các bạn có thể thử cài đặt phương pháp thứ nhất xem sao. Mình nghĩ là không có nhiều khó khăn lắm đâu. OK chúng ta bắt đầu nhé

Bước 2: Chuẩn bị dữ liệu.

Đối với mỗi một bài toán Machine Learning nào đều cần phải chuẩn bị về mặt dữ liệu. Nếu không có dữ liệu thì sẽ không có gì cả 😋 Các bạn hãy thu thập các dữ liệu mặt của sếp mình, càng nhiều càng đa dạng càng tốt, Kiểu đa sắc thái như thế này là một nguồn dữ liệu rất quý giá.

Hướng dẫn dùng epoch training trong PHP

Sau đó thu thập dữ liệu của các loại mặt khác không phải là mặt của sếp mình cho tất cả vào một folder chẳng hạn. Lúc này chúng ta sẽ có hai folder có tổ chức như sau:

Hướng dẫn dùng epoch training trong PHP

Càng bạn lưu ý rằng nên thu thập nhiều ảnh một chút model sẽ chính xác hơn

Bước 3: Tiền xử lý dữ liệu

Đây là một bước khá quan trọng trong khi thực hiện một bài toán Deep Learning nào. Chúng ta đã biết rằng Garbage in – Garbage out chính vì thế nên việc đưa dữ liệu vào trong mô hình cũng cần phải được xử lý một cách kĩ lưỡng. Chúng ta có một vài thao tác xử lý dữ liệu như sau:

  • Resize image
  • Chuyển về gray scale (nếu cần)
  • Normalization image – chuẩn hóa ảnh giúp cho việc training được cải thiện về tốc độ và độ chính xác
  • Augumentation image – giúp sinh thêm các dữ liệu mới, làm giàu hơn tập dữ liệu đã có
  • Loại bỏ các dữ liệu nhiễu giúp mô hình không bị lệch
  • Cân bằng lại dữ liệu giúp cho mô hình học được tổng quát hơn

Trong bài viết này chúng ta sử dụng Keras và model Mobilenet để training nên các bước tiền xử lý dữ liệu này chúng ta sử dụng trực tiếp của Keras luôn. Tiến hành import các thư viện cần thiết:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

# Import dependency

import os

import cv2

import keras

import numpy as np

from keras import backend as K

from keras.layers.core import Dense, Activation

from keras.optimizers import Adam

from keras.metrics import categorical_crossentropy

from keras.preprocessing.image import ImageDataGenerator

from keras.preprocessing import image

from keras.models import Model

from keras.applications import imagenet_utils

from keras.layers import Dense, GlobalAveragePooling2D

from keras.applications import MobileNet

from keras.applications.mobilenet import preprocess_input

from IPython.display import Image

from keras.optimizers import Adam

Và định nghĩa các tham số

1

2

3

4

5

6

7

8

# Define parameters

IMAGE_SIZE = 224

IMAGE_DATA = './data'

images = []

labels = []

Sau đó chúng ta định nghĩa hàm preprocess như sau:

1

2

3

4

5

6

7

8

def prepare_image(file):

    img_path = ''

    img = image.load_img(img_path + file, target_size=(IMAGE_SIZE, IMAGE_SIZE))

    img_array = image.img_to_array(img)

    img_array_expanded_dims = np.expand_dims(img_array, axis=0)

    return keras.applications.mobilenet.preprocess_input(img_array_expanded_dims)

Và đoạn code để sinh dữ liệu mẫu dùng cho việc training như sau:

1

2

3

4

5

6

7

8

9

# Generate dataset

for path, subdirs, files in os.walk(IMAGE_DATA):

    for name in files:

        img_path = os.path.join(path, name)

        images.append(prepare_image(img_path))

        labels.append(path.split('/')[-1])

Bước 4: Định nghĩa mô hình

Giống như đã mô tả ở trên chúng ta sử dụng mô hình Mobilenet để dự đoán mặt vào có phải là sếp hay không. Mình sẽ không nhắc lại lý thuyết về CNN nữa vì nó đã xuất hiện quá nhiều trên Viblo cũng như các diễn đàn khác. Các bạn có thể tìm hiểu nhé.

Khai báo mô hình đơn giản với Keras như sau:

 

1

2

3

model = keras.applications.mobilenet.MobileNet(classes=2, weights=None)

Mọi người có thể sử dụng model.summary() để hiển thị số lượng các tham số của mô hình

Hướng dẫn dùng epoch training trong PHP

Mapping label

Vì mô hình của chúng ta là mô hình phân loại nên chúng ta sẽ cần sử dụng hàm loss là cross_entropy để tính toán. Chính vì thế nên việc đầu tiên là chuyển các class từ boss thành 1 và other thành 0. Chúng ta thực hiện như sau

1

2

3

4

5

6

7

8

9

# Mapping label

mapped_labels = list(map(lambda x: 1 if x == 'boss' else 0, labels))

from keras.utils import np_utils

y_data = np_utils.to_categorical(mapped_labels)

Bước 5: Phân chia dữ liệu

Chúng ta sử dụng thư viện train_test_split để tiến hành phân chia dữ liệu thành hai tập training và testing. Giống như bao bài toán khác 😃😃😃

1

2

3

4

5

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(images, y_data, test_size=0.2)

Bước 6: Training thuật toán

Giờ là lúc chúng ta dạy cho mô hình biết được đâu là boss và đâu không phải là boss rồi đấy. Có một lưu ý là do mạng Mobilenet là một hàm khá lớn dù là 2 class nhưng số lượng tham số cũng lên đến 3,230,914 nên chúng ta cần sử dụng nhiều dữ liệu hơn để tránh bị Overfiting khiến cho mô hình kém hiệu quả. Dù sao thì dữ liệu vẫn là yếu tố quan trọng nhất phải không các bạn. Tiếp theo chúng ta cần complie mô hình

Complie mô hình

1

2

3

4

5

model.compile(loss='categorical_crossentropy',

                           optimizer='adam',

                           metrics=['accuracy'])

Đặt checkpoint

Việc đặt checkpoint rất quan trọng trong quá trình training mô hình. Giúp chúng ta lưu lại được mô hình tốt nhất theo một tiêu chí nào đó ví dụ như val_loss hay val_accuracy cũng là cách để chúng ta phòng tránh trường hợp đang training thì mất điện hay muốn training tiếp trong lần sau mà không cần training lại từ đâu. Tóm lại là phải viết checkpoint vào không mất mô hình đừng kêu 😂😂😂

1

2

3

4

5

6

7

8

from keras.callbacks import ModelCheckpoint

model_file = "boss_model/model_mobilenet.hdf5"

checkpoint = ModelCheckpoint(model_file, monitor='val_loss', verbose=1, save_best_only=True, mode='min')

callbacks_list = [checkpoint]

Training

Sau cùng là bước training

1

2

3

model.fit(x=X_train, y=y_train, batch_size=16, epochs=100, verbose=1, validation_data=(X_test, y_test), callbacks=callbacks_list)

Các bạn cứ đợi và theo dõi thôi nhé. Do tập dữ liệu của mình nhỏ khoảng 750 ảnh nên việc training cũng sẽ diễn ra rất nhanh thôi. Đây là kết quả training trên máy của mình sau vài epochs

1

2

3

4

5

6

7

8

9

10

11

12

Epoch 1/100

750/750 [==============================] - 5s 37ms/step - loss: 0.3298 - acc: 0.8667 - val_loss: 0.0221 - val_acc: 1.0000

Epoch 00001: val_loss improved from inf to 0.02205, saving model to boss_model/model_mobilenet.hdf5

Epoch 2/100

750/750 [==============================] - 3s 7ms/step - loss: 0.0143 - acc: 0.9600 - val_loss: 0.0159 - val_acc: 0.9465

Epoch 00002: val_loss improved from 0.02205 to 0.01592, saving model to boss_model/model_mobilenet.hdf5

Epoch 3/100

750/750 [==============================] - 3s 7ms/step - loss: 0.0017 - acc: 0.9952 - val_loss: 0.0027 - val_acc: 0.9815

Bước 7: Chuẩn bị mô hình cho deploy

Lưu mô hình

Sau khi tiến hành training lại mô hình nhiều lần chúng ta sẽ thu được một mô hình tốt nhất và sử dụng nó để deploy lên hệ thống thực. Việc này được thực hiện như sau:

1

2

3

model.save('boss_model/final_model.h5')

Load lại mô hình

Và sau đó các bạn thử load lại mô hình này và predict một vài mẫu dữ liệu xem sao nhé:

1

2

3

4

5

6

7

8

9

from keras.models import load_model

import keras

from keras.utils.generic_utils import CustomObjectScope

# Load pretrained model

with CustomObjectScope({'relu6': keras.applications.mobilenet.relu6,'DepthwiseConv2D': keras.applications.mobilenet.DepthwiseConv2D}):

    model = load_model('./boss_model/final_model.h5')

Một lưu ý là chúng ta cần phải chạy qua các bước tiền xử lý khi dự đoán, giống hệt lúc chúng ta training.

Bước 8: Deploy bằng OpenCV

Xử lý model để dự đoán

Việc đầu tiên cần làm là Tạo file boss_model.py. Chúng ta sử dụng file này để load model đã được lưu từ các bước trên bao gồm cả các hàm về xử lý dữ liệu và dự đoán kết quả

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

import cv2

import keras

import numpy as np

from keras.models import load_model

from keras.preprocessing import image

from keras.utils.generic_utils import CustomObjectScope

# Load pretrained model

with CustomObjectScope({'relu6': keras.applications.mobilenet.relu6,'DepthwiseConv2D': keras.applications.mobilenet.DepthwiseConv2D}):

    model = load_model('./model/model.h5')

IMAGE_SIZE=224

def prepare_image(img):

    img_array = image.img_to_array(img)

    img_array_expanded_dims = np.expand_dims(img_array, axis=0)

    return keras.applications.mobilenet.preprocess_input(img_array_expanded_dims)

def predict(img):

    """

    Predict face crop from frame

    :param img:

    :return: If boss is appear when open the code IDE

    """

    try:

        img = cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE), interpolation=cv2.INTER_AREA)

        probs = model.predict(prepare_image(img))

        is_boss = np.argmax(probs[0])

        return is_boss

    except:

        return False

Detect khuôn mặt bằng dlib

Giống như mô tả ở phái đầu tiên của bài viết, trong quá trình dự đoán chúng ta cần phải detect khuôn mặt và sử dụng một thư viện rất nổi tiếng đó là dlib. Quá trình xử lý của nó như sau:

1

2

3

4

5

import dlib

hog_face_detector = dlib.get_frontal_face_detector()

faces_hog = hog_face_detector(image)

Kết quả của nó như sau:

Hướng dẫn dùng epoch training trong PHP

Sử dụng OpenCV để stream dữ liệu từ Webcam

Chúng ta cần sử dụng dữ liệu stream từ webcam để theo dõi sếp và phát hiện ra khi nào sếp đến gần một cách tức thời. Việc này có thể thực hiện bằng cách sử dụng webcam và OpenCV để stream dữ liệu. Về cơ bản chúng ta có thể thực hiện nó như sau:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

import cv2

cap = cv2.VideoCapture(0)

while True:

    ret, frame = cap.read()

    if ret:

        # Excute frame here

        cv2.imshow("frame", frame)

        key = cv2.waitKey(1)

        if key == 27:

            break

cap.release()

cv2.destroyAllWindows()

Xử lý crop mặt và dự đoán

Chúng ta sẽ crop từng khuôn mặt trong từng frame và dự đoán kết quả. Nếu là boss thì thực hiện mở ngay cửa sổ code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

if ret:

        # Resize window

        cv2.namedWindow('frame', cv2.WINDOW_NORMAL)

        cv2.resizeWindow('frame', 400, 400)

        # Resize frame for decrease predict time

        scale = 0.5

        resize_frame = cv2.resize(frame, (int(frame.shape[1]*scale), int(frame.shape[0]*scale)))

        faces_hog = hog_face_detector(resize_frame)

        frame_h, frame_w, _ = frame.shape

        reindex_x = lambda x: max(min(x, frame_w), 1)

        reindex_y = lambda x: max(min(x, frame_h), 1)

        # loop over detected faces

        for face in faces_hog:

            x = reindex_x(int(face.left() / scale))

            y = reindex_y(int(face.top() / scale))

            r = reindex_x(int(face.right() / scale))

            b = reindex_y(int(face.bottom() / scale))

            # draw box over face

            crop_face = frame[x: r, y: b]

            is_boss = predict(crop_face)

            if is_boss:

                cv2.putText(frame, "BOSS", (10, 100), cv2.FONT_HERSHEY_SIMPLEX, 2,

                            (0, 0, 255), 4)

                cv2.rectangle(frame, (x, y), (r, b), (0, 0, 255), 2)

                boss_count += 1

                # Open your IDE application for coding

                if boss_count > 3:

                    os.system('open -a "PyCharm CE"')

                    boss_count = 0

            else:

                cv2.putText(frame, "NORMAL", (10, 100), cv2.FONT_HERSHEY_SIMPLEX, 2,

                            (0, 255, 0), 4)

                cv2.rectangle(frame, (x, y), (r, b), (0, 255, 0), 2)

Mọi người có thể tham khảo kĩ hơn source code trong file này tại đây

Source code

Các bạn có thể tham khảo source code của bài viết tại đây

Cảm ơn các bạn đã theo dõi bài viết hẹn gặp lại trong những bài viết tiếp theo.

 

Và định nghĩa các tham số

# Define parameters

IMAGE_SIZE = 224

IMAGE_DATA = './data'

images = []

labels = []

Sau đó chúng ta định nghĩa hàm preprocess như sau:

def prepare_image(file):

img_path = ''

img = image.load_img(img_path + file, target_size=(IMAGE_SIZE, IMAGE_SIZE))

img_array = image.img_to_array(img)

img_array_expanded_dims = np.expand_dims(img_array, axis=0)

return keras.applications.mobilenet.preprocess_input(img_array_expanded_dims)

Và đoạn code để sinh dữ liệu mẫu dùng cho việc training như sau:

# Generate dataset

for path, subdirs, files in os.walk(IMAGE_DATA):

for name in files:

img_path = os.path.join(path, name)

images.append(prepare_image(img_path))

labels.append(path.split('/')[-1])

Bước 4: Định nghĩa mô hình

Giống như đã mô tả ở trên chúng ta sử dụng mô hình Mobilenet để dự đoán mặt vào có phải là sếp hay không. Mình sẽ không nhắc lại lý thuyết về CNN nữa vì nó đã xuất hiện quá nhiều trên Viblo cũng như các diễn đàn khác. Các bạn có thể tìm hiểu nhé.

Khai báo mô hình đơn giản với Keras như sau:

model = keras.applications.mobilenet.MobileNet(classes=2, weights=None)

Mọi người có thể sử dụng model.summary() để hiển thị số lượng các tham số của mô hình

Hướng dẫn dùng epoch training trong PHP

Mapping label

Vì mô hình của chúng ta là mô hình phân loại nên chúng ta sẽ cần sử dụng hàm loss là cross_entropy để tính toán. Chính vì thế nên việc đầu tiên là chuyển các class từ boss thành 1 và other thành 0. Chúng ta thực hiện như sau

# Mapping label

mapped_labels = list(map(lambda x: 1 if x == 'boss' else 0, labels))

from keras.utils import np_utils

y_data = np_utils.to_categorical(mapped_labels)

Bước 5: Phân chia dữ liệu

Chúng ta sử dụng thư viện train_test_split để tiến hành phân chia dữ liệu thành hai tập training và testing. Giống như bao bài toán khác 😃😃😃

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(images, y_data, test_size=0.2)

Bước 6: Training thuật toán

Giờ là lúc chúng ta dạy cho mô hình biết được đâu là boss và đâu không phải là boss rồi đấy. Có một lưu ý là do mạng Mobilenet là một hàm khá lớn dù là 2 class nhưng số lượng tham số cũng lên đến 3,230,914 nên chúng ta cần sử dụng nhiều dữ liệu hơn để tránh bị Overfiting khiến cho mô hình kém hiệu quả. Dù sao thì dữ liệu vẫn là yếu tố quan trọng nhất phải không các bạn. Tiếp theo chúng ta cần complie mô hình

Complie mô hình

model.compile(loss='categorical_crossentropy',

optimizer='adam',

metrics=['accuracy'])

Đặt checkpoint

Việc đặt checkpoint rất quan trọng trong quá trình training mô hình. Giúp chúng ta lưu lại được mô hình tốt nhất theo một tiêu chí nào đó ví dụ như val_loss hay val_accuracy cũng là cách để chúng ta phòng tránh trường hợp đang training thì mất điện hay muốn training tiếp trong lần sau mà không cần training lại từ đâu. Tóm lại là phải viết checkpoint vào không mất mô hình đừng kêu 😂😂😂

from keras.callbacks import ModelCheckpoint

model_file = "boss_model/model_mobilenet.hdf5"

checkpoint = ModelCheckpoint(model_file, monitor='val_loss', verbose=1, save_best_only=True, mode='min')

callbacks_list = [checkpoint]

Training

Sau cùng là bước training

model.fit(x=X_train, y=y_train, batch_size=16, epochs=100, verbose=1, validation_data=(X_test, y_test), callbacks=callbacks_list)

Các bạn cứ đợi và theo dõi thôi nhé. Do tập dữ liệu của mình nhỏ khoảng 750 ảnh nên việc training cũng sẽ diễn ra rất nhanh thôi. Đây là kết quả training trên máy của mình sau vài epochs

1

2

3

4

5

6

7

8

9

10

11

12

Epoch 1/100

750/750 [==============================] - 5s 37ms/step - loss: 0.3298 - acc: 0.8667 - val_loss: 0.0221 - val_acc: 1.0000

Epoch 00001: val_loss improved from inf to 0.02205, saving model to boss_model/model_mobilenet.hdf5

Epoch 2/100

750/750 [==============================] - 3s 7ms/step - loss: 0.0143 - acc: 0.9600 - val_loss: 0.0159 - val_acc: 0.9465

Epoch 00002: val_loss improved from 0.02205 to 0.01592, saving model to boss_model/model_mobilenet.hdf5

Epoch 3/100

750/750 [==============================] - 3s 7ms/step - loss: 0.0017 - acc: 0.9952 - val_loss: 0.0027 - val_acc: 0.9815

Bước 7: Chuẩn bị mô hình cho deploy

Lưu mô hình

Sau khi tiến hành training lại mô hình nhiều lần chúng ta sẽ thu được một mô hình tốt nhất và sử dụng nó để deploy lên hệ thống thực. Việc này được thực hiện như sau:

model.save('boss_model/final_model.h5')

Load lại mô hình

Và sau đó các bạn thử load lại mô hình này và predict một vài mẫu dữ liệu xem sao nhé:

from keras.models import load_model

import keras

from keras.utils.generic_utils import CustomObjectScope

# Load pretrained model

with CustomObjectScope({'relu6': keras.applications.mobilenet.relu6,'DepthwiseConv2D': keras.applications.mobilenet.DepthwiseConv2D}):

model = load_model('./boss_model/final_model.h5')

Một lưu ý là chúng ta cần phải chạy qua các bước tiền xử lý khi dự đoán, giống hệt lúc chúng ta training.

Bước 8: Deploy bằng OpenCV

Xử lý model để dự đoán

Việc đầu tiên cần làm là Tạo file boss_model.py. Chúng ta sử dụng file này để load model đã được lưu từ các bước trên bao gồm cả các hàm về xử lý dữ liệu và dự đoán kết quả

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

import cv2

import keras

import numpy as np

from keras.models import load_model

from keras.preprocessing import image

from keras.utils.generic_utils import CustomObjectScope

# Load pretrained model

with CustomObjectScope({'relu6': keras.applications.mobilenet.relu6,'DepthwiseConv2D': keras.applications.mobilenet.DepthwiseConv2D}):

model = load_model('./model/model.h5')

IMAGE_SIZE=224

def prepare_image(img):

img_array = image.img_to_array(img)

img_array_expanded_dims = np.expand_dims(img_array, axis=0)

return keras.applications.mobilenet.preprocess_input(img_array_expanded_dims)

def predict(img):

"""

Predict face crop from frame

:param img:

:return: If boss is appear when open the code IDE

"""

try:

img = cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE), interpolation=cv2.INTER_AREA)

probs = model.predict(prepare_image(img))

is_boss = np.argmax(probs[0])

return is_boss

except:

return False

Detect khuôn mặt bằng dlib

Giống như mô tả ở phái đầu tiên của bài viết, trong quá trình dự đoán chúng ta cần phải detect khuôn mặt và sử dụng một thư viện rất nổi tiếng đó là dlib. Quá trình xử lý của nó như sau:

import dlib

hog_face_detector = dlib.get_frontal_face_detector()

faces_hog = hog_face_detector(image)

Kết quả của nó như sau:

Hướng dẫn dùng epoch training trong PHP

Sử dụng OpenCV để stream dữ liệu từ Webcam

Chúng ta cần sử dụng dữ liệu stream từ webcam để theo dõi sếp và phát hiện ra khi nào sếp đến gần một cách tức thời. Việc này có thể thực hiện bằng cách sử dụng webcam và OpenCV để stream dữ liệu. Về cơ bản chúng ta có thể thực hiện nó như sau:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

import cv2

cap = cv2.VideoCapture(0)

while True:

ret, frame = cap.read()

if ret:

# Excute frame here

cv2.imshow("frame", frame)

key = cv2.waitKey(1)

if key == 27:

break

cap.release()

cv2.destroyAllWindows()

Xử lý crop mặt và dự đoán

Chúng ta sẽ crop từng khuôn mặt trong từng frame và dự đoán kết quả. Nếu là boss thì thực hiện mở ngay cửa sổ code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

if ret:

# Resize window

cv2.namedWindow('frame', cv2.WINDOW_NORMAL)

cv2.resizeWindow('frame', 400, 400)

# Resize frame for decrease predict time

scale = 0.5

resize_frame = cv2.resize(frame, (int(frame.shape[1]*scale), int(frame.shape[0]*scale)))

faces_hog = hog_face_detector(resize_frame)

frame_h, frame_w, _ = frame.shape

reindex_x = lambda x: max(min(x, frame_w), 1)

reindex_y = lambda x: max(min(x, frame_h), 1)

# loop over detected faces

for face in faces_hog:

x = reindex_x(int(face.left() / scale))

y = reindex_y(int(face.top() / scale))

r = reindex_x(int(face.right() / scale))

b = reindex_y(int(face.bottom() / scale))

# draw box over face

crop_face = frame[x: r, y: b]

is_boss = predict(crop_face)

if is_boss:

cv2.putText(frame, "BOSS", (10, 100), cv2.FONT_HERSHEY_SIMPLEX, 2,

(0, 0, 255), 4)

cv2.rectangle(frame, (x, y), (r, b), (0, 0, 255), 2)

boss_count += 1

# Open your IDE application for coding

if boss_count > 3:

os.system('open -a "PyCharm CE"')

boss_count = 0

else:

cv2.putText(frame, "NORMAL", (10, 100), cv2.FONT_HERSHEY_SIMPLEX, 2,

(0, 255, 0), 4)

cv2.rectangle(frame, (x, y), (r, b), (0, 255, 0), 2)

Mọi người có thể tham khảo kĩ hơn source code trong file này tại đây

Source code

Các bạn có thể tham khảo source code của bài viết tại đây

Cảm ơn các bạn đã theo dõi bài viết hẹn gặp lại trong những bài viết tiếp theo.

Nguồn: Sưu tầm từ internet via Devmaster