[딥러닝] Convolutional Neural Network(tensorflow) 기반 얼굴 인식 프로젝트 (3)

이벤트 주소: CSDN 21일 학습 챌린지

머리말

얼마 전 연구 끝에 LeNet-5 손글씨 숫자의 도입부터 최근 날씨 인식 연구에 이르기까지. 저는 C++/Qt 개발에 종사하고 있고 Qt에 익숙하기 때문에 큰 투표를 하고 싶습니다. 그래서 Qt 인터페이스 기반의 얼굴 인식을 구현하고 싶습니다.

Convolutional Neural Networks의 개념이 생소 하다면 Convolution은 실제로 무엇을합니까?
신경망의 훈련 과정이나 환경을 구축하는 방법을 이해하고 싶다면 이것을 읽을 수 있습니다. 기사: 환경 구축 및 교육 과정

이 프로젝트를 배우고 싶다면 첫 번째 기사 : Convolutional Neural Network (tensorflow) 기반 얼굴 인식 프로젝트 (1) 두
번째 기사 : Convolutional Neural Network (tensorflow) 기반 얼굴 인식 프로젝트 (2)

기본 아이디어

구체적인 단계는 다음과 같습니다.

  1. 먼저 데이터를 수집해야 하는 제 생각은 OpenCV를 통해 카메라를 호출하여 얼굴 사진을 수집하는 것입니다.
  2. 그런 다음 주로 데이터 세트, 훈련 세트, 검증 세트 및 테스트 세트를 분류하기 위해 전처리를 수행합니다.
  3. 모델 학습을 시작하려면 미리 레이블 키-값 쌍을 만드십시오.
  4. 얼굴 인식 효과를 테스트하고 OpenCV를 통해 얼굴 사진을 캡처한 다음 이미지를 전처리하고 최종적으로 모델에 전달한 다음 인식 결과를 텍스트 형식으로 화면에 인쇄하고 q를 입력할 때까지 순환하여 종료합니다.

이 문서는 주로 위 단계의 세 번째 단계를 구현합니다.

활성화 기능

신경망의 각 계층의 I/O는 선형 합산의 전체 프로세스이므로 이전 계층에서 일련의 선형 변환을 수행하는 한 다음 계층의 출력을 성공적으로 얻을 수 있습니다. 활성화 함수가 없으면 신경망을 아무리 복잡하게 만들든 레이어가 몇 개이든 최종 출력은 모두 키의 선형 조합이므로 간단한 선형 조합으로는 더 복잡한 문제를 처리할 수 없습니다. 활성화 함수를 도입한 후에는 일반 활성화 함수가 모두 비선형임을 알 수 있으므로 신경 세포에 비선형성을 도입하면 신경망이 비선형 요소에 가까워질 수 있으며 신경망을 적용할 수 있습니다. 많은 수의 비선형 모델에

시그모이드 함수

시그모이드 함수는 부드럽고 유도하기 쉬우며 값 범위는 [0, 1]입니다. 원형 시스템에서 삼각 함수 계산 문제를 풀고 선형 시스템에서 곱셈과 나눗셈 문제를 풉니다. 공식은 다음과 같습니다
여기에 이미지 설명 삽입
. 순환 시스템, 선형 시스템 및 쌍곡선 시스템 등에 적용하여 서로 다른 시스템에서 서로 다른 복잡한 컴퓨팅 문제를 해결할 수 있습니다.
여기에 이미지 설명 삽입

Tanh/쌍곡선 탄젠트 활성화 함수

쌍곡선 활성화 함수의 일종으로, 일반적으로 수학적 언어로 tanh로 표기되며, Sigmoid 함수의 0을 중심으로 출력할 수 있지만 기울기가 사라지는 문제는 여전히 존재합니다. 그 본질은 여러 층이 반복해서 전달된다는 것이므로 데이터가 너무 작고 층이 많으면 결국 0이 될 수 있습니다. 그래서 함수의 미분을 제어한 후에 이 문제는 어느 정도 해결되었습니다.

여기에 이미지 설명 삽입

ReLU 활성화 기능

정식 명칭은 선형 정류 함수로 인공 신경망에서 매우 일반적으로 사용되는 비선형 함수로 일반적으로 램프 함수와 이 함수에서 파생된 일련의 변형입니다.
여기에 이미지 설명 삽입

다음과 같은 많은 장점이 있습니다. 입력 값이 양수인 한 포화 영역에 들어가지 않고 다른 활성화 함수에 비해 계산 속도가 훨씬 빠릅니다. 그러나 성공적으로 해결되지 않은 문제가 있습니다. 즉, 음수 값을 입력하면 함수가 완전히 실패하고 이때 기울기는 0이 됩니다. 물론 앞서 언급한 sigmoid 함수와 tanh 함수도 같은 문제를 가지고 있습니다. 그리고 0을 중심으로 하는 함수가 아니기 때문에 도출이 매우 어렵고 이를 지원하기 위해서는 많은 함수가 필요합니다. 공식:여기에 이미지 설명 삽입

손실 함수

