美文网首页
卷积神经网络的应用—手势识别

卷积神经网络的应用—手势识别

作者: 此间不留白 | 来源:发表于2019-11-19 21:08 被阅读0次

一步步实现卷积神经网络的文章中,详细介绍了如何利用numpy实现了一个卷积神经网络,本篇文章将利用tensorflow实现一个卷积神经网络的手势识别项目。

导入相关库

利用tensorflow实现一个卷积神经网络时,首先,需要导入需要用到的python库,如下所示:


import math
import numpy as np
import h5py
import matplotlib.pyplot as plt
import scipy
from PIL import Image
from scipy import ndimage
import tensorflow as tf
from tensorflow.python.framework import ops
from cnn_utils import *

%matplotlib inline
np.random.seed(1)

数据集处理

加载数据集

首先,加载准备好的数据集,如下代码所示:


def load_dataset():
    train_dataset = h5py.File('datasets/train_signs.h5', "r")
    train_set_x_orig = np.array(train_dataset["train_set_x"][:]) #训练集特征
    train_set_y_orig = np.array(train_dataset["train_set_y"][:]) # 训练集标签

    test_dataset = h5py.File('datasets/test_signs.h5', "r")
    test_set_x_orig = np.array(test_dataset["test_set_x"][:]) # 测试集特征
    test_set_y_orig = np.array(test_dataset["test_set_y"][:]) # 测试集标签
    classes = np.array(test_dataset["list_classes"][:]) # 类别列表
    
    train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0]))
    test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0]))
    
    return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes

数据集的表示如下所示:


加载数据集,并随机显示其中的一个数据,如下所示:

X_train_orig, Y_train_orig, X_test_orig, Y_test_orig, classes = load_dataset()
index = 6
plt.imshow(X_train_orig[index])
print ("y = " + str(np.squeeze(Y_train_orig[:, index])))

数据归一化处理

图像矩阵的取值范围是(0-255),需要对图像数据归一化处理,即每个像素值除以255,具体代码实现如下所示:


X_train = X_train_orig/255.
X_test = X_test_orig/255.

独热编码处理

对于多元分类问题,需要使用独热编码进行处理,关于独热编码的实现,有两种方法,一种是利用numpy实现,另外一种是tensorflow实现,这两种方法都在tensorflow中有过介绍,这里,直接给出独热编码的numpy实现,如下代码所示:


def convert_to_one_hot(Y, C):
    Y = np.eye(C)[Y.reshape(-1)].T
    return Y

为了确保后续程序的运行正确,可以打印出数据集的维数,如下代码所示:



Y_train = convert_to_one_hot(Y_train_orig, 6).T
Y_test = convert_to_one_hot(Y_test_orig, 6).T
print ("number of training examples = " + str(X_train.shape[0]))
print ("number of test examples = " + str(X_test.shape[0]))
print ("X_train shape: " + str(X_train.shape))
print ("Y_train shape: " + str(Y_train.shape))
print ("X_test shape: " + str(X_test.shape))
print ("Y_test shape: " + str(Y_test.shape))

创建placeholder

tensorflow程序需要在运行之前,创建placeholder,当运行tensorflow的session时,再将真正数据填入其中,类似于函数形参和实参的概念,具体实现如下代码所示:

def create_placeholders(n_H0, n_W0, n_C0, n_y):
    """
    为tensorflow的session创建placeholder
    
    参数:
    n_H0 -- 标量,输入图像的高度
    n_W0 -- 标量,输入图像的宽度
    n_C0 --标量,输入图像的通道
    n_y -- 标量,分类的类别数
        
    Returns:
    X -- placeholder for the data input, of shape [None, n_H0, n_W0, n_C0] and dtype "float"
    Y -- placeholder for the input labels, of shape [None, n_y] and dtype "float"
    """

  
    X = tf.placeholder(name='X', shape=(None, n_H0, n_W0, n_C0), dtype=tf.float32)
    Y = tf.placeholder(name='Y', shape=(None, n_y), dtype=tf.float32)
  
    return X, Y

初始化权重参数

在tensorflow实现权重参数时,只需要实现W参数即可,而不需要手动实现偏置参数b。另外,用tensorflow实现卷积神经网络时,只需初始化卷积层的权重参数即可,而全连接层的参数,tensorflow会自动实现。

具体实现,如下代码所示;


