百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Keras实例人脸识别

toyiye 2024-06-21 12:07 8 浏览 0 评论

1、 olivettifaces人脸数据库简介

Olivetti Faces是纽约大学的一个比较小的人脸库,由40个人的400张图片构成,即每个人的人脸图片为10张。每张图片的灰度级为8位,每个像素的灰度大小位于0-255之间,每张图片大小为64×64。如下图,这个图片大小是1190*942,一共有20*20张人脸,故每张人脸大小是(1190/20)*(942/20)即57*47=2679:


本文所用的训练数据就是这张图片,400个样本,40个类别

要运行CNN算法,这张图片必须先转化为数组(或者说矩阵),这个用到python的图像库PIL,几行代码就可以搞定 。

训练机器学习算法,我们一般将原始数据分成训练数据(training_set)、验证数据(validation_set)、测试数据(testing_set)。本程序将training_set、validation_set、testing_set分别设置为320、40、40个样本。它们的label为0~39,对应40个不同的人。这部分的代码如下:


2、 伪代码讲解

1、数据的读取;标签的划分

# 读取整张图片的数据,并设置对应标签
def get_load_data(dataset_path):
    img = Image.open(dataset_path)
    # 数据归一化。asarray是使用原内存将数据转化为np.ndarray
    img_ndarray = np.asarray(img, dtype = 'float64')/255
    # 400 pictures, size: 57*47 = 2679  
    faces_data = np.empty((400, 2679))
    for row in range(20):  
       for column in range(20):
           # flatten可将多维数组降成一维
           faces_data[row*20+column] = np.ndarray.flatten(img_ndarray[row*57:(row+1)*57, column*47:(column+1)*47])

    # 设置图片标签
    label = np.empty(400)
    for i in range(40):
        label[i*10:(i+1)*10] = i
    label = label.astype(np.int)

    # 分割数据集:每个人前8张图片做训练,第9张做验证,第10张做测试;所以train:320,valid:40,test:40
    train_data = np.empty((320, 2679))
    train_label = np.empty(320)
    valid_data = np.empty((40, 2679))
    valid_label = np.empty(40)
    test_data = np.empty((40, 2679))
    test_label = np.empty(40)
    for i in range(40):
        train_data[i*8:i*8+8] = faces_data[i*10:i*10+8] # 训练集对应的数据
        train_label[i*8:i*8+8] = label[i*10 : i*10+8]   # 训练集对应的标签
        valid_data[i] = faces_data[i*10+8]   # 验证集对应的数据
        valid_label[i] = label[i*10+8]       # 验证集对应的标签
        test_data[i] = faces_data[i*10+9]    # 测试集对应的数据
        test_label[i] = label[i*10+9]        # 测试集对应的标签
    train_data = train_data.astype('float32')
    valid_data = valid_data.astype('float32')
    test_data = test_data.astype('float32')
       
    result = [(train_data, train_label), (valid_data, valid_label), (test_data, test_label)]
    return result

依照图片的path地址,读取图片的主要信息,根据上面的注释大家都能理解每一步都是做什么的,主要介绍以下几个地方:

  1. 设置图片标签:每10张图片设置一个相同的标签,
  2. 分割数据集:每个人10张照片中,前8张用做训练,第9张用做内测验证,第10张用做外测,也是按照像素索引进行划分;
  3. 函数的返回值就是3个元组,分别是训练集、内测验证集、外测测试集;

2、CNN网络的搭建

# CNN主体
def get_set_model(lr=0.005,decay=1e-6,momentum=0.9):
    model = Sequential()
    # 卷积1+池化1
    if K.image_data_format() == 'channels_first':
        model.add(Conv2D(nb_filters1, kernel_size=(3, 3), input_shape = (1, img_rows, img_cols)))
    else:
        model.add(Conv2D(nb_filters1, kernel_size=(2, 2), input_shape = (img_rows, img_cols, 1)))
    model.add(Activation('tanh'))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    # 卷积2+池化2
    model.add(Conv2D(nb_filters2, kernel_size=(3, 3)))
    model.add(Activation('tanh'))  
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))  

    # 全连接层1+分类器层
    model.add(Flatten())  
    model.add(Dense(1000))       #Full connection
    model.add(Activation('tanh'))  
    model.add(Dropout(0.5))  
    model.add(Dense(40))
    model.add(Activation('softmax'))  

    # 选择设置SGD优化器参数
    sgd = SGD(lr=lr, decay=decay, momentum=momentum, nesterov=True)  
    model.compile(loss='categorical_crossentropy', optimizer=sgd)
    return model  

Kreas框架是不是看起来很简洁,它的语法主体就包含在以下声明中:

from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.optimizers import SGD    # 梯度下降的优化器
  • Sequential:模型初始化
  • Dense:全连接层
  • Flatten:合并拉伸函数
  • SGD:optimizers,优化器
  • Dropout、Activation、Conv2D、MaxPooling2D就不介绍了,各自的参数含义也请参考卷积神经网络(CNN)原理

3、训练过程,保存参数

# 训练过程,保存参数
def get_train_model(model,X_train, Y_train, X_val, Y_val):
    model.fit(X_train, Y_train, batch_size = batch_size, epochs = epochs,  
          verbose=1, validation_data=(X_val, Y_val))
    # 保存参数
    model.save_weights('model_weights.h5', overwrite=True)  
    return model  

4、测试过程,调用参数

# 测试过程,调用参数
def get_test_model(model,X,Y):
    model.load_weights('model_weights.h5')  
    score = model.evaluate(X, Y, verbose=0)
    return score  

三、Kreas源码及结果展示

# -*- coding:utf-8 -*-
# -*- author:zzZ_CMing  CSDN address:https://blog.csdn.net/zzZ_CMing
# -*- 2018/06/05;11:41
# -*- python3.5
"""
olivetti Faces是纽约大学组建的一个比较小的人脸数据库。有40个人,每人10张图片,组成一张有400张人脸的大图片。
像素灰度范围在[0,255]。整张图片大小是1190*942,20行320列,所以每张照片大小是(1190/20)*(942/20)= 57*47
程序需配置h5py:python -m pip install h5py
博客地址:https://blog.csdn.net/zzZ_CMing,更多机器学习源码
"""
import numpy as np
from PIL import Image
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.optimizers import SGD    # 梯度下降的优化器
from keras.utils import np_utils
from keras import backend as K

# 读取整张图片的数据,并设置对应标签
def get_load_data(dataset_path):
    img = Image.open(dataset_path)
    # 数据归一化。asarray是使用原内存将数据转化为np.ndarray
    img_ndarray = np.asarray(img, dtype = 'float64')/255
    # 400 pictures, size: 57*47 = 2679  
    faces_data = np.empty((400, 2679))
    for row in range(20):  
       for column in range(20):
           # flatten可将多维数组降成一维
           faces_data[row*20+column] = np.ndarray.flatten(img_ndarray[row*57:(row+1)*57, column*47:(column+1)*47])

    # 设置图片标签
    label = np.empty(400)
    for i in range(40):
        label[i*10:(i+1)*10] = i
    label = label.astype(np.int)

    # 分割数据集:每个人前8张图片做训练,第9张做验证,第10张做测试;所以train:320,valid:40,test:40
    train_data = np.empty((320, 2679))
    train_label = np.empty(320)
    valid_data = np.empty((40, 2679))
    valid_label = np.empty(40)
    test_data = np.empty((40, 2679))
    test_label = np.empty(40)
    for i in range(40):
        train_data[i*8:i*8+8] = faces_data[i*10:i*10+8] # 训练集对应的数据
        train_label[i*8:i*8+8] = label[i*10 : i*10+8]   # 训练集对应的标签
        valid_data[i] = faces_data[i*10+8]   # 验证集对应的数据
        valid_label[i] = label[i*10+8]       # 验证集对应的标签
        test_data[i] = faces_data[i*10+9]    # 测试集对应的数据
        test_label[i] = label[i*10+9]        # 测试集对应的标签
    train_data = train_data.astype('float32')
    valid_data = valid_data.astype('float32')
    test_data = test_data.astype('float32')
       
    result = [(train_data, train_label), (valid_data, valid_label), (test_data, test_label)]
    return result

# CNN主体
def get_set_model(lr=0.005,decay=1e-6,momentum=0.9):
    model = Sequential()
    # 卷积1+池化1
    if K.image_data_format() == 'channels_first':
        model.add(Conv2D(nb_filters1, kernel_size=(3, 3), input_shape = (1, img_rows, img_cols)))
    else:
        model.add(Conv2D(nb_filters1, kernel_size=(2, 2), input_shape = (img_rows, img_cols, 1)))
    model.add(Activation('tanh'))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    # 卷积2+池化2
    model.add(Conv2D(nb_filters2, kernel_size=(3, 3)))
    model.add(Activation('tanh'))  
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))  

    # 全连接层1+分类器层
    model.add(Flatten())  
    model.add(Dense(1000))       #Full connection
    model.add(Activation('tanh'))  
    model.add(Dropout(0.5))  
    model.add(Dense(40))
    model.add(Activation('softmax'))  

    # 选择设置SGD优化器参数
    sgd = SGD(lr=lr, decay=decay, momentum=momentum, nesterov=True)  
    model.compile(loss='categorical_crossentropy', optimizer=sgd)
    return model  

# 训练过程,保存参数
def get_train_model(model,X_train, Y_train, X_val, Y_val):
    model.fit(X_train, Y_train, batch_size = batch_size, epochs = epochs,  
          verbose=1, validation_data=(X_val, Y_val))
    # 保存参数
    model.save_weights('model_weights.h5', overwrite=True)  
    return model  

# 测试过程,调用参数
def get_test_model(model,X,Y):
    model.load_weights('model_weights.h5')  
    score = model.evaluate(X, Y, verbose=0)
    return score  



# [start]
epochs = 35          # 进行多少轮训练
batch_size = 40      # 每个批次迭代训练使用40个样本,一共可训练320/40=8个网络
img_rows, img_cols = 57, 47         # 每张人脸图片的大小
nb_filters1, nb_filters2 = 20, 40   # 两层卷积核的数目(即输出的维度)

if __name__ == '__main__':  
    # 将每个人10张图片,按8:1:1的比例拆分为训练集、验证集、测试集数据
    (X_train, y_train), (X_val, y_val),(X_test, y_test) = get_load_data('olivettifaces.gif')
    
    if K.image_data_format() == 'channels_first':    # 1为图像像素深度
        X_train = X_train.reshape(X_train.shape[0],1,img_rows,img_cols)
        X_val = X_val.reshape(X_val.shape[0], 1, img_rows, img_cols)  
        X_test = X_test.reshape(X_test.shape[0], 1, img_rows, img_cols)  
        input_shape = (1, img_rows, img_cols)
    else:
        X_train = X_train.reshape(X_train.shape[0], img_rows, img_cols, 1)  
        X_val = X_val.reshape(X_val.shape[0], img_rows, img_cols, 1)  
        X_test = X_test.reshape(X_test.shape[0], img_rows, img_cols, 1)  
        input_shape = (img_rows, img_cols, 1)
    
    print('X_train shape:', X_train.shape)
    # convert class vectors to binary class matrices  
    Y_train = np_utils.to_categorical(y_train, 40)
    Y_val = np_utils.to_categorical(y_val, 40)
    Y_test = np_utils.to_categorical(y_test, 40)

    # 训练过程,保存参数
    model = get_set_model()
    get_train_model(model, X_train, Y_train, X_val, Y_val)
    score = get_test_model(model, X_test, Y_test)

    # 测试过程,调用参数,得到准确率、预测输出
    model.load_weights('model_weights.h5')
    classes = model.predict_classes(X_test, verbose=0)  
    test_accuracy = np.mean(np.equal(y_test, classes))
    print("last accuarcy:", test_accuracy)
    for i in range(0,40):
        if y_test[i] != classes[i]:
            print(y_test[i], '被错误分成', classes[i]);
    

运行结果:
X_train shape: (320, 57, 47, 1)
Train on 320 samples, validate on 40 samples
Epoch 1/35
320/320 [==============================] - 3s 10ms/step - loss: 3.6880 - val_loss: 3.6834
Epoch 2/35
320/320 [==============================] - 2s 6ms/step - loss: 3.6873 - val_loss: 3.6807
Epoch 3/35
320/320 [==============================] - 2s 5ms/step - loss: 3.6814 - val_loss: 3.6775
Epoch 4/35
320/320 [==============================] - 2s 6ms/step - loss: 3.6792 - val_loss: 3.6738
Epoch 5/35
320/320 [==============================] - 2s 6ms/step - loss: 3.6768 - val_loss: 3.6697
Epoch 6/35
320/320 [==============================] - 2s 6ms/step - loss: 3.6682 - val_loss: 3.6649
Epoch 7/35
320/320 [==============================] - 2s 6ms/step - loss: 3.6638 - val_loss: 3.6594
Epoch 8/35
320/320 [==============================] - 2s 6ms/step - loss: 3.6525 - val_loss: 3.6525
Epoch 9/35
320/320 [==============================] - 2s 7ms/step - loss: 3.6468 - val_loss: 3.6438
Epoch 10/35
320/320 [==============================] - 2s 7ms/step - loss: 3.6371 - val_loss: 3.6329
Epoch 11/35
320/320 [==============================] - 2s 6ms/step - loss: 3.6213 - val_loss: 3.6197
Epoch 12/35
320/320 [==============================] - 2s 6ms/step - loss: 3.6133 - val_loss: 3.6017
Epoch 13/35
320/320 [==============================] - 2s 6ms/step - loss: 3.5855 - val_loss: 3.5778
Epoch 14/35
320/320 [==============================] - 2s 6ms/step - loss: 3.5511 - val_loss: 3.5453
Epoch 15/35
320/320 [==============================] - 2s 6ms/step - loss: 3.5156 - val_loss: 3.5000
Epoch 16/35
320/320 [==============================] - 2s 6ms/step - loss: 3.4572 - val_loss: 3.4356
Epoch 17/35
320/320 [==============================] - 2s 5ms/step - loss: 3.3838 - val_loss: 3.3436
Epoch 18/35
320/320 [==============================] - 2s 6ms/step - loss: 3.2650 - val_loss: 3.2079
Epoch 19/35
320/320 [==============================] - 2s 5ms/step - loss: 3.0900 - val_loss: 3.0246
Epoch 20/35
320/320 [==============================] - 2s 6ms/step - loss: 2.8635 - val_loss: 2.7595
Epoch 21/35
320/320 [==============================] - 2s 7ms/step - loss: 2.5709 - val_loss: 2.4273
Epoch 22/35
320/320 [==============================] - 2s 6ms/step - loss: 2.2209 - val_loss: 2.0682
Epoch 23/35
320/320 [==============================] - 2s 5ms/step - loss: 1.8098 - val_loss: 1.7000
Epoch 24/35
320/320 [==============================] - 2s 5ms/step - loss: 1.4596 - val_loss: 1.3756
Epoch 25/35
320/320 [==============================] - 2s 5ms/step - loss: 1.1423 - val_loss: 1.1275
Epoch 26/35
320/320 [==============================] - 2s 6ms/step - loss: 0.8719 - val_loss: 0.9146
Epoch 27/35
320/320 [==============================] - 2s 6ms/step - loss: 0.7283 - val_loss: 0.7697
Epoch 28/35
320/320 [==============================] - 2s 6ms/step - loss: 0.5765 - val_loss: 0.6689
Epoch 29/35
320/320 [==============================] - 2s 6ms/step - loss: 0.4444 - val_loss: 0.5779
Epoch 30/35
320/320 [==============================] - 2s 6ms/step - loss: 0.4039 - val_loss: 0.5126
Epoch 31/35
320/320 [==============================] - 2s 5ms/step - loss: 0.3047 - val_loss: 0.4686
Epoch 32/35
320/320 [==============================] - 2s 6ms/step - loss: 0.2877 - val_loss: 0.4124
Epoch 33/35
320/320 [==============================] - 2s 6ms/step - loss: 0.2184 - val_loss: 0.3725
Epoch 34/35
320/320 [==============================] - 2s 5ms/step - loss: 0.1842 - val_loss: 0.3516
Epoch 35/35
320/320 [==============================] - 2s 5ms/step - loss: 0.1684 - val_loss: 0.3328
last accuarcy: 0.925
8.0 被错误分成 34
18.0 被错误分成 6
39.0 被错误分成 8

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码