손실 함수는 모델의 예측 값 f(x)와 실제 값 Y의 차이를 측정하는 데 사용되는 연산 함수입니다. 일반적으로 L(Y, f(x)를 사용하는 음이 아닌 실수 값 함수입니다. ) - 손실 함수가 작을수록 모델의 견고성이 우수함을 나타냅니다.

효과

손실 함수는 주로 모델의 훈련 단계에서 사용되며, 훈련 데이터의 각 배치가 모델로 전송된 후 예측 값은 순방향 전파를 통해 출력되고 손실 함수는 예측 값과 실제 값의 차이를 계산합니다. 가치, 즉 손실 가치. 손실 값을 얻은 후 모델은 역전파를 통해 각 매개변수를 업데이트하여 실제 값과 예측 값 사이의 손실을 줄여 모델에서 생성된 예측 값이 실제 값에 더 가깝게 이동하여 학습 목적을 달성합니다. .

신경망 모델 구축

매개변수 설명

매번 많은 매개변수가 있을 것입니다. 여기서는 매개변수에 대해 소개하겠습니다.

batch_size : 각 반복에서 캡처된 학습 샘플의 수를 지정합니다.
nb_epoch : 학습 회전 수
border_mode : 컨볼루션 레이어의 매개변수를 동일하게 선택하면 컨볼루션 연산의 입력 및 출력 크기가 동일하게 유지됩니다. 유효를 선택하면 컨볼루션 후에 크기가 작아집니다.
verbose : 로그 표시 0은 표준 출력 스트림에 대한 로그 정보를 출력하지 않음을 의미합니다. 1은 진행률 표시줄 레코드를 출력함을 의미합니다. 2는 각 에포크에 대해 한 줄 레코드를 출력합니다.

CNN 모델

4개의 convolution layer, 6개의 activation layer, 2개의 pooling layer, 3개의 dropout layer, 2개의 Dense layer, 1개의 Flatten layer를 포함하여 총 18개의 layer가 있습니다.

    def build_model(self, dataset, nb_classes=9):
        # 构建一个空的网络模型,它是一个线性堆叠模型,各神经网络层会被顺序添加,专业名称为序贯模型或线性堆叠模型
        self.model = Sequential()

        # 以下代码将顺序添加CNN网络需要的各层,一个add就是一个网络层
        self.model.add(Convolution2D(32, 3, 3, border_mode='same',
                                     input_shape=dataset.input_shape))  # 1 2维卷积层
        self.model.add(Activation('relu'))  # 2 激活函数层

        self.model.add(Convolution2D(32, 3, 3))  # 3 2维卷积层
        self.model.add(Activation('relu'))  # 4 激活函数层

        self.model.add(MaxPooling2D(pool_size=(2, 2)))  # 5 池化层
        self.model.add(Dropout(0.25))  # 6 Dropout层

        self.model.add(Convolution2D(64, 3, 3, border_mode='same'))  # 7  2维卷积层
        self.model.add(Activation('relu'))  # 8  激活函数层

        self.model.add(Convolution2D(64, 3, 3))  # 9  2维卷积层
        self.model.add(Activation('relu'))  # 10 激活函数层

        self.model.add(MaxPooling2D(pool_size=(2, 2)))  # 11 池化层
        self.model.add(Dropout(0.25))  # 12 Dropout层

        self.model.add(Flatten())  # 13 Flatten层
        self.model.add(Dense(512))  # 14 Dense层,又被称作全连接层
        self.model.add(Activation('relu'))  # 15 激活函数层
        self.model.add(Dropout(0.5))  # 16 Dropout层
        self.model.add(Dense(nb_classes))  # 17 Dense层
        self.model.add(Activation('softmax'))  # 18 分类层,输出最终结果

        # 输出网络结构
        self.model.summary()

네트워크 구조

다음은 신경망의 구조이며, 총 파라미터 수는 6M입니다.

Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 64, 64, 32)        896       
_________________________________________________________________
activation_1 (Activation)    (None, 64, 64, 32)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 62, 62, 32)        9248      
_________________________________________________________________
activation_2 (Activation)    (None, 62, 62, 32)        0         
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 31, 31, 32)        0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 31, 31, 32)        0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 31, 31, 64)        18496     
_________________________________________________________________
activation_3 (Activation)    (None, 31, 31, 64)        0         
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 29, 29, 64)        36928     
_________________________________________________________________
activation_4 (Activation)    (None, 29, 29, 64)        0         
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 14, 14, 64)        0         
_________________________________________________________________
dropout_2 (Dropout)          (None, 14, 14, 64)        0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 12544)             0         
_________________________________________________________________
dense_1 (Dense)              (None, 512)               6423040   
_________________________________________________________________
activation_5 (Activation)    (None, 512)               0         
_________________________________________________________________
dropout_3 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 10)                5130      
_________________________________________________________________
activation_6 (Activation)    (None, 10)                0         
=================================================================
Total params: 6,493,738
Trainable params: 6,493,738
Non-trainable params: 0

모델 훈련

