深度卷积神经网络TensorFlow GPU实现

来源:互联网 发布:保健品可以网络销售 编辑:程序博客网 时间:2024/06/10 23:15

深度卷积神经网络TensorFlow GPU实现

Deep Learning CNN’s in Tensorflow with GPUs

Taylor Guo, 2017年6月11日

这里写图片描述

本文讲解卷积神经网络架构,如何在tensorflow中创建卷积神经网络,如何在图像标注上做预测。最后是如何在GPU上运行模型,这样就可以节省时间来创建更好的模型,而不是等待它们收敛。


主要内容:

  • 卷积神经网络介绍

  • 创建卷积神经网络 并 在CPU上训练

  • GPU上训练


先决条件:

  • 基本的机器学习知识

  • 基本的TensorFlow知识

  • AWS账号 (GPU)


卷积神经网络

卷积神经网络是目前图像分类的最新架构。广泛地应用于人脸识别,自动驾驶,物体识别。

基本架构

卷积神经网络的基本架构由3部分组成:卷积,池化 和 全连接。这些组件一起作用,学习输入图像的稠密特征表示。

卷积

这里写图片描述

卷积主要是由卷积核组成(最上面的绿色部分),也称为滤波器,是用一个滑动窗口从输入图像中提取特征。滤波器在输入图像上平移的位移称为步长。每次移动都会计算卷积核和当前输入图像区域的矩阵乘法。可以用多个滤波器堆叠来创建输入图像的高维表示。

如果滤波器没有均匀地与输入图像大小相映射会出现什么状况?

有两种方法处理滤波器大小和输入图像大小尺寸不同,same padding 和 valid padding。Same padding在输入图像的边界外补零(如上图所示)来保留输入图像的长宽。Valid padding不补边缘,在卷积时不会超过输入图像的边界。

通常都会使用same padding 或者 快速降低输入图像的维度。

最后是激活函数(通常是ReLU),对卷积后的结果进行非线性处理。ReLU和其他的激活函数不同,比如sigmoid和tanh,ReLU只有一边,是非对称的。这种一边的形式的激活特性可以让网络创建稀疏表示(隐藏单元是0值),可以增加计算效率。

这里写图片描述

池化

池化操作为了降低维度。它用一个函数对相邻元素数值进行求和。两个常用的函数是最大池化和平均池化。通过计算输入图像区域的最大值,输出图像将这个区域内的亮度值求和,(进行最大或平均)。

池化层也有一个内核,padding沿着步长移动。为了计算池化操作的输出图像的大小,可以用以下公式计算:

(输入图像宽度 - 内核宽度 + 2*padding) / 步长 + 1

这里写图片描述

全连接层

全连接层与神经网络比较类似。输入部分的每个神经元都和输出部分的每个神经元相连接;完全连接起来。因为这种连接,输出部分的每个神经元都只使用一次。

这里写图片描述

在卷积神经网络中,输入层通过池化后填入全连接层。根据不同的任务,用回归或分类算法创建想要的输出。

回顾

上面是卷积神经网络的构建。将输入图像传入卷积网络,提取高维特征。池化总结了图像中的空间特征,减小了维度。最后,这个特征表示传入全连接层给 分类器 或者 回归器。

这里写图片描述


TensorFlow 创建 卷积神经网络

现在已经了解了卷积神经网络,可以在TensorFlow中创建卷积神经网络了。

创建卷积神经网络训练 MNIST 数据集(手写数字图像集)。训练之后,可以获得~98.0%精确度,大概10K次迭代。

搭建环境

Anaconda

非Anaconda

$ pip install tensorflow

数据

这里写图片描述

需要创建3个分离的输入;训练集,验证集,测试集。
验证集提供了更多的数据来调参,可以更好地训练模型。

下载数据

数据可以用如下命令下载:

$ curl https://pjreddie.com/media/files/mnist_train.csv -o data/mnist_train.csv # 104 MB

