9- 深度学习之神经网络核心原理与算法-全连接网络GPU实现

全连接网络GPU实现

  • 加入Dropout
  • 封装全连接层

之前我们的全连接网络只能运行在cpu上,我们改造为gpu实现。

封装全连接层到一个类里面。

因为我们要用到theano

WARNING (theano.configdefaults): g++ not available, if using conda: `conda install m2w64-toolchain`
D:\softEnvDown\Anaconda2\envs\py3\lib\site-packages\theano\configdefaults.py:560: UserWarning: DeprecationWarning: there is no c++ compiler.This is deprecated and with Theano 0.11 a c++ compiler will be mandatory
  warnings.warn("DeprecationWarning: there is no c++ compiler."
WARNING (theano.configdefaults): g++ not detected ! Theano will be unable to execute optimized C-implementations (for both CPU and GPU) and will default to Python implementations. Performance will be severely degraded. To remove this warning, set Theano flags cxx to an empty string.
WARNING (theano.tensor.blas): Using NumPy C-API based implementation for BLAS functions.

根据报错,我们安装conda install -c msys2 m2w64-toolchain

因为我们要把我们的代码放在gpu上进行计算,所以我们引入theano

import theano.tensor as T
from theano.tensor import shared_randomstreams
from theano.tensor.nnet import sigmoid

引入theano里面的tensor提供了许多数学相关的函数。shared_randomstreams帮我们取随机值。使用提供的sigmoid激励函数。

# 是否使用GPU
GPU = True
if GPU:
    print("Trying to run under a GPU.  If this is not desired, then modify " + \
          "network3.py\nto set the GPU flag to False.")
    try:
        theano.config.device = 'gpu'
    except:
        pass  # it's already set
    theano.config.floatX = 'float32'
else:
    print("Running with a CPU.  If this is not desired, then the modify " + \
          "network3.py to set\nthe GPU flag to True.")

如果使用gpu的话,定义两个theano的变量theano.config.devicetheano.config.floatX = 'float32'

报错:

You can find the C code in this temporary file: C:\Users\mtian\AppData\Local\Temp\theano_compilation_error__dohjzex
Traceback (most recent call last):
  File "D:\softEnvDown\Anaconda2\envs\py3\lib\site-packages\theano\gof\lazylinker_c.py", line 75, in <module>
    raise ImportError()
ImportError

解决方案;

conda install mingw libpython

全连接的实现被我们封装进了一个类里面:

class FullyConnectedLayer(object):
    def __init__(self, n_in, n_out, activation_fn=sigmoid, p_dropout=0.0):
        # 前一层神经元个数
        self.n_in = n_in
        # 后一层神经元个数
        self.n_out = n_out
        # 激励函数
        self.activation_fn = activation_fn
        # dropout
        self.p_dropout = p_dropout
        # 初始化权重
        self.w = theano.shared(
            np.asarray(
                np.random.normal(
                    loc=0.0, scale=np.sqrt(1.0 / n_out), size=(n_in, n_out)),
                dtype=theano.config.floatX),
            name='w', borrow=True)
        # 初始化偏置
        self.b = theano.shared(
            np.asarray(np.random.normal(loc=0.0, scale=1.0, size=(n_out,)),
                       dtype=theano.config.floatX),
            name='b', borrow=True)
        self.params = [self.w, self.b]

    def set_inpt(self, inpt, inpt_dropout, mini_batch_size):
        # reshape输入
        self.inpt = inpt.reshape((mini_batch_size, self.n_in))
        # 输出
        self.output = self.activation_fn(
            (1 - self.p_dropout) * T.dot(self.inpt, self.w) + self.b)
        # 取最大值
        self.y_out = T.argmax(self.output, axis=1)
        # dropout输入dropout
        self.inpt_dropout = dropout_layer(
            inpt_dropout.reshape((mini_batch_size, self.n_in)), self.p_dropout)
        # dropout输出
        self.output_dropout = self.activation_fn(
            T.dot(self.inpt_dropout, self.w) + self.b)

    def accuracy(self, y):
        return T.mean(T.eq(y, self.y_out))

n_in表示前一层网络有多少神经元, n_out表示后一层一共有多少神经元, 激励函数(默认使用sigmoid函数) p_Dropout 抛弃多少神经元(百分比)

保存传入的参数到类的私有变量。

初始化权重self.w

使用theano.shared方法可以把我们的权重值放在gpu上运算。这里我们使用正态分布,均值为0,方差为(1/后一层神经元个数)开根号。总共有多少个权重 (n_in, n_out)前一层乘以后一层。数组的数据类型可以用theano里面的floatx来表示(方便放在gpu上运行)。设置一个名字name w。borrow设置为true表示共享变量。

https://groups.google.com/forum/#!topic/theano-users/XWDOoKdpn5I

初始化偏置self.b

使用均值为0,方差为1的正态分布初始化数组,数组的size是n_out.偏置等于下一层神经元的个数。数组的数据类型可以用theano里面的floatx来表示(方便放在gpu上运行)。

self.params 将刚才初始化的w和b放在一个列表里面。

set_input函数

通过这个方法设置我们需要的值。

参数: 前一层的输出,和前一层经过Dropout之后的输出当做本层的输入,mini_batch的大小。

reshape一下inpt。总共是有mini_batch条数据,每条数据有n_in这么多列。

本层全连接层的输出,线性部分wx+b经过激励函数。

引入了dropout。也就是输出的时候要保留多少个神经元的结果。

取一下输出的最大值。如果仍做手写数字的识别,输出一共有10种0-9。取最大值也就是它最大的可能性。

对于全连接层输入的时候我们要做一下Dropout reshape。

drop_layer函数在下面实现:

def dropout_layer(layer, p_dropout):
    srng = shared_randomstreams.RandomStreams(
        np.random.RandomState(0).randint(999999))
    mask = srng.binomial(n=1, p=1 - p_dropout, size=layer.shape)
    return layer * T.cast(mask, theano.config.floatX)

就是要保留多少数据。

输出的时候也要做一下Dropout

直接和输入时的Dropout和w做内积再加上偏置。

计算一下本层的输出和做完Dropout之后的输出。

定义一个计算准确率的函数

    def accuracy(self, y):
        return T.mean(T.eq(y, self.y_out))

传入网络的真实值与预测值进行比较。取平均值,得到准确率。

我们Network类的修改;

class Network(object):
    def __init__(self, layers, mini_batch_size):
        self.layers = layers
        self.mini_batch_size = mini_batch_size
        # 把每一层的参数放到一个list里
        self.params = [param for layer in self.layers for param in layer.params]
        # 初始化x, y
        self.x = T.matrix("x")
        self.y = T.ivector("y")
        # 初始化第一层
        init_layer = self.layers[0]
        init_layer.set_inpt(self.x, self.x, self.mini_batch_size)
        # 初始化后面每层
        for j in range(1, len(self.layers)):
            prev_layer, layer = self.layers[j - 1], self.layers[j]
            layer.set_inpt(
                prev_layer.output, prev_layer.output_dropout, self.mini_batch_size)
        # 最后一层的输出
        self.output = self.layers[-1].output
        self.output_dropout = self.layers[-1].output_dropout

构造函数,总共传入多少层。将每一层的参数放入一个list中。

首先遍历每一层,然后在每一层里面取每一层的参数。

初始化一下训练数据和它对应的标签。标签是一个0-9向量 x是一个28,28的矩阵。

设置一下网络第一次的输入,经过Dropout之后的输入。因为这里是第一层,此时原始的图片中第一个参数和第二个参数是一样的。

初始化后面的每一层网络。从第二层开始一直到最后一层。

取一下本层的网络的前一层和当前层。为当前层的网络设置参数: 前一层的输出,前一层的Dropout输出。

我们保留一下最后一层的output。最后一层Dropout之后的输出。-1是取最后一层。

梯度下降函数

    def SGD(self, training_data, epochs, mini_batch_size, eta,
            validation_data, test_data, lmbda=0.0):
        training_x, training_y = training_data
        validation_x, validation_y = validation_data
        test_x, test_y = test_data

        num_training_batches = size(training_data) / mini_batch_size
        num_validation_batches = size(validation_data) / mini_batch_size
        num_test_batches = size(test_data) / mini_batch_size

eta学习率 验证数据集是帮助我们网络在训练的时候调整参数的,让你发现哪些超参数有问题。

测试数据集是帮我们验证我们最后训练出来的模型的好坏的。lmbda是做正则化用的参数

保存一下训练数据集和验证数据集分别对应的x和y。

我们计算一下验证,测试,训练总共要分成多少个batches

L2正则化

mark

mark

原始的损失函数+加号后面这一项: L2正则项

w的平方累加和,

mark

原始的C0 和 我们的L2正则化项。

计算偏导。

原来我们是手工实现的,直接调用theano里面提供的方法grad计算梯度

参数: 损失,每层神经元的参数w和b

更新每一层的参数:

mark

w-学习率* 偏导。

设置更新方程

index 就是一个标量i

第一个参数是i,第二层个参数是cost,第三个参数是上面的更新参数

输入时训练数据集的x, 0-60 60-120

验证数据集上的准确率。调用最后一层。如果最后一层是全连接层的话,调用 全连接层我们刚实现的计算准确率的函数。把x对应的实际标签y丢进去。

组织一下batches

开始训练

 # 开始训练
        best_validation_accuracy = 0.0
        for epoch in range(epochs):
            for minibatch_index in range(num_training_batches):
                iteration = num_training_batches * epoch + minibatch_index
                if iteration % 1000 == 0:
                    print("Training mini-batch number {0}".format(iteration))
                cost_ij = train_mb(minibatch_index)
                if (iteration + 1) % num_training_batches == 0:
                    validation_accuracy = np.mean(
                        [validate_mb_accuracy(j) for j in range(num_validation_batches)])
                    print("Epoch {0}: validation accuracy {1:.2%}".format(
                        epoch, validation_accuracy))
                    if validation_accuracy >= best_validation_accuracy:
                        print("This is the best validation accuracy to date.")
                        best_validation_accuracy = validation_accuracy
                        best_iteration = iteration
                        if test_data:
                            test_accuracy = np.mean(
                                [test_mb_accuracy(j) for j in range(num_test_batches)])
                            print('The corresponding test accuracy is {0:.2%}'.format(
                                test_accuracy))
        print("Finished training network.")
        print("Best validation accuracy of {0:.2%} obtained at iteration {1}".format(
            best_validation_accuracy, best_iteration))
        print("Corresponding test accuracy of {0:.2%}".format(test_accuracy))

总共训练多少轮,每轮里面训练多少个把batch 每次取一个batch进行训练。

每隔多少步打印一下。当前训练到了多少个minibatch。调用我们的train_mb函数进行训练。

每训练完一轮,就使用我们的验证数据集进行验证。之前这一轮在验证数据集上的准确率。

如果验证数据集上的准确率大于以往的最佳验证数据集准确率。表示更新了。

并且保存它训练的步数。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏量化投资与机器学习

机器学习模型的变量评估和选择基于技术指标『深度解析』

简介 本文重点介绍机器学习模型中输入变量(预测因子)的选择,预处理以及评估的相关细节。所有的计算和实验将用R语言来实现。 输入数据 我们将采用11个指标(振荡器...

3295
来自专栏LhWorld哥陪你聊算法

【Keras篇】---Keras初始,两种模型构造方法,利用keras实现手写数字体识别

Keras 适合快速体验 ,keras的设计是把大量内部运算都隐藏了,用户始终可以用theano或tensorflow的语句来写扩展功能并和keras结合使用。

1022
来自专栏ACM算法日常

leetcode题解 | 48. 旋转图像

你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。

871
来自专栏数值分析与有限元编程

用面积坐标推导六节点三角形单元刚度矩阵

建立高阶单元时,利用面积坐标可以简化计算,特别是利用面积坐标的积分公式计算等效节点力。 (一)节点形函数 ? (二)单元位移场及应变场 ? ? ? (三)单元刚...

4237
来自专栏marsggbo

【TensorFlow】tf.nn.softmax_cross_entropy_with_logits的用法

在计算loss的时候,最常见的一句话就是 tf.nn.softmax_cross_entropy_with_logits ,那么它到底是怎么做的呢?

601
来自专栏华章科技

三天速成!香港科技大学TensorFlow课件分享

该教程第一天先介绍了深度学习和机器学习的潜力与基本概念,而后便开始探讨深度学习框架 TensorFlow。首先我们将学到如何安装 TensorFlow,其实我们...

1042
来自专栏编程

图像处理基础

作者简介 本文来自鲍骞月的投稿,主要讲解图像处理基础,欢迎大家积极留言,提出你的疑问或者建议,与投稿小伙伴交流。 GitHub地址:https://github...

2076
来自专栏木子昭的博客

万能的0和1 之 字典特征抽取

机器是无法识别自然语言的,机器只能识别0和1,经典的案例就是字典特征抽取 0表示不存在 1表示存在 以国漫人物信息,做示例 原始数据 ? ...

2898
来自专栏机器之心

三天速成!香港科技大学TensorFlow课件分享

机器之心整理 参与:蒋思源 这是一套香港科技大学发布的极简 TensorFlow 入门教程,三天全套幻灯片教程已被分享到 Google Drive。机器之心将简...

53512
来自专栏程序生活

斯坦福tensorflow教程-tensorflow 实现逻辑回归03_logreg_placeholder.py实验结果utils.py

2663

扫码关注云+社区