이해가 되지 않는다면 코드의 주석을 보십시오.

    def train(self, dataset, batch_size=20, nb_epoch=10, data_augmentation=True):
        # 参数batch_size的作用即在于此,其指定每次迭代训练样本的数量
        # nb_epoch 训练轮换次数
        sgd = SGD(lr=0.01, decay=1e-6,
                  momentum=0.9, nesterov=True)  # 采用SGD+momentum的优化器进行训练,首先生成一个优化器对象
        self.model.compile(loss='categorical_crossentropy',
                           optimizer=sgd,
                           metrics=['accuracy'])  # 完成实际的模型配置工作

        # 不使用数据提升,所谓的提升就是从我们提供的训练数据中利用旋转、翻转、加噪声等方法创造新的
        # 训练数据,有意识的提升训练数据规模,增加模型训练量
        if not data_augmentation:
            self.model.fit(dataset.train_images,
                           dataset.train_labels,
                           batch_size=batch_size,
                           nb_epoch=nb_epoch,
                           validation_data=(dataset.valid_images, dataset.valid_labels),
                           shuffle=True,
                           verbose = 1)
        # 使用实时数据提升
        else:
            # 定义数据生成器用于数据提升,其返回一个生成器对象datagen,datagen每被调用一
            # 次其生成一组数据(顺序生成),节省内存,其实就是python的数据生成器
            datagen = ImageDataGenerator(
                featurewise_center=False,  # 是否使输入数据去中心化(均值为0),
                samplewise_center=False,  # 是否使输入数据的每个样本均值为0
                featurewise_std_normalization=False,  # 是否数据标准化(输入数据除以数据集的标准差)
                samplewise_std_normalization=False,  # 是否将每个样本数据除以自身的标准差
                zca_whitening=False,  # 是否对输入数据施以ZCA白化
                rotation_range=20,  # 数据提升时图片随机转动的角度(范围为0~180)
                width_shift_range=0.2,  # 数据提升时图片水平偏移的幅度(单位为图片宽度的占比,0~1之间的浮点数)
                height_shift_range=0.2,  # 同上,只不过这里是垂直
                horizontal_flip=True,  # 是否进行随机水平翻转
                vertical_flip=False)  # 是否进行随机垂直翻转

            # 计算整个训练样本集的数量以用于特征值归一化、ZCA白化等处理
            datagen.fit(dataset.train_images)

            # 利用生成器开始训练模型
            self.model.fit_generator(datagen.flow(dataset.train_images, dataset.train_labels,
                                                  batch_size=batch_size),
                                     samples_per_epoch=dataset.train_images.shape[0],
                                     nb_epoch=nb_epoch,
                                     validation_data=(dataset.valid_images, dataset.valid_labels),
                                     verbose = 1)

훈련 결과

최종 인식 효과도 99.28%에 달했다.

Epoch 1/10
 - 45s - loss: 1.5003 - accuracy: 0.4488 - val_loss: 0.2484 - val_accuracy: 0.9661
Epoch 2/10
 - 45s - loss: 0.5669 - accuracy: 0.8032 - val_loss: 0.1429 - val_accuracy: 0.9331
Epoch 3/10
 - 46s - loss: 0.3572 - accuracy: 0.8778 - val_loss: 0.3107 - val_accuracy: 0.8703
Epoch 4/10
 - 45s - loss: 0.2577 - accuracy: 0.9139 - val_loss: 0.0277 - val_accuracy: 0.9940
Epoch 5/10
 - 46s - loss: 0.2046 - accuracy: 0.9350 - val_loss: 0.0275 - val_accuracy: 0.9940
Epoch 6/10
 - 45s - loss: 0.1824 - accuracy: 0.9400 - val_loss: 0.0242 - val_accuracy: 0.9930
Epoch 7/10
 - 46s - loss: 0.1512 - accuracy: 0.9473 - val_loss: 0.1970 - val_accuracy: 0.9341
Epoch 8/10
 - 46s - loss: 0.1426 - accuracy: 0.9541 - val_loss: 0.0149 - val_accuracy: 0.9960
Epoch 9/10
 - 46s - loss: 0.1474 - accuracy: 0.9541 - val_loss: 0.0391 - val_accuracy: 0.9930
Epoch 10/10
 - 45s - loss: 0.1103 - accuracy: 0.9666 - val_loss: 0.0133 - val_accuracy: 0.9928

평가 모델

모델의 정확도가 요구 사항을 충족할 수 있는지 여부를 확인하는 데 사용됩니다.

로드 모델

    def load_model(self, file_path=MODEL_PATH):
        self.model = load_model(file_path)

평가 시험

    def evaluate(self, dataset):
        score = self.model.evaluate(dataset.test_images, dataset.test_labels, verbose=1)
        print("%s: %.2f%%" % (self.model.metrics_names[1], score[1] * 100))

시험 결과

정확한 비율은 99.16%입니다.
여기에 이미지 설명 삽입

요약하다

이 장의 주요 어려움은 항상 미세 조정해야 하는 모델의 설계에 있습니다. 그런 다음 손실 함수, 활성화 함수 등과 같은 몇 가지 개념을 이해해야 합니다.

рекомендация

отblog.csdn.net/qq_45254369/article/details/126412574
рекомендация