$ curl https://pjreddie.com/media/files/mnist_test.csv -o data/mnist_test.csv # 17.4 MB

Python Code

import numpy as npIMAGE_SIZE = 28def load_train_data(data_path, validation_size=500):    """    Load mnist data. Each row in csv is formatted (label, input)    :return: 3D Tensor input of train and validation set with 2D Tensor of one hot encoded image labels    """    # Data format: 1 byte label, 28 * 28 input    train_data = np.genfromtxt(data_path, delimiter=',', dtype=np.float32)    x_train = train_data[:, 1:]    # Get label and one-hot encode    y_train = train_data[:, 0]    y_train = (np.arange(10) == y_train[:, None]).astype(np.float32)    # get a validation set and remove it from the train set    x_train, x_val, y_train, y_val = x_train[0:(len(x_train) - validation_size), :], x_train[(        len(x_train) - validation_size):len(x_train), :], \                                     y_train[0:(len(y_train) - validation_size), :], y_train[(        len(y_train) - validation_size):len(y_train), :]    # reformat the data so it's not flat    x_train = x_train.reshape(len(x_train), IMAGE_SIZE, IMAGE_SIZE, 1)    x_val = x_val.reshape(len(x_val), IMAGE_SIZE, IMAGE_SIZE, 1)    return x_train, x_val, y_train, y_valdef load_test_data(data_path):    """    Load mnist test data    :return: 3D Tensor input of train and validation set with 2D Tensor of one hot encoded image labels    """    test_data = np.genfromtxt(data_path, delimiter=',', dtype=np.float32)    x_test = test_data[:, 1:]    y_test = np.array(test_data[:, 0])    y_test = (np.arange(10) == y_test[:, None]).astype(np.float32)    x_test = x_test.reshape(len(x_test), IMAGE_SIZE, IMAGE_SIZE, 1)    return x_test, y_test

架构

可以用更有帮助的函数创建网络。这些函数用以创建之前讨论的单个组件。

模型定义:

import tensorflow as tfclass Model(object):    def __init__(self, batch_size=128, learning_rate=1e-4, num_labels=10):        self._batch_size = batch_size        self._learning_rate = learning_rate        self._num_labels = num_labels    def inference(self, images, keep_prob):        pass    def train(self, loss, global_step):        pass    def loss(self, logits, labels):        pass    def accuracy(self, logits, labels):        pass    def _create_conv2d(self, x, W):        return tf.nn.conv2d(input=x,                            filter=W,                            strides=[1, 1, 1, 1],                            padding='SAME')    def _create_max_pool_2x2(self, input):        return tf.nn.max_pool(value=input,                              ksize=[1, 2, 2, 1],                              strides=[1, 2, 2, 1],                              padding='SAME')    def _create_weights(self, shape):        return tf.Variable(tf.truncated_normal(shape=shape, stddev=0.1, dtype=tf.float32))    def _create_bias(self, shape):        return tf.Variable(tf.constant(1., shape=shape, dtype=tf.float32))    def _activation_summary(self, x):        tensor_name = x.op.name        tf.summary.histogram(tensor_name + '/activations', x)        tf.summary.scalar(tensor_name + '/sparsity', tf.nn.zero_fraction(x))

模型的TensorFlow 图 表示

这里写图片描述

下面是训练模型的代码。有3个主要的函数:

import tensorflow as tfclass Model(object):    def __init__(self, batch_size=128, learning_rate=1e-4, num_labels=10):        self._batch_size = batch_size        self._learning_rate = learning_rate        self._num_labels = num_labels    def inference(self, images, keep_prob):        with tf.variable_scope('conv1') as scope:            kernel = self._create_weights([5, 5, 1, 32])            conv = self._create_conv2d(images, kernel)            bias = self._create_bias([32])            preactivation = tf.nn.bias_add(conv, bias)            conv1 = tf.nn.relu(preactivation, name=scope.name)            self._activation_summary(conv1)        # pool 1        h_pool1 = self._create_max_pool_2x2(conv1)        with tf.variable_scope('conv2') as scope:            kernel = self._create_weights([5, 5, 32, 64])            conv = self._create_conv2d(h_pool1, kernel)            bias = self._create_bias([64])            preactivation = tf.nn.bias_add(conv, bias)            conv2 = tf.nn.relu(preactivation, name=scope.name)            self._activation_summary(conv2)        # pool 2        h_pool2 = self._create_max_pool_2x2(conv2)        with tf.variable_scope('local1') as scope:            reshape = tf.reshape(h_pool2, [-1, 7 * 7 * 64])            W_fc1 = self._create_weights([7 * 7 * 64, 1024])            b_fc1 = self._create_bias([1024])            local1 = tf.nn.relu(tf.matmul(reshape, W_fc1) + b_fc1, name=scope.name)            self._activation_summary(local1)        with tf.variable_scope('local2_linear') as scope:            W_fc2 = self._create_weights([1024, self._num_labels])            b_fc2 = self._create_bias([self._num_labels])            local1_drop = tf.nn.dropout(local1, keep_prob)            local2 = tf.nn.bias_add(tf.matmul(local1_drop, W_fc2), b_fc2, name=scope.name)            self._activation_summary(local2)        return local2    def train(self, loss, global_step):        tf.summary.scalar('learning_rate', self._learning_rate)        train_op = tf.train.AdamOptimizer(self._learning_rate).minimize(loss, global_step=global_step)        return train_op    def loss(self, logits, labels):        with tf.variable_scope('loss') as scope:            cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=labels)            cost = tf.reduce_mean(cross_entropy, name=scope.name)            tf.summary.scalar('cost', cost)        return cost    def accuracy(self, logits, labels):        with tf.variable_scope('accuracy') as scope:            accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(logits, 1), tf.argmax(labels, 1)),             dtype=tf.float32), name=scope.name)            tf.summary.scalar('accuracy', accuracy)        return accuracy    def _create_conv2d(self, x, W):        return tf.nn.conv2d(input=x,                            filter=W,                            strides=[1, 1, 1, 1],                            padding='SAME')    def _create_max_pool_2x2(self, input):        return tf.nn.max_pool(value=input,                              ksize=[1, 2, 2, 1],                              strides=[1, 2, 2, 1],                              padding='SAME')    def _create_weights(self, shape):        return tf.Variable(tf.truncated_normal(shape=shape, stddev=0.1, dtype=tf.float32))    def _create_bias(self, shape):        return tf.Variable(tf.constant(1., shape=shape, dtype=tf.float32))    def _activation_summary(self, x):        tensor_name = x.op.name        tf.summary.histogram(tensor_name + '/activations', x)        tf.summary.scalar(tensor_name + '/sparsity', tf.nn.zero_fraction(x))

代码在这里

Inference 这个函数创建对输入表示创建一个预测。它对每个输入返回一个 1×10的张量。张量中的值会传递给损失函数,计算这个预测与基准相差多少。

根据参数batch_size,每次需要处理128个图像。这个技术称为mini-batch。
在更小的数据集上batch上处理输入数据,而不是整个数据集,这样就可以有效使用内存。
因为是在每个小型数据集上更新权重,而不是处理所有样本,模型也能够更快收敛。

Loss 可以用softmax cross entropy 函数执行N路分类。Softmax可以归一化(将tensor加成1个数值)从inference函数产生的输入数据。

张量归一化后,Cross entropy 计算编码标注。cross entropy计算预测值与基准值之间的差异。每次迭代,优化器都最小化cross entropy的值。

Cross Entropy : ylogpred

Loss after Training

训练 和 评估

10k次迭代训练模型。
每1000次迭代,测试验证集上的模型,设置理想的精度。
最后,在测试集上评估训练好的模型,得到测量精度。
经过10k次迭代,精度大概在98.0%。

运行下面的命令,执行代码:

$ python3 mnist_conv2d_medium_tutorial/train.py

import tensorflow as tfimport mnist_conv2d_medium_tutorial.mnist as mnistfrom mnist_conv2d_medium_tutorial.model import ModelFLAGS = tf.app.flags.FLAGSNUM_LABELS = 10def train():    model = Model()    with tf.Graph().as_default():        images, val_images, labels, val_labels = mnist.load_train_data(FLAGS.train_data)        x = tf.placeholder(shape=[None, mnist.IMAGE_SIZE, mnist.IMAGE_SIZE, 1], dtype=tf.float32, name='x')        y = tf.placeholder(shape=[None, NUM_LABELS], dtype=tf.float32, name='y')        keep_prob = tf.placeholder(tf.float32, name='dropout_prob')        global_step = tf.contrib.framework.get_or_create_global_step()        logits = model.inference(x, keep_prob=keep_prob)        loss = model.loss(logits=logits, labels=y)        accuracy = model.accuracy(logits, y)        summary_op = tf.summary.merge_all()        train_op = model.train(loss, global_step=global_step)        init = tf.global_variables_initializer()        saver = tf.train.Saver()        with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess:            writer = tf.summary.FileWriter(FLAGS.summary_dir, sess.graph)            sess.run(init)            for i in range(FLAGS.num_iter):                offset = (i * FLAGS.batch_size) % (len(images) - FLAGS.batch_size)                batch_x, batch_y = images[offset:(offset + FLAGS.batch_size), :], labels[                                                                                  offset:(offset + FLAGS.batch_size), :]                _, cur_loss, summary = sess.run([train_op, loss, summary_op],                                                feed_dict={x: batch_x, y: batch_y, keep_prob: 0.5})                writer.add_summary(summary, i)                print(i, cur_loss)                if i % 1000 == 0:                    validation_accuracy = accuracy.eval(feed_dict={x: val_images, y: val_labels, keep_prob: 1.0})                    print('Iter {} Accuracy: {}'.format(i, validation_accuracy))                if i == FLAGS.num_iter - 1:                    saver.save(sess, FLAGS.checkpoint_file_path, global_step)def main(argv=None):    train()if __name__ == '__main__':    tf.app.flags.DEFINE_integer('batch_size', 128, 'size of training batches')    tf.app.flags.DEFINE_integer('num_iter', 10000, 'number of training iterations')    tf.app.flags.DEFINE_string('checkpoint_file_path', 'checkpoints/model.ckpt-10000', 'path to checkpoint file')    tf.app.flags.DEFINE_string('train_data', 'data/mnist_train.csv', 'path to train and test data')    tf.app.flags.DEFINE_string('summary_dir', 'graphs', 'path to directory for storing summaries')    tf.app.run()

模型训练好后,就可以在测试集上评估了。

import tensorflow as tffrom mnist_conv2d_medium_tutorial import mnistfrom mnist_conv2d_medium_tutorial.model import ModelFLAGS = tf.app.flags.FLAGSdef evaluate():    with tf.Graph().as_default():        images, labels = mnist.load_test_data(FLAGS.test_data)        model = Model()        logits = model.inference(images, keep_prob=1.0)        accuracy = model.accuracy(logits, labels)        saver = tf.train.Saver()        with tf.Session() as sess:            tf.global_variables_initializer().run()            saver.restore(sess, FLAGS.checkpoint_file_path)            total_accuracy = sess.run([accuracy])            print('Test accuracy: {}'.format(total_accuracy))def main(argv=None):    evaluate()if __name__ == '__main__':    tf.app.flags.DEFINE_string('checkpoint_file_path', 'checkpoints/model.ckpt-10000', 'path to checkpoint file')    tf.app.flags.DEFINE_string('test_data', 'data/mnist_test.csv', 'path to test data')    tf.app.run()

$ python3 mnist_conv2d_medium_tutorial/evaluate.py

运行以下命令,可视化结果:

$ tensorboard –logdir=graphs/ –port=6006 navigate in browser: localhost:6006

原创粉丝点击