def initialize_parameters():
  
    tf.set_random_seed(1)                         
    W1 = tf.get_variable(name='W1', dtype=tf.float32, shape=(4, 4, 3, 8), initializer=tf.contrib.layers.xavier_initializer(seed = 0))
    W2 = tf.get_variable(name='W2', dtype=tf.float32, shape=(2, 2, 8, 16), initializer=tf.contrib.layers.xavier_initializer(seed = 0))
    parameters = {"W1": W1,
                  "W2": W2}
    
    return parameters

用tensorflow实现前向传播

用tensorflow实现卷积神经网络前向传播的过程如下所示:

def forward_propagation(X, parameters):
    """
    实现前向传播的模型
    CONV2D -> RELU -> MAXPOOL -> CONV2D -> RELU -> MAXPOOL -> FLATTEN -> FULLYCONNECTED
    
    参数:
    X -- 输入数据集
    参数 -- python字典,包含权重参数

    返回值:
    Z3 -- 最后一层线性单元的输出
    """
    
    #得到参数
    W1 = parameters['W1']
    W2 = parameters['W2']
  
    # 卷积步长是1,填充方式为same
    Z1 = tf.nn.conv2d(input=X, filter=W1, strides=(1, 1, 1, 1), padding='SAME')
    # 线性激活函数
    A1 = tf.nn.relu(Z1)
    # 最大池化层,步长为1
    P1 = tf.nn.max_pool(value=A1, ksize=(1, 8, 8, 1), strides=(1, 8, 8, 1), padding='SAME')
    # 卷积层,过滤矩阵为W2
    Z2 = tf.nn.conv2d(input=P1, filter=W2, strides=(1, 1, 1, 1), padding='SAME')
    # 线性激活单元
    A2 = tf.nn.relu(Z2)
    # 最大池化层,4×4的窗口,填充方式为‘SAME’
    P2 = tf.nn.max_pool(value=A2, ksize=(1, 4, 4, 1), strides=(1, 4, 4, 1), padding='SAME')
    #转化为一维
    P2 = tf.contrib.layers.flatten(inputs=P2)
    # 使用非线性激活函数的全连接层
    # 输出层,包含六个神经元.
    Z3 = tf.contrib.layers.fully_connected(P2, 6, activation_fn=None)

    return Z3

计算损失

tensoflow提供了以下两个函数用以计算损失,具体解释如下所示:

  • tf.nn.softmax_cross_entropy_with_logits(logits = Z3, labels = Y): 该函数既可以计算softmax激活函数,也可以计算由此产生的softmax的熵损失,详细介绍可以查阅 相关文档。
  • cost=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=Z3, labels=Y)):计算整个张量维度的元素均值,用它来对所有样本的损失求和,以获得总体损失。详细信息,可以参考相关文档。

def compute_cost(Z3, Y):
  
    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=Z3, labels=Y))
   
    return cost

构建模型

通过以上准备,现在可以构建一个卷积神经网络,具体步骤,如下所示:

  • 创建placeholder
  • 初始化参数
  • 前向传播
  • 计算损失
  • 进行优化

具体实现,如下代码所示:


def model(X_train, Y_train, X_test, Y_test, learning_rate = 0.009,
          num_epochs = 100, minibatch_size = 64, print_cost = True):
    """
用tensorflow实现一个三层的卷积神经网络:
    CONV2D -> RELU -> MAXPOOL -> CONV2D -> RELU -> MAXPOOL -> FLATTEN -> FULLYCONNECTED
    
    参数:
    X_train --训练集 shape (None, 64, 64, 3)
    Y_train -- 训练集输出,shape (None, n_y = 6)
    X_test -- 测试集输入 (None, 64, 64, 3)
    Y_test -测试集输出 shape (None, n_y = 6)
    learning_rate --学习率
    num_epochs -- 迭代次数
    minibatch_size -- min-batch的尺寸
    print_cost -- 为True时,打印出每100次迭代的损失
    
    返回值:
    train_accuracy -- 训练集的精度(X_train)
    test_accuracy -- 测试集的精度 (X_test)
    parameters -- 用于预测的模型参数
    """
    
    ops.reset_default_graph()                         # 能够在不覆盖tf变量的情况下重新运行模型
    tf.set_random_seed(1)                             # 随机种子,保持结果一致
    seed = 3                                          
    (m, n_H0, n_W0, n_C0) = X_train.shape             
    n_y = Y_train.shape[1]                            
    costs = []                                        # 跟踪损失
    
    # 创建一个placeholder
   
    X, Y = create_placeholders(n_H0, n_W0, n_C0, n_y)

    # 初始化参数

    parameters = initialize_parameters()

    # 前向传播
   
    Z3 = forward_propagation(X, parameters)
 
    #损失函数

    cost = compute_cost(Z3, Y)

    
    # 反向传播,定义一个tensorflow优化器,用 AdamOptimizer 最小化损失

    optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
    
    # 初始化全局变量
    init = tf.global_variables_initializer()
     
    # 运行一个session进行计算
    with tf.Session() as sess:
        
    
        sess.run(init)
        
        # 迭代训练
        for epoch in range(num_epochs):

            minibatch_cost = 0.
            num_minibatches = int(m / minibatch_size) # min-batch的数量
            seed = seed + 1
            minibatches = random_mini_batches(X_train, Y_train, minibatch_size, seed)

            for minibatch in minibatches:

                # 选择一个minbatch
                (minibatch_X, minibatch_Y) = minibatch
               
       
                _ , temp_cost = sess.run([optimizer, cost], feed_dict={X:minibatch_X, Y:minibatch_Y})
             
                minibatch_cost += temp_cost / num_minibatches
                

            # 打印出每次迭代的损失
            if print_cost == True and epoch % 5 == 0:
                print ("Cost after epoch %i: %f" % (epoch, minibatch_cost))
            if print_cost == True and epoch % 1 == 0:
                costs.append(minibatch_cost)
        
        
        # 绘制损失
        plt.plot(np.squeeze(costs))
        plt.ylabel('cost')
        plt.xlabel('iterations (per tens)')
        plt.title("Learning rate =" + str(learning_rate))
        plt.show()

        # 预测,取得输出值为1的索引
        predict_op = tf.argmax(Z3, 1)
        correct_prediction = tf.equal(predict_op, tf.argmax(Y, 1))
        
        # 计算测试集的精度
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
        print(accuracy)
        train_accuracy = accuracy.eval({X: X_train, Y: Y_train})
        test_accuracy = accuracy.eval({X: X_test, Y: Y_test})
        print("Train Accuracy:", train_accuracy)
        print("Test Accuracy:", test_accuracy)
                
        return train_accuracy, test_accuracy, parameters

最后,绘制出的损失曲线如下所示和精度如下所示:

相关文章

  • CNN

    参考:CNN卷积神经网络原理讲解+图片识别应用(附源码)卷积神经网络 – CNN深入学习卷积神经网络(CNN)的原...

  • 卷积神经网络的应用—手势识别

    在一步步实现卷积神经网络的文章中,详细介绍了如何利用numpy实现了一个卷积神经网络,本篇文章将利用tensorf...

  • 深度学习入门--卷积神经网络-卷积层

    卷积神经网络(CNN)被广泛应用于图像识别这个领域,几乎所有的基于深度学习的图像识别都是以卷积神经网络作为技术基础...

  • Task03 字符识别模型

    一、CNN模型 CNN,又称卷积神经网络,它是一种前馈的神经网络,在图像识别领域有着巨大的应用。 二、如何理解卷积...

  • 卷积神经网络学习(一)滤波器意义

    作者:荔枝boy 一. 卷积神经网络的发展 二. 卷积神经网络的重要性 三. 卷积神经网络与图像识别 四. 滤波器...

  • TensorFlow 实战Google深度学习框架(第2版)第六

    第六章:图像识别与卷积神经网络 * 6.1图像识别问题简介&经典数据集* 6.2卷积神经网络简介* 6.3卷积神经...

  • MNIST手写字体识别(机器学习)

    练习:使用 CNN(卷积神经网络)识别 MNIST手写字体— Tensorflow 本文利用卷积神经网络将 MNI...

  • 18-tensorflow

    基础 深度学习介绍 深度学习,如深度神经网络、卷积神经网络和递归神经网络已被应用计算机视觉、语音识别、自然语言处理...

  • 神经网络(一)

    神经网络 1. 神经网络基础 2. 浅层神经网络分析 3. 卷积神经网络 4. 卷积神经网络MNIST数字图片识别...

  • 再战机器学习—卷积神经网络

    卷积神经网络 卷积神经网络可能是离我们最近的神经网络,遍布在计算机视觉应用。通常卷积神经网络是由卷积层、池化层和全...

网友评论

      本文标题:卷积神经网络的应用—手势识别

      本文链接:https://www.haomeiwen.com/subject/hhugictx.html