<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>人工智能 &#187; 深度学习</title>
	<atom:link href="http://www.newlifeclan.com/ai/archives/category/deep-learning/feed" rel="self" type="application/rss+xml" />
	<link>http://www.newlifeclan.com/ai</link>
	<description>深入学习</description>
	<lastBuildDate>Tue, 16 Aug 2022 08:59:48 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.0.38</generator>
	<item>
		<title>DQN 改进</title>
		<link>http://www.newlifeclan.com/ai/archives/305</link>
		<comments>http://www.newlifeclan.com/ai/archives/305#comments</comments>
		<pubDate>Wed, 04 Jul 2018 07:14:40 +0000</pubDate>
		<dc:creator><![CDATA[napoleon]]></dc:creator>
				<category><![CDATA[深度学习]]></category>

		<guid isPermaLink="false">http://www.newlifeclan.com/ai/?p=305</guid>
		<description><![CDATA[我们来看三个重要的改进： &#8211;  双DQN &#8211;  优先回放 &#8211;  对抗网络  [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>我们来看三个重要的改进：</p>
<p>&#8211;  双DQN</p>
<p>&#8211;  优先回放</p>
<p>&#8211;  对抗网络</p>
<p><span id="more-305"></span></p>
<h2>双DQN</h2>
<p>我们解决的第一个问题是：Q学习容易出现过高估计动作值问题。</p>
<p>我们来回顾一下具有函数逼近的Q学习更新规则，并重点看看TD目标</p>
<p><img class="alignnone size-full wp-image-309" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/07/20180704153656.jpg" alt="20180704153656" width="590" height="141" /></p>
<p>这里的max运算有必要用到，以便计算可以从下个状态获得最佳潜在值，为了更好的理解这一点，我们重写目标并展开max运算。可以更有效的理解为，我们想要获得状态S’的Q值，以及从该状态的所有潜在动作中实现最大Q值的动作</p>
<p><img class="alignnone size-full wp-image-310" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/07/20180704154040.jpg" alt="20180704154040" width="616" height="315" /></p>
<p>可以看出arg max运算有可能会出错，尤其是在早期阶段。为何？因为Q值依然在变化，我们可能没有收集足够的信息来判断最佳动作是什么，Q值的准确性在很大程度上取决于：尝试了哪些动作以及探索了哪些周围的状态。实际上，事实证明这一部分会导致过高估计Q值，因为我们始终在一组杂乱数字中选择最大值，或许我们不应该盲目的信任这些值。</p>
<p>那么如何才能使我们的估值更加可靠呢？有一个经实践证明效果很好的方法就是双Q学习，我们使用一组参数w，选择最佳动作，但是使用另一组参数w‘，评估动作。相当于有两个单独的函数逼近器，我们必须在最佳动作上达成一致，如果根据W‘  和W 选择的动作并不是最佳动作，那么返回的Q值不会这么高，长期下来，就可以避免该算法传播偶尔获得的更高奖励，这些奖励并不能反映长期回报。</p>
<p><img class="alignnone size-full wp-image-311" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/07/20180704161947.jpg" alt="20180704161947" width="572" height="204" /></p>
<p>你可能会问，我们从哪获取第二参数呢？从原始的双Q学习公式中，你会保留两个值函数，在每一步随机选择一个函数进行更新，并仅使用另一个评估动作。但是将DQN与固定Q目标结合使用时，我们已经有一组替代的参数。</p>
<p><img class="alignnone size-full wp-image-312" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/07/20180704162358.jpg" alt="20180704162358" width="417" height="208" /></p>
<p>还记得W-吗？实际上，W- 已经保留不用有一段时间了。它与W之间的区别已经足够大，可以重新用于该目的，原理就是这样。这个简单的修改就可以使Q值变起来可靠。防止他们在学习的早期阶段爆发或在后期阶段出现波动。经过证明，形成的策略效果比Vanilla DQN强很多。</p>
<p>&nbsp;</p>
<h2>优先回放</h2>
<p><a href="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/07/20180704163049.jpg"><img class="alignnone wp-image-314 size-full" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/07/20180704163049.jpg" alt="20180704163049" width="807" height="340" /></a></p>
<p>回忆一下经验回放的基本原理，我们与环境互动以便收集经验元祖，将元祖保存在缓冲区，然后随机抽取一个批次从中学习规律。这样有助于打破连续经验之间的关系。并使学习算法稳定下来，到目前为止没有发现什么问题。但是某些经验可能比其他经验更重要，更需要学习。此外，这些重要的经验可能很少发生，如果我们均匀地按照批次抽样，那么这些经验被选中的概率很小，因为缓冲区实际上容量有限。因此更早的重要经验可能会丢失，这时候就要用到优先经验回放了。</p>
<p>但是我们根据什么条件来为每个元祖分配优先级呢？一种方法是使用TD误差增量，误差越大，我们该元祖中预计学到的规律就越多。我们将此误差的大小作为衡量优先级的条件，并将其与每一个相应的元祖一起存储在回放缓冲区。在创建批次时，我们可以使用该值计算抽样概率。选择任何元祖i的概率等于其优先级值pi，并用回放缓冲区中的所有优先级值之和标准化。选择某个元祖后，我们可以使用最新的Q值，将其优先级更新为新计算的TD误差。似乎效果不错，经过证明，可以减少学习值函数所需的批次更新数量。</p>
<p><img class="alignnone size-full wp-image-315" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/07/20180704183850.jpg" alt="20180704183850" width="701" height="416" /></p>
<p>有几个方面可以加以改进。首先，如果TD误差为0，那么该元祖的优先级值及其被选中的概率也为0。</p>
<p>0或者非常低的TD误差，并不一定就表明我们从此类元祖中学不到任何规律，可能是因为到该时间点为止，经历的样本有限。估值很接近真实的值。为了防止此类元祖不被选中，我们可以在每个<strong>平衡值</strong>后面加上一个很小的常量e</p>
<p><img class="alignnone size-full wp-image-316" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/07/20180704185347.jpg" alt="20180704185347" width="662" height="337" /></p>
<p>另一个类似的问题是贪婪地使用这些优先级值，可能会导致一小部分经验子集不断被回放，导致对该子集的过拟合。为了避免该问题，我们重新引入一些均匀随机抽样元素，这样会添加另一个超参数a，我们用它将抽样概率重新定义为，优先级pi的a次幂除以所有优先级之和pk，每个都是a次幂，我们可以通过调整该参数，控制采用优先级的随机性的幅度。</p>
<p><img class="alignnone size-full wp-image-317" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/07/20180704205909.jpg" alt="20180704205909" width="644" height="314" /></p>
<p>a等于0，表示采用完全均匀随机性方法，a等于1，表示仅采用优先级值。当我们使用优先经验回放时，我们需要对更新规则进行一项调整</p>
<p><img class="alignnone size-full wp-image-318" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/07/20180704211501.jpg" alt="20180704211501" width="823" height="376" /></p>
<p>我们的原始Q学习更新，来自于对所有经验的预期结果，在使用随机性更新规则时，我们对这些经验抽样的方式，必须与来源底层分布匹配。</p>
<p>当我们从回放缓冲区均匀地抽样经验元祖时，能够满足这一前提条件。</p>
<p>但当我们采用非均匀抽样时（例如，使用优先级）时，则不满足该前提条件。我们学习的Q值将因为这些优先级值出现偏差。我们只希望使用这些值进行抽样，为了更正这一偏差，我们需要引入一个重要的抽样权重等于 1/N，N是该回放缓冲区的大小，乘以1/p(i) ，p(i)是抽样概率，我们可以添加另一个超参数b，并将每个重要抽样权重提升为b，控制这些权重对学习的影响程度比这些权重在学习结束是更加重要。这时候Q值开始收敛，因此你可以逐渐将b从很低的值增加到1，这些细节部分可能一开始很难明白，但是每个小小的改进，都可以有效地达到更加稳定高效的学习算法，因此确保仔细阅读优先经验回放论文。</p>
<p>&nbsp;</p>
<h2>对抗网络</h2>
<p>我们将简单介绍最后一个DQN增强技巧，对抗网络。</p>
<p><img class="alignnone size-full wp-image-319" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/07/20180704213642.jpg" alt="20180704213642" width="790" height="330" /></p>
<p>这是一个典型DQN架构，有一系列卷积层，然后是几个完全连接层，生成了Q值，对抗网络的核心概念是使用两个信息流，一个估算状态值函数，一个估值每个动作的优势，两个信息流，可能在一开始具有一些共同的层级。例如，卷积层，然后分支为各自的完全连接层，最后通过<strong>结合状态和优势值</strong>，获得期望的Q值，这么做的原因是，大部分状态在动作之间变化不大，因此可以尝试直接估算它们，但是我们依然需要捕获动作在每个状态中产生的区别，这时候我们就要用到<strong>优势函数，</strong>需要进行一些调整，以便将Q学习应用与该框架，你可以在对抗网络论文中找到该调整的方法。和双DQN以及经验回放一样，该技巧显著改善了vanilla DQN。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.newlifeclan.com/ai/archives/305/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>深度Q学习算法</title>
		<link>http://www.newlifeclan.com/ai/archives/300</link>
		<comments>http://www.newlifeclan.com/ai/archives/300#comments</comments>
		<pubDate>Wed, 04 Jul 2018 07:13:36 +0000</pubDate>
		<dc:creator><![CDATA[napoleon]]></dc:creator>
				<category><![CDATA[深度学习]]></category>

		<guid isPermaLink="false">http://www.newlifeclan.com/ai/?p=300</guid>
		<description><![CDATA[该算法中有两个交错的主要流程。 第一个流程是对环境取样，方法是执行动作，并以回放存储器的形式，存储观察的经验元 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>该算法中有两个交错的主要流程。</p>
<p>第一个流程是对环境取样，方法是执行动作，并以回放存储器的形式，存储观察的经验元祖。<span id="more-300"></span></p>
<p><strong>环境取样</strong></p>
<p>使用策略从状态S中选择动作A</p>
<p>执行行动A，观察奖励R和下一个输入Xt+1.</p>
<p>准备下一个状态</p>
<p>在回放存储器D中存储经验元祖（S，A，R，S‘）</p>
<p>S &lt;&#8211; S&#8221;</p>
<p><img class="alignnone size-full wp-image-301" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/07/20180704140732.jpg" alt="20180704140732" width="675" height="185" /></p>
<p>&nbsp;</p>
<p><strong>学习</strong></p>
<p>另一个流程是随机地从该存储器中选择一小批元祖，并使用梯度下降更新步骤从该批次中学习规律。</p>
<p>从D中的元祖（sj,aj,rj,sj+1）获取随机的小批次</p>
<p>设置目标</p>
<p>更新</p>
<p>每一个C步骤，重置 W- &lt;&#8212;W</p>
<p><img class="alignnone size-full wp-image-302" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/07/20180704141016.jpg" alt="20180704141016" width="604" height="112" /></p>
<p>&nbsp;</p>
<p>两个流程并非直接相互依赖。因此，你可以完成多个取样步骤，然后完成一个学习步骤。或者具有不同随机批次的多个学习步骤。</p>
<p>该算法的还有剩余步骤，旨在支持这些步骤：</p>
<p>1. 一开始你需要初始化空的回放存储器；注意存储器是有限的，因此你可能需要使用循环Q，保存最近的n个经验元祖。</p>
<p>2. 然后，你还需要初始化神经网络的参数^q或权重w;你可以采取一些不错的做法，例如，从正态分布中随机抽取一些权重方差等于每个神经元输入数量的两倍。Keras和Tensorflow等通常都包含这些初始化方法，因此不需要自己去实现这些方法。</p>
<p>3. 采用固定Q目标方法，你需要第二组参数 w-，它可以初始化为w。</p>
<p>4. （注意，这一特定算法专门用于视频游戏。）对于每个阶段和该阶段中的每个时间步t，你会观察原始屏幕图像或者输入帧Xt，并需要将其转换为灰阶形式，剪切为正方形等等。此外，为了捕获时间关系，你可以堆叠一些输入帧以构建每个状态向量，我们用函数phi表示这个预处理和堆叠操作，该函数会接收一系列的帧并形成组合表示法。注意，如果我们要堆叠帧。例如四个帧则需要对前三个时间步进行特殊处理。比如，我们可以将这些丢失的帧，当作空帧，使用第一帧的副本或跳过存储经验帧这一步，直到获得完整的序列。在现实中，你无法立即运行学习步骤，需要等待，直到存储器中有足够数量的元祖。</p>
<p>注意每个阶段之后，我们不清空存储器，这样可以跨阶段地回忆和形成批量经验，DQN论文中用到了很多其他技巧和优化方式，</p>
<p>例如奖励裁剪，误差裁剪，将过去的动作存储为状态向量的一部分，处理终止状态，挖掘一段时间内的 ∈等<img class="alignnone size-full wp-image-303" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/07/20180704151308.jpg" alt="20180704151308" width="648" height="462" /></p>
<p>&nbsp;</p>
<p>延伸阅读：</p>
<ul>
<li>Mnih et al.，2015 年，<a href="https://storage.googleapis.com/deepmind-media/dqn/DQNNaturePaper.pdf" target="_blank">《通过深度强化学习实现人类级别的控制》</a>（DQN 论文）</li>
<li>He et al. ，2015 年，<a href="https://arxiv.org/abs/1502.01852" target="_blank">《深入研究纠正器：在 ImageNet 分类方面超过人类水平》</a>（权重初始化）</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.newlifeclan.com/ai/archives/300/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>深度卷积对抗网络</title>
		<link>http://www.newlifeclan.com/ai/archives/256</link>
		<comments>http://www.newlifeclan.com/ai/archives/256#comments</comments>
		<pubDate>Wed, 27 Jun 2018 12:42:20 +0000</pubDate>
		<dc:creator><![CDATA[napoleon]]></dc:creator>
				<category><![CDATA[深度学习]]></category>

		<guid isPermaLink="false">http://www.newlifeclan.com/ai/?p=256</guid>
		<description><![CDATA[深度卷积对抗网络简称DCGAN，这些GAN给你之前使用MNIST数据库构建差不多，但是这次的生成器和辨别器用神 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>深度卷积对抗网络简称DCGAN，这些GAN给你之前使用MNIST数据库构建差不多，但是这次的生成器和辨别器用神经网络构建，有关于DCGAN原始论文请看：https://arxiv.org/pdf/1511.06434.pdf。他的技术性不是特别强，并提供了关于这些东西训练的一些好建议。确保你在构建过程中，阅读它。<span id="more-256"></span></p>
<p>我们使用的是“<a href="http://ufldl.stanford.edu/housenumbers/">街景门牌号</a>”数据集，下图是一堆的地址图像，收集来自Google街景，他们比MNIST数据集中的图像要复杂，我们有三个颜色通道，红、绿、蓝，而且他们更大，并且图像有更多的细节。其中一些包含多个数字，那么由于这些图像比我们之前使用的，更复杂，我们需要用卷积网络来使生成器和辨别器很好的发挥作用。充分展示深度学习的神奇力量，产生一些非常酷的图像，所以基本来说，你在这里所做的和你之前在其他GAN课程中，所执行操作的唯一区别是更改生成器和辨别器。但是，训练的其余部分，像损失、优化器和输入他们基本上都一样。现在唯一的区别就在于，我们的生成器是一个卷积网络，辨别器也是一个卷积网络</p>
<p>&nbsp;</p>
<p><img class="alignnone size-full wp-image-257" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/SVHN_examples.png" alt="SVHN_examples" width="340" height="340" /></p>
<p>那么一开始，我们和往常一样导入数据，导入模块</p><pre class="crayon-plain-tag">%matplotlib inline

import pickle as pkl

import matplotlib.pyplot as plt
import numpy as np
from scipy.io import loadmat
import tensorflow as tf</pre><p>&nbsp;</p><pre class="crayon-plain-tag">!mkdir data</pre><p></p>
<h2> 导入数据：</h2>
<p>这部分我们加载并提取SVHN数据集。</p><pre class="crayon-plain-tag">from urllib.request import urlretrieve
from os.path import isfile, isdir
from tqdm import tqdm

data_dir = 'data/'

if not isdir(data_dir):
    raise Exception("Data directory doesn't exist!")

class DLProgress(tqdm):
    last_block = 0

    def hook(self, block_num=1, block_size=1, total_size=None):
        self.total = total_size
        self.update((block_num - self.last_block) * block_size)
        self.last_block = block_num

if not isfile(data_dir + "train_32x32.mat"):
    with DLProgress(unit='B', unit_scale=True, miniters=1, desc='SVHN Training Set') as pbar:
        urlretrieve(
            'http://ufldl.stanford.edu/housenumbers/train_32x32.mat',
            data_dir + 'train_32x32.mat',
            pbar.hook)

if not isfile(data_dir + "test_32x32.mat"):
    with DLProgress(unit='B', unit_scale=True, miniters=1, desc='SVHN Training Set') as pbar:
        urlretrieve(
            'http://ufldl.stanford.edu/housenumbers/test_32x32.mat',
            data_dir + 'test_32x32.mat',
            pbar.hook)</pre><p>这个数据集实际上是一个.mat文件，他们通常和Matlab一起使用，但Scipy实际上有一个函数，可以将这些.mat文件，作为Numpy数组导入。那么我么们可以提取这些数组，像平常一样使用他们</p><pre class="crayon-plain-tag">trainset = loadmat(data_dir + 'train_32x32.mat')
testset = loadmat(data_dir + 'test_32x32.mat')</pre><p>这里我们可以看到数据集中的一个小的图像样本</p><pre class="crayon-plain-tag">idx = np.random.randint(0, trainset['X'].shape[3], size=36)
fig, axes = plt.subplots(6, 6, sharex=True, sharey=True, figsize=(5,5),)
for ii, ax in zip(idx, axes.flatten()):
    ax.imshow(trainset['X'][:,:,:,ii], aspect='equal')
    ax.xaxis.set_visible(False)
    ax.yaxis.set_visible(False)
plt.subplots_adjust(wspace=0, hspace=0)</pre><p><img class="alignnone size-full wp-image-258" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/201805271856.png" alt="201805271856" width="299" height="293" /></p>
<p>上面的图像样本，是我们即将传入辨别器的真实图像，也是生成器要学习重现的东西</p><pre class="crayon-plain-tag">def scale(x, feature_range=(-1, 1)):
    # scale to (0, 1)
    x = ((x - x.min())/(255 - x.min()))
    
    # scale to feature_range
    min, max = feature_range
    x = x * (max - min) + min
    return x</pre><p>&nbsp;</p><pre class="crayon-plain-tag">class Dataset:
    def __init__(self, train, test, val_frac=0.5, shuffle=False, scale_func=None):
        split_idx = int(len(test['y'])*(1 - val_frac))
        # 构建测试集和验证集
        self.test_x, self.valid_x = test['X'][:,:,:,:split_idx], test['X'][:,:,:,split_idx:]
        self.test_y, self.valid_y = test['y'][:split_idx], test['y'][split_idx:]
        self.train_x, self.train_y = train['X'], train['y']
        
        self.train_x = np.rollaxis(self.train_x, 3)
        self.valid_x = np.rollaxis(self.valid_x, 3)
        self.test_x = np.rollaxis(self.test_x, 3)
        
        if scale_func is None:
            self.scaler = scale
        else:
            self.scaler = scale_func
        self.shuffle = shuffle
        
    def batches(self, batch_size):
        if self.shuffle:
            idx = np.arange(len(dataset.train_x))
            np.random.shuffle(idx)
            self.train_x = self.train_x[idx]
            self.train_y = self.train_y[idx]
        
        n_batches = len(self.train_y)//batch_size
        for ii in range(0, len(self.train_y), batch_size):
            x = self.train_x[ii:ii+batch_size]
            y = self.train_y[ii:ii+batch_size]
            
            yield self.scaler(x), y</pre><p>你应该记得之前，我们的生成器使用一个tanh输入，来创建这些新的图像，以使输出的范围在-1到1之间。因此我们需要重新缩放所有真实图像，是他们在-1到1之间，以便在进入辨别器时匹配。上面就是缩放的代码，包含数据集的一个类，我们可以从batches这里获得取批。我们并不对这个网络进行分类，所以我们实际上不需要使用验证集，这只是你可以用于SVHN数据集的常规数据集的类。</p>
<p>&nbsp;</p>
<h2>网络输入</h2>
<p>这是必不可少的。</p><pre class="crayon-plain-tag">def model_inputs(real_dim, z_dim):
    inputs_real = tf.placeholder(tf.float32, (None, *real_dim), name='input_real')
    inputs_z = tf.placeholder(tf.float32, (None, z_dim), name='input_z')
    
    return inputs_real, inputs_z</pre><p>我们有真实图像的输入，我们直接使用真图的尺寸，32*32*3（本例子的数据，你可以使用任意图像大小）。我只是将它留作一个占位符。</p>
<p>进入生成器本征向量input_z,他和我们之前在MNIST GAN中看到的一样。</p>
<p>&nbsp;</p>
<h2>生成器</h2>
<p>这里是不同的地方，我们将在这里实现生成器和生成器的输入噪声向量z，输出也同样是一个tanh层。基本上SVHN图像输出需要匹配的大小，即32*32，但是tanh输出范围在-1到1之间。而且我们还需要匹配这些图像的深度？</p>
<p>我们的SVHN图像有三个颜色通道，那么他们的深度为3，即大小为32*32*3，这意味着我们具有tanh激活的输出层，也必须接受是32*32*3。这里你可以看到DCGAN论文中，使用的生成器示意图。那么（从左到右）我们取z向量，将他投射到一个全链接层，然后重塑这个全链接层，使他的大小为4*4*1024个过滤器（或者说深度），然后使用转置卷积，来减小深度并增加宽度和高度，然后在使用tanh激活。</p>
<p>同样在转置卷积中，使用步幅2，你会注意到这里并没有最大池化层或者类似的东西，没有全链接层。</p>
<p>虽然第一个使用全链接层，但是后面便全部都是卷积层，我们在转置卷积中，使用步幅2，进行所有上采样，需要注意一件事：这里最后一层在DCGAN论文中，它的大小为64*64*3，但我们的图像是32*32*3，所以他跟你应该用的架构不完全相同。但是他大致向你，展示了你应该为生成器构建的架构是什么样的。</p>
<p><img class="alignnone wp-image-259 size-large" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/dcgan-1024x433.png" alt="dcgan" width="780" height="329" /></p>
<p>output是输出的深度，我们使用variable_scope进行重用，你也必须对上面的所有层进行批量归一化，除了最后一层，如果不使用批量归一化层，这个网络就无法发挥作用。典型的处理方式是，先使用转置卷积，然后是批量归一化，最后激活。</p><pre class="crayon-plain-tag">def generator(z, output_dim, reuse=False, alpha=0.2, training=True):
    with tf.variable_scope('generator', reuse=reuse):
        # First fully connected layer 
        # 首先传入张量z，这是用于生成图像噪声的向量，将他链接到一个全连接层，
        # 给他一个大小 4*4*512，上图前两个部分
        x1 = tf.layers.dense(z, 4*4*512)
        # Reshape it to start the convolutional stack
        # 并添加批量归一化和leaky ReLU
        x1 = tf.reshape(x1, (-1, 4, 4, 512))
        x1 = tf.layers.batch_normalization(x1, training=training)
        x1 = tf.maximum(alpha * x1, x1)
        # 4x4x512 now  上面，现在的层数为4*4*512
        
        # 将上面的4*4*512 发到下面的转置卷积层
        # 含有256个过滤器，并将步幅设为2，卷积核大小为5*5
        x2 = tf.layers.conv2d_transpose(x1, 256, 5, strides=2, padding='same')
        # 并添加批量归一化和leaky ReLU
        x2 = tf.layers.batch_normalization(x2, training=training)
        x2 = tf.maximum(alpha * x2, x2)
        # 8x8x256 now
        
        x3 = tf.layers.conv2d_transpose(x2, 128, 5, strides=2, padding='same')
        x3 = tf.layers.batch_normalization(x3, training=training)
        x3 = tf.maximum(alpha * x3, x3)
        # 16x16x128 now
        
        # Output layer
        # 最后，我们连接到输出层，使用该层作为logit
        logits = tf.layers.conv2d_transpose(x3, output_dim, 5, strides=2, padding='same')
        # 32x32x3 now
        
        # 输出
        out = tf.tanh(logits)
        
        return out</pre><p>我们完成的是一个转置卷积网络。</p>
<p>&nbsp;</p>
<h2>辨别器</h2>
<p>这是我们构建辨别器的地方，同样，这与你之前看到的非常相似，我们传入真实的图像，他们是32*32*3的张量，我们让他们通过一些卷积层，最后获得sigmoid输出，我们还要返回logit。用于在sigmoid交叉熵损失函数计算中使用，这跟你之前构建的卷积分类器非常像。你可以从较宽较高的层开始，但深度仅为3。下一个卷积层会更窄一些，但也会更深，像这样将卷积层堆叠起来，卷积层越往后越窄、越深。而最后一层只是一个全连接层，你将它平滑化，所以结尾将是只有一个单元的全连接层，你将它用作sigmoid输出。对于卷积层，我建议第一层以16、32、64个过滤器开始，这是层的深度。然后对于后面的每个层，深度翻倍，而宽度和高度减半。所以基本上你每添加一个新的卷积层，就给深度乘以2，而给宽度和高度除以2 。此外，你还会需要对每一个卷积层使用leaky ReLU激活和批量归一化，要确保你不对第一层使用，批量归一化，其他层都可以。</p><pre class="crayon-plain-tag"># 这是非常普通的卷积分类器，给你之前构建的一样，
# 与之前不同的是，我们这次要使用批量归一化和Leakuy ReLU
# 还有这里没有最大池化，没有全连接层，结尾处除外
def discriminator(x, reuse=False, alpha=0.2):
    with tf.variable_scope('discriminator', reuse=reuse):
        # Input layer is 32x32x3
        # 在第一层不要使用批量归一化，会出现一些奇怪的东西
        x1 = tf.layers.conv2d(x, 64, 5, strides=2, padding='same')
        relu1 = tf.maximum(alpha * x1, x1)
        # 16x16x64
        
        x2 = tf.layers.conv2d(relu1, 128, 5, strides=2, padding='same')
        bn2 = tf.layers.batch_normalization(x2, training=True)
        relu2 = tf.maximum(alpha * bn2, bn2)
        # 8x8x128
        
        x3 = tf.layers.conv2d(relu2, 256, 5, strides=2, padding='same')
        bn3 = tf.layers.batch_normalization(x3, training=True)
        relu3 = tf.maximum(alpha * bn3, bn3)
        # 4x4x256

        # Flatten it 我们扁平化并重塑它
        # 基本上扁平化只是将它重塑为一个具有大小的长向量
        # 也就是4*4*256 这是这一层的单元数量
        # flat 是扁平化后层中的单元数量
        flat = tf.reshape(relu3, (-1, 4*4*256))
        # 我们让他通过只有一个单元的全连接层，这个单元是我们要发给sigmoid函数的输出
        logits = tf.layers.dense(flat, 1)
        out = tf.sigmoid(logits)
        
        return out, logits</pre><p>&nbsp;</p>
<h2>模型损失</h2>
<p></p><pre class="crayon-plain-tag">def model_loss(input_real, input_z, output_dim, alpha=0.2):
    """
    Get the loss for the discriminator and generator
    :param input_real: Images from the real dataset
    :param input_z: Z input
    :param out_channel_dim: The number of channels in the output image
    :return: A tuple of (discriminator loss, generator loss)
    """
    g_model = generator(input_z, output_dim, alpha=alpha)
    d_model_real, d_logits_real = discriminator(input_real, alpha=alpha)
    d_model_fake, d_logits_fake = discriminator(g_model, reuse=True, alpha=alpha)

    d_loss_real = tf.reduce_mean(
        tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_real, labels=tf.ones_like(d_model_real)))
    d_loss_fake = tf.reduce_mean(
        tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_fake, labels=tf.zeros_like(d_model_fake)))
    g_loss = tf.reduce_mean(
        tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_fake, labels=tf.ones_like(d_model_fake)))

    d_loss = d_loss_real + d_loss_fake

    return d_loss, g_loss</pre><p>&nbsp;</p>
<h2>优化器</h2>
<p></p><pre class="crayon-plain-tag">def model_opt(d_loss, g_loss, learning_rate, beta1):
    """
    Get optimization operations
    :param d_loss: Discriminator loss Tensor
    :param g_loss: Generator loss Tensor
    :param learning_rate: Learning Rate Placeholder
    :param beta1: The exponential decay rate for the 1st moment in the optimizer
    :return: A tuple of (discriminator training operation, generator training operation)
    """
    # Get weights and bias to update
    t_vars = tf.trainable_variables()
    d_vars = [var for var in t_vars if var.name.startswith('discriminator')]
    g_vars = [var for var in t_vars if var.name.startswith('generator')]

    # Optimize
    with tf.control_dependencies(tf.get_collection(tf.GraphKeys.UPDATE_OPS)):
        d_train_opt = tf.train.AdamOptimizer(learning_rate, beta1=beta1).minimize(d_loss, var_list=d_vars)
        g_train_opt = tf.train.AdamOptimizer(learning_rate, beta1=beta1).minimize(g_loss, var_list=g_vars)

    return d_train_opt, g_train_opt</pre><p>&nbsp;</p>
<p>&nbsp;</p>
<h2>构建模型</h2>
<p>这里是一些用于构建模型的代码，这一次我基本上是将损失和优化器放入上面这些函数内，使这个构建过程更容易一些，这是一个叫作 GAN 的类。我们基本上在它里面构建整个模型，我们调用这些函数，构建输入，进行计算，获得损失和优化器。<br />
我们可以用这些来实际训练网络，像这样将它打包在一个对象里，以更容易地传递数据和进行构建。</p>
<p>&nbsp;</p><pre class="crayon-plain-tag">class GAN:
    def __init__(self, real_size, z_size, learning_rate, alpha=0.2, beta1=0.5):
        tf.reset_default_graph()
        
        self.input_real, self.input_z = model_inputs(real_size, z_size)
        
        self.d_loss, self.g_loss = model_loss(self.input_real, self.input_z,
                                              real_size[2], alpha=0.2)
        
        self.d_opt, self.g_opt = model_opt(self.d_loss, self.g_loss, learning_rate, beta1)</pre><p>这是用于展示正在生成的图像的一个函数，我们可以在训练过程中用它，查看进展如何。也可以在训练完成后使用它，看看是否要从生成器生成新的图像，我们可以使用此函数实际看到生成的图像。</p><pre class="crayon-plain-tag">def view_samples(epoch, samples, nrows, ncols, figsize=(5,5)):
    fig, axes = plt.subplots(figsize=figsize, nrows=nrows, ncols=ncols, 
                             sharey=True, sharex=True)
    for ax, img in zip(axes.flatten(), samples[epoch]):
        ax.axis('off')
        img = ((img - img.min())*255 / (img.max() - img.min())).astype(np.uint8)
        ax.set_adjustable('box-forced')
        im = ax.imshow(img, aspect='equal')
   
    plt.subplots_adjust(wspace=0, hspace=0)
    return fig, axes</pre><p>这个函数很明显是用来训练网络，我们只需传入网络net和数据dataset给它一些超参数，它会帮我们训练数据或训练网络。</p><pre class="crayon-plain-tag">def train(net, dataset, epochs, batch_size, print_every=10, show_every=100, figsize=(5,5)):
    saver = tf.train.Saver()
    sample_z = np.random.uniform(-1, 1, size=(72, z_size))

    samples, losses = [], []
    steps = 0

    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        for e in range(epochs):
            for x, y in dataset.batches(batch_size):
                steps += 1

                # Sample random noise for G
                batch_z = np.random.uniform(-1, 1, size=(batch_size, z_size))

                # Run optimizers
                _ = sess.run(net.d_opt, feed_dict={net.input_real: x, net.input_z: batch_z})
                _ = sess.run(net.g_opt, feed_dict={net.input_z: batch_z, net.input_real: x})

                if steps % print_every == 0:
                    # At the end of each epoch, get the losses and print them out
                    train_loss_d = net.d_loss.eval({net.input_z: batch_z, net.input_real: x})
                    train_loss_g = net.g_loss.eval({net.input_z: batch_z})

                    print("Epoch {}/{}...".format(e+1, epochs),
                          "Discriminator Loss: {:.4f}...".format(train_loss_d),
                          "Generator Loss: {:.4f}".format(train_loss_g))
                    # Save losses to view after training
                    losses.append((train_loss_d, train_loss_g))

                if steps % show_every == 0:
                    gen_samples = sess.run(
                                   generator(net.input_z, 3, reuse=True, training=False),
                                   feed_dict={net.input_z: sample_z})
                    samples.append(gen_samples)
                    _ = view_samples(-1, samples, 6, 12, figsize=figsize)
                    plt.show()

        saver.save(sess, './checkpoints/generator.ckpt')

    with open('samples.pkl', 'wb') as f:
        pkl.dump(samples, f)
    
    return losses, samples</pre><p>&nbsp;</p>
<h2>超参</h2>
<p>这里是你设置超参数和实际训练网络的地方，GAN 的训练稍有点复杂，因为它们对超参数非常敏感，人们不断通过各种实验，来找到最佳类型的参数，或者不是最佳的，但至少是有用的超参数。那么接下来发生的是&#8211;生成器和辨别器它们在互相玩游戏。而你必须设置超参数，以使生成器和辨别器，不会互相压制。生成器能够生成图像，而辨别器能够区分图像，确定图像是真是假。<br />
但同时 如果辨别器的区分能力太好，生成器就无法学习。<br />
所以你在这里要做的是尝试一些你自己的超参数，或者参阅这里的 <a href="https://arxiv.org/pdf/1511.06434.pdf">DCGAN 论文</a>，看看什么比较有用。我发现他们的参数对此数据库的确非常有效。但不会总是这样，当你在使用不同的数据库时，最好尝试不同的超参数。我发现的一点是，当超参数设置正确时，辨别器损失通常在 0.3 左右。这意味着：辨别器正确区分图像真假的概率为 50%，这基本上正是你想要的 对吧？<br />
因为你想要&#8211;你的辨别器&#8211; 或你希望生成器能生成看起来逼真的图像。然后对于辨别器，如果它无法确定是真是假，则它正确的概率将是 50%，基本就像掷硬币一样。所以这就是你在设置超参数时的目标。</p>
<p>而且我也从我的生成器损失看到他通常在2或3之类的左右，我是说当辨别器在0.3或者0.3左右时，你可以尝试下面这些超参数。想起个好头或者一次作对，请参阅 <a href="https://arxiv.org/pdf/1511.06434.pdf">DCGAN 论文</a>。</p><pre class="crayon-plain-tag">real_size = (32,32,3)
z_size = 100
# 学习率为0.0002
learning_rate = 0.0002
# 批大小128
batch_size = 128
# 训练25次
epochs = 25
alpha = 0.2
beta1 = 0.5

# Create the network
net = GAN(real_size, z_size, learning_rate, alpha=alpha, beta1=beta1)</pre><p>&nbsp;</p><pre class="crayon-plain-tag">dataset = Dataset(trainset, testset)

losses, samples = train(net, dataset, epochs, batch_size, figsize=(10,5))</pre><p>在他训练时就一边训练一边打印，图像和生成器和辨别器损失。从一堆噪声，到可以学习颜色，到显示一些斑点，到生成类似的数字，21个echop后，可以清晰的看清出数字了，</p><pre class="crayon-plain-tag">fig, ax = plt.subplots()
losses = np.array(losses)
plt.plot(losses.T[0], label='Discriminator', alpha=0.5)
plt.plot(losses.T[1], label='Generator', alpha=0.5)
plt.title("Training Losses")
plt.legend()</pre><p><img class="alignnone size-full wp-image-263" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/201806272050.png" alt="201806272050" width="372" height="264" /></p>
<p>这是生成器和辨别器在训练步长中的损失图，可以看到蓝色时辨别器损失他比较低，大概在0.5左右。</p>
<p>&nbsp;</p><pre class="crayon-plain-tag">fig, ax = plt.subplots()
losses = np.array(losses)
plt.plot(losses.T[0], label='Discriminator', alpha=0.5)
plt.plot(losses.T[1], label='Generator', alpha=0.5)
plt.title("Training Losses")
plt.legend()</pre><p><img class="alignnone size-full wp-image-264" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/201806272051.png" alt="201806272051" width="366" height="264" /></p><pre class="crayon-plain-tag">_ = view_samples(-1, samples, 6, 12, figsize=(10,5))</pre><p><img class="alignnone wp-image-265 size-full" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/201806272052.png" alt="201806272052" width="594" height="306" /></p><pre class="crayon-plain-tag">_ = view_samples(-1, samples, 6, 12, figsize=(10,5))</pre><p><img class="alignnone size-full wp-image-266" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/201806272053.png" alt="201806272053" width="594" height="306" /></p>
<p>上面时我们在训练中从生成器获得的最终图像。产生了一些不错的图像，有些能清晰的看清数字。</p>
<p>你也可以做一些改进，这需要从Ian Goodfellow和其他人的论文中了解。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.newlifeclan.com/ai/archives/256/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>生成对抗网络</title>
		<link>http://www.newlifeclan.com/ai/archives/240</link>
		<comments>http://www.newlifeclan.com/ai/archives/240#comments</comments>
		<pubDate>Mon, 25 Jun 2018 06:34:46 +0000</pubDate>
		<dc:creator><![CDATA[napoleon]]></dc:creator>
				<category><![CDATA[深度学习]]></category>

		<guid isPermaLink="false">http://www.newlifeclan.com/ai/?p=240</guid>
		<description><![CDATA[我们将在MNIST数据集中来训练生成对抗网络（GAN），并使用训练后的网络，生成一个新的手写数字。 GANS是 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>我们将在MNIST数据集中来训练生成对抗网络（GAN），并使用训练后的网络，生成一个新的手写数字。<span id="more-240"></span></p>
<p>GANS是由Ian Goodfellow 等其他人在2014年<a href="https://arxiv.org/abs/1406.2661" target="_blank">首次提出</a>，当时他在Yoshua Bengio教授的实验室做研究。此后，人气爆棚，下面有一些例子：</p>
<ul>
<li><a href="https://affinelayer.com/pixsrv/" target="_blank">Pix2Pix</a> 非常酷，你画一个东西，它能够创建一幅图像</li>
<li><a href="https://github.com/junyanz/CycleGAN" target="_blank">CycleGAN</a>  也很棒，比如实现让马看起来像斑马，真的很厉害</li>
<li><a href="https://github.com/wiseodd/generative-models" target="_blank">A whole list</a></li>
</ul>
<p>GAN背后的意思是你要有两个网络，一个是生成器G还有一个就是辨别器D，他们相互竞争。生成器将伪造的数据，让他们看起来更像真实数据，传递给辨别器。辨别器可以根据看到数据努力判定并预测它接收到的数据是真的还是假的。所以生成器将假数据传递给辨别器，而你将真实数据传递给辨别器，然后，由辨别器来判断是真是假。当你在训练时，生成器会学习生成图像和数据，让他们看起来尽量和真实数据一样。在这个过程中，他会学习模仿实际真实数据的概率分布。通过这种方式，你可以生成与真实世界中看起来一样的新图像、新数据。那么按照惯例，我们在这里要使用Tensorflow实现一些神经网络，来作为生成器和辨别器。</p>
<p>生成器经过训练以欺骗辨别器，它希望输出看起来尽可能接近实际数据的数据。辨别器经过训练可以确定哪些数据是真实的，哪些是假的。最终，生成器将生成很真实的数据，传送到辨别器。</p>
<p><img class="alignnone size-full wp-image-243" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/gan_diagram.png" alt="gan_diagram" width="714" height="319" /></p>
<p>上图显示的是GAN的结构，使用MNIST图像作为数据。潜在样本是生成器用来构造伪造图像的随机向量。当生成器通过训练学习时，它会计算出如何将这些随机向量映射为可以欺骗辨别器的可识别图像。</p>
<p>辨别器的输出是一个S形函数，其中0表示假图像，1表示真实图像。如果您只对生成新图像感兴趣，可以在训练后丢弃鉴别器。 现在，让我们看看我们如何在TensorFlow中构建这些东西。</p><pre class="crayon-plain-tag">%matplotlib inline

import pickle as pkl
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt</pre><p>首先，请在此导入包和数据集</p><pre class="crayon-plain-tag">from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data')</pre><p>输出</p><pre class="crayon-plain-tag">Extracting MNIST_data/train-images-idx3-ubyte.gz
Extracting MNIST_data/train-labels-idx1-ubyte.gz
Extracting MNIST_data/t10k-images-idx3-ubyte.gz
Extracting MNIST_data/t10k-labels-idx1-ubyte.gz</pre><p>&nbsp;</p>
<h2>模型输入</h2>
<p>首先，我们需要为图形创建输入。 我们需要两个输入，一个用于辨别器，一个用于生成器。 这里我们将调用辨别器输入inputs_real和生成器输入inputs_z。 我们将为他们分配适合每个网络的尺寸。其中real_dim作为真实输入的维度，z_dim作为z输入的维度。</p><pre class="crayon-plain-tag">def model_inputs(real_dim, z_dim):
    inputs_real = tf.placeholder(tf.float32, (None, real_dim), name='input_real') 
    inputs_z = tf.placeholder(tf.float32, (None, z_dim), name='input_z')
    
    return inputs_real, inputs_z</pre><p>首先，我们定义输入张量，使用tf.placeholder方法，设定float32数据类型，然后大小为任意批量大小，接下来设置我们真实数据的维度real_dim，我们将用它作为真实输入。</p>
<p>然后，是z输入，这是要进入生成器的向量。接下来的一样，tf.placeholder方法，设定float32数据类型，然后大小为任意批量大小，将进入生成器的向量的维度。</p>
<p><img class="alignnone size-full wp-image-244" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/gan_network.png" alt="gan_network" width="733" height="382" /></p>
<p>在这里，我们将构建生成器网络。这张图显示了，整个网络的样子，这里的生成器是我们的输入z，他只是一个随机向量，一种随机白噪声，我们会将其传入生成器。然后，生成器学习如何将这个随机向量z转变为tanh层中的图像，所以，我们在生成器中输入z，他将进入Leaky ReLU层，Leaky ReLU类似于普通的ReLU，你知道ReLU的负数端斜率为0，而Leaky ReLU的区别在于其负数端有一个较小的斜率，比如 0.01；正数端是相同的。tanh函数类似于sigmoid会将输入缩放到某个范围，但是tanh的输出范围为-1到1。这意味着，我们需要做转换工作，需要转换MNIST图像，将MNIST图像取值范围在-1到1之间，然后将其传入辨别器网络。</p>
<p>现在，只有生成器这部分，是你要完成的。</p>
<p>&nbsp;</p>
<p><strong>Variable Scope</strong></p>
<p>你其中要做的一件事，就是用tf.variable_scope。第一步，我们要为生成器和辨别器中的不同变量命名，你可以用name_scope来完成。但如果使用variable_scope你可以设置它，下次再次调用变量。我想说的是，有时候我们需要再次创建网络。以生成器为例：我们想要训练它，但也想从中取样。对于辨别器而言，我们要放入假图像和真实图像。那么，当我们做这些不同的事情，例如将假图像和真实图像放入辨别器里，我们希望重复使用之前的变量，也就是之前创建网络时所用的变量，因为如果不重用变量，当你运行函数，再次创建网络时，他会创建全新的变量，这并不是我们想要的。我们希望对真实和伪造的输入图像，使用相同的变量，要这样做，你只需要将代码放在tf.variable中，给出scope_name。这个例子中我们会对不同的网络，使用生成器和辨别器。这里设置reuse参数，如果你想创建新的网络，将reuse设为False。如果你想重用变量，将他设为True。</p><pre class="crayon-plain-tag">with tf.variable_scope('scope_name', reuse=False):
    # code here</pre><p>&nbsp;</p>
<h4 id="Leaky-ReLU">Leaky ReLU</h4>
<p>像我们之前讲到的，我们要使用Leaky ReLU，对于普通的ReLu你可以使用tf.maximum创建，但Tensorflow并没有自带Leaky ReLU函数，所以我们要自己创建，可以使用tf.maximum来创建，这里我们可以将函数设为max(a*x,x)。在这里 a只是一个控制尺度的参数。他控制负数端输出值的大小。通常情况下会设的非常下，比如 0.01 。那么他的意义就是:当x为负时，我们将取这个乘积，因为他更大。当x为正数时，我们将取值x，因为他更大。</p>
<p style="text-align: center">f(x)=max(α∗x,x)</p>
<h4 id="Tanh-Output">Tanh Output</h4>
<p>最后，我们需要得到生成器的tanh输出，下面函数中，想要输出tanh，以获取新的图像。 我们要返回logits，并传入tf.nn.sigmoid_cross_entroy_with_logites之中，</p><pre class="crayon-plain-tag">def generator(z, out_dim, n_units=128, reuse=False, alpha=0.01):
    with tf.variable_scope('generator', reuse=reuse):
        # Hidden layer
        h1 = tf.layers.dense(z, n_units, activation=None)
        # Leaky ReLU
        h1 = tf.maximum(alpha * h1, h1)
        
        # Logits and tanh output
        logits = tf.layers.dense(h1, out_dim, activation=None)
        out = tf.tanh(logits)
        
        return out</pre><p>你有隐藏层，需要将他变成线性层，然后传递给Leaky ReLU，你可以在这里执行计算获取logit和tanh的输出，然后返回out和logit。</p>
<p>上面的生成器，首先我们将它包裹在variable_scope中，使用generator作为作用域的名称，所以基本上所有的变量，都将以generator开头，这里我们选择重用，因为它将告诉作用域，重用本网络的变量。那么我们从函数参数中获得reuse。将他传递到这里。默认为false，如果我们让张量通过它，他会为我们创建一个新的网络。但是我们将他设置为true，这样你让另一个张量通过它，他就会重用之前创建的变量。对于隐藏层，我们使用tf.layers.dense进行构建，这是一个全链接层，你可以直接使用层模块，因为他是高级的，他会为你执行所有的权重初始化，那么我们传入z输入张量，并定义单元数量这是一个自变量，默认设置为128.他们不使用激活，所以只是一个线性层，之所以这么做，因为tensorflow没有leaky ReLU函数。所以我们得自己执行计算，这也意味着我们只能获得这层的线性输出。</p>
<p>然后，使他通过一些函数，来为我们计算Leaky ReLU。要这样做我们使用tf.maximun , alpha是一个比较下的数字，你要用它乘以这层的输入。如果h1为正，比如说+1，alpha*h1 是o.o1 ,h1是1，因为alpha默认为0.01。如果h1这个为负，那么最大值就是alpha*h1 。这样你就可以计算Leaky ReLU，一般情况下，如果是正输入，你将得到与输入相同的值，如果是负输入，你将得到比输入小的负值。</p>
<p>在这里我们使用tf.layers.dense获取logits，传入我们的ReLU输出、out_dim，然后使用tf.tanh创建生成器的输出。</p>
<p>&nbsp;</p>
<h2 id="Discriminator">Discriminator  辨别器</h2>
<p>基本上和生成器相同，只是我们使用的是sigmoid输出层，所以这里我们要再次使用tf.variable_scope，定义隐藏层，Leaky ReLU、logit和输出。在强调一些辨别器的输出，应该使用sigmoid。因为我们要让辨别器，给出非真即假的选择，1或0.</p><pre class="crayon-plain-tag">def discriminator(x, n_units=128, reuse=False, alpha=0.01):
    with tf.variable_scope('discriminator', reuse=reuse):
        # Hidden layer
        h1 = tf.layers.dense(x, n_units, activation=None)
        # Leaky ReLU
        h1 = tf.maximum(alpha * h1, h1)
        
        logits = tf.layers.dense(h1, 1, activation=None)
        out = tf.sigmoid(logits)
        
        return out, logits</pre><p>辨别器的代码和上面的生成器差不多，唯一的不同之处在于我们使用sigmoid作为输出。</p>
<p>&nbsp;</p>
<h2>超参数</h2>
<p></p><pre class="crayon-plain-tag"># Size of input image to discriminator 图片到辨别器大小
input_size = 784  # 28*28而来，是MNIST图像被平面化了
# Size of latent vector to generator
z_size = 100   # 传入生成器的本征向量大小，这只是随机生成的一种噪音，将他传入生成器，生成图像
# Sizes of hidden layers in generator and discriminator
g_hidden_size = 128  # 这两项是生成器和辨别器隐藏层大小
d_hidden_size = 128
# Leak factor for leaky ReLU
alpha = 0.01
# Smoothing 
smooth = 0.1</pre><p>&nbsp;</p>
<p>需要记住的一点是，当你在构建神经网络时。如果你的网络中有非线性隐藏层，它可以作为通用函数逼近器。这就是为什么我们将隐藏层与非线性激活函数 leaky ReLU 一起使用。说到 leaky ReLU，alpha 是渗漏系数，你可以将这些传入生成器和辨别器网络中。<br />
smooth是是标签平滑化的参数，我们下面会讲到。</p>
<p>&nbsp;</p>
<h2>构建网络</h2>
<p>这里你将使用之前的函数，你要获取真实的图像的输入，从你的模型输入函数获得本征向量输入，然后创建生成器网络和辨别器网络，d_model_real为真实图像的输出，d_logits_real为真实图像的logits。d_model_fake为假图像的输出，d_logits_fake为假图像的logits。我们要从生成器获取假图像，也就是g_model,然后将将假图像传入辨别器，来获得输出d_model_fake。<strong>由于我们想对真实图像和假图像，使用相同的权重，我们需要将reuse设为ture。</strong></p>
<p>所以我们的辨别器定义为discriminator(g_model, reuse=True)</p><pre class="crayon-plain-tag">tf.reset_default_graph()
# Create our input placeholders
input_real, input_z = model_inputs(input_size, z_size)

# Build the model
g_model = generator(input_z, input_size, n_units=n_units, alpha=alpha)
# g_model is the generator output

d_model_real, d_logits_real = discriminator(input_real, n_units=n_units, alpha=alpha)
d_model_fake, d_logits_fake = discriminator(g_model, reuse=True, n_units=n_units, alpha=alpha)</pre><p>好的，我来讲解上面的代码：</p>
<p>我们首先使用tf.reset_default_graph()，但它的作用基本上是擦除，你之前定义的任何图，直接重置它，然后当你调用它时，会构建一个新图。如果没有它，当你调用后面的函数时，你只会构建越来越大的图，然后变得很混乱，并最终崩溃。所以每次当你运行这部分时，记得将它放到这里。</p>
<p>下面我们使用输入大小，调用model_inputs这个input_size,input_size是我们MNIST图像的大小，实际上MNIST图像将被扁平化，成为784维长的向量。然后传入生成器的向量大小z_size,我们会得到真图输入的张量和另一个张量，它是进入生成器的本征向量输入。</p>
<p>下面，我们使用input_z来创建我们的生成器网络，这里的g_model是我们生成器的tanh输出，然后这是logit。</p>
<p>接下来，我们构建辨别器，传入真图输入向量input_real,获得sigmoid输出和logit，记住sigmoid的作用就是尝试决定这是真图还是假图，真则输出1，假则输出0.</p>
<p>然后我们还将传入假图像，假图像来自生成器，也就是这个 g_model，生成器的 tanh 输出，是一个我们将传递给辨别器的图像，此图像将尝试欺骗辨别器。</p>
<p>让后者认为它是真的，由于我们想对真图像和假图像，使用相同的权重 我们需要在此将 reuse 设为 true，然后传入来自生成器的假图像。</p>
<p>好的 接下来我们将讨论，此 GAN 网络的损失和优化器。</p>
<p>&nbsp;</p>
<h2 id="Discriminator-and-Generator-Losses">Discriminator and Generator Losses  辨别器和生成器的损失</h2>
<p>这里你将实施代码，来获得辨别器和生成器损失，在GAN中，我们实际要做的是，同时训练辨别器和生成器网络，我们需要这两个不同网络的损失，对于辨别器，总损失是真实图像和假图像损失之和，记得在前面的代码块中，我们定义了真实图像和假图像的输出，所以我们可以使用这些来获得损失。这里我们使用sigmoid交叉熵</p><pre class="crayon-plain-tag">tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=logits, labels=labels))</pre><p>和往常一样，你只需传入logits，传入标签，然后为了获得传入的所有样本的总损失，我们使用tf.reduce_mean。</p>
<p>对于真实图像，我们使用来自真实图像的logits，我们已在上面定义，对于标签，由于这些是真实图像，而且我们想让辨别器直到他们是真的，我们希望标签（真图的输出为1）全部为1。</p>
<p>为了帮助辨别器更好的泛化，我们要执行一个叫做标签平滑的操作，我们要做的是创建一个叫做smooth的参数，它略小于1，然后我们用标签乘以该参数；例如 如果smooth是0.9，然后你用标签乘以0.9，那么你的实际标签将是0.9.</p>
<p>假数据的辨别器损失也类似，那么我们再次获取logits虚假图像的d_logits,我们在上面做了定义，然后我们设定这些标签（也就是假输出为0）全部为0，也就是说0，对应假图像，所以当遇到假图时，我们希望标签为0。最后，对于生成器我们再次使用d_logits_fake，但这次，我们的标签全部为1，因为记得我们想让生成器欺骗辨别器，所以我们想让辨别器以为假图是真的。再一次1对应真，我们的生成器，让辨别器将所有这些都视为真的。</p>
<p>在这里我们使用tf.nn.sigmoid_cross_entropy_with_logits 传入适当的logits和标签，来计算所有损失。</p><pre class="crayon-plain-tag"># Calculate losses
d_loss_real = tf.reduce_mean(
                  tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_real, 
                                                          labels=tf.ones_like(d_logits_real) * (1 - smooth)))
d_loss_fake = tf.reduce_mean(
                  tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_fake, 
                                                          labels=tf.zeros_like(d_logits_real)))
d_loss = d_loss_real + d_loss_fake

g_loss = tf.reduce_mean(
             tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_fake,
                                                     labels=tf.ones_like(d_logits_fake)))</pre><p>下面我们来讲解上面的代码：</p>
<p>我们在这里看到的时网络的损失， 这是我们用来训练模型的东西。</p>
<p>d_loss_real = tf.reduce_mean( tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_real, labels=tf.ones_like(d_logits_real) * (1 &#8211; smooth)))</p>
<p>首先，是真实的图像的辨别器损失，我们使用tf.reduce_mean来获取我们传入的所有图像的损失平均值，里面使用tf.nn.sigmoid_cross_entropy_with_logits来实际计算该损失，里面传入logits真图的logits，然后是标签labels，我们希望这些均为1，使用tf.ones_like来获得与d_logits_real形状相同的为1的张量，然后进行标签平滑化，所以要给他乘以(1 &#8211; smooth)</p>
<p>接下来，是假图像的损失，别的差不多，但是labels我们希望为0，因为他是假图，所以使用tf.zeros_like(d_logits_real)。</p>
<p>获取总损失，就需要将它们加起来。</p>
<p>对于生成器的损失，我们同样使用假数据logits:d_logits_fake。但是这次我们想让辨别器认为他是真的，所以我们想让辨别器对这些假图输出1，所以labels应该为1，使用tf.ones_like(d_logits_fake)</p>
<p>&nbsp;</p>
<h2>优化器</h2>
<p>我们需要做的最后一件事，就是构建优化器，和往常一样，我们将在这里使用Adam优化器，因为它非常好用，我们要做的就是，分别对生成器训练辨别器变量。首先，你需要获取所有的可训练的变量，要这样做，你只需使用tf.trainable_variables() 。他的作用是返回，所有可训练的变量对象的，一个列表，获取列表后，你可遍历它，并对这些变量对象执行操作。</p>
<p>对于生成器优化器，我们只需要生成器变量，你可能记得，我们之前使用variable_scope命名所有的生成器变量，使他们以generator一词开头，以便我们遍历得到的，可训练变量的列表。然后创建一个新的列表，仅包含以generator开头的变量。这样我们的生成器图中，将只有可训练的变量，然后我们可以将它传入Adam优化器中，仅训练那些有生成器损失的变量，然后你基本上可以对辨别器，执行相同的操作，即获得所有以discriminator开头的变量，然后在优化器，即tf.train.AdamOptimizer()中，调用minimize方法时，传入变量列表，仅传入那些将在训练中更新的变量，那么我们在下面实现优化器</p><pre class="crayon-plain-tag"># Optimizers
learning_rate = 0.002

# Get the trainable_variables, split into G and D parts
t_vars = tf.trainable_variables()
g_vars = [var for var in t_vars if var.name.startswith('generator')]
d_vars = [var for var in t_vars if var.name.startswith('discriminator')]

d_train_opt = tf.train.AdamOptimizer(learning_rate).minimize(d_loss, var_list=d_vars)
g_train_opt = tf.train.AdamOptimizer(learning_rate).minimize(g_loss, var_list=g_vars)</pre><p>像我之前所说，我们要将可训练变量，分为生成器和辨别器两部分，因为我们将用不同的优化器，来分别训练这些变量。那么要获取所有可训练变量，只需执行tf.trainable_variables()，他会返回一个列表，显示你的图表中可训练的所有变量。</p>
<p>也就是说此列表包含变量对象，这些变量对象有属性名，即“字符串”，生成器我们用了variable_scope始终以generator开头，所以可以将他们分成两个部分。</p>
<p>然后，我们将他传入到优化器中，给出优化器学习率，然后我们将最小化辨别器损失，传入var_list=d_vars 辨别器变量。生成器同理。</p>
<p>&nbsp;</p>
<h2>训练你的模型</h2>
<p>这里是我们用于训练网络的代码，与你看到的其他代码很相似。</p><pre class="crayon-plain-tag">batch_size = 100
epochs = 100
samples = []
losses = []
# Only save generator variables
saver = tf.train.Saver(var_list=g_vars)
with tf.Session() as sess:
    # 与往常一样，我们先开始一个会话，他会初始化我们可以开始训练的所有变量
    sess.run(tf.global_variables_initializer())
    
    for e in range(epochs):
        # 循环训练批次
        for ii in range(mnist.train.num_examples//batch_size):
            # 获取批次，他会给我们一批数据，一个批次是一个元祖。
            # 第一个元素是我们的图像，第二个元素就是标签，但是我们不关心标签，只获得图像
            batch = mnist.train.next_batch(batch_size)
            
            # Get images, reshape and rescale to pass to D
            # 只获得第0批，他会像我们提供图像实际上是28*28的数组
            # 我们想将他们展开成张量，并出传入我们的辨别器中
            # reshape是重塑它，批量大小784=28*28而来
            # 对于批量图像，生成器使用tanh输出，这意味着图像会缩放到-1到1范围内
            
            batch_images = batch[0].reshape((batch_size, 784))
            # 由于NNIST图像实际上是0到1，我们必须重新缩放，
            # 下面的batch_images*2 - 1会进入辨别器，真实图片重新缩放为-1到1
            batch_images = batch_images*2 - 1
            
            # Sample random noise for G
            # 这里获取生成器输入，生成器本征向量，这里从-1到1的随机噪声
            batch_z = np.random.uniform(-1, 1, size=(batch_size, z_size))
            
            # Run optimizers
            # 运行优化器 传入input_real真实图像，然后传入本征向量input_z,
            # 进入生成器生成假图，我们的d_train_opt通过训练，不断降低d_loss
            # d_loss是真实图像损失和假图损失之和，所要对真图和假图优化
            _ = sess.run(d_train_opt, feed_dict={input_real: batch_images, input_z: batch_z})
            # 对于生成器我们只需要传入本征向量
            _ = sess.run(g_train_opt, feed_dict={input_z: batch_z})
        
        # At the end of each epoch, get the losses and print them out
        # 这里我们是跟踪网络训练性能，每个epoch获取辨别器和生成器各自损失
        train_loss_d = sess.run(d_loss, {input_z: batch_z, input_real: batch_images})
        train_loss_g = g_loss.eval({input_z: batch_z})
            
        print("Epoch {}/{}...".format(e+1, epochs),
              "Discriminator Loss: {:.4f}...".format(train_loss_d),
              "Generator Loss: {:.4f}".format(train_loss_g))    
        # Save losses to view after training
        losses.append((train_loss_d, train_loss_g))
        
        # Sample from generator as we're training for viewing afterwards
        sample_z = np.random.uniform(-1, 1, size=(16, z_size))
        gen_samples = sess.run(
                       generator(input_z, input_size, reuse=True),
                       feed_dict={input_z: sample_z})
        samples.append(gen_samples)
        saver.save(sess, './checkpoints/generator.ckpt')

# Save training generator samples
with open('train_samples.pkl', 'wb') as f:
    pkl.dump(samples, f)</pre><p>&nbsp;</p>
<h2>训练损失</h2>
<p>这段代码输出的就是训练损失图，损失一般都是刚开始高，然后降低，最后，随着训练会变得平缓</p><pre class="crayon-plain-tag">fig, ax = plt.subplots()
losses = np.array(losses)
plt.plot(losses.T[0], label='Discriminator')
plt.plot(losses.T[1], label='Generator')
plt.title("Training Losses")
plt.legend()</pre><p>这里是100个epoch后的结果，如果训练更久，效果更好</p>
<p><img class="alignnone size-full wp-image-251" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/tuxiangxiazai.png" alt="tuxiangxiazai" width="375" height="264" /></p>
<p>&nbsp;</p>
<h2>训练生成器样本</h2>
<p>下面用来查看我们保存的样本的一些代码，上面的代码实际上将样本保存在了磁盘上</p><pre class="crayon-plain-tag">def view_samples(epoch, samples):
    fig, axes = plt.subplots(figsize=(7,7), nrows=4, ncols=4, sharey=True, sharex=True)
    for ax, img in zip(axes.flatten(), samples[epoch]):
        ax.xaxis.set_visible(False)
        ax.yaxis.set_visible(False)
        im = ax.imshow(img.reshape((28,28)), cmap='Greys_r')
    
    return fig, axes</pre><p>加载之前保存的训练样本</p><pre class="crayon-plain-tag"># Load samples from generator taken while training
with open('train_samples.pkl', 'rb') as f:
    samples = pkl.load(f)</pre><p></p><pre class="crayon-plain-tag">_ = view_samples(-1, samples)</pre><p><img class="alignnone size-full wp-image-252" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/201806271457.png" alt="201806271457" width="412" height="401" /></p>
<p>这基本上是我们看到的结果，这是最后依次epoch从生成器获得的样本。这时生成器已经训练了一会儿，我们可以看到它实际产生了一些比较清晰的数字，这里有一个7，3，1有的像2，有的有些奇怪，但总体而言，他们产生了一些不错的数字。不过这只是它生成图像的一个较小样本，你会看到一些杂乱的东西，一些噪声。</p>
<p>如果我们训练生成器时间更久的话，这些奇怪的图就会消失，会获得清晰的数字。</p>
<p>&nbsp;</p>
<p>下面展示每10次epoch产生的生成器图像，这只是向你展示生成器训练进度的一种方式，刚开始所有的东西，都是一团白色的噪声。</p>
<p>然后不断学习，将边缘变黑，不断有模糊的数字形状，直到清晰。</p><pre class="crayon-plain-tag">rows, cols = 10, 6
fig, axes = plt.subplots(figsize=(7,12), nrows=rows, ncols=cols, sharex=True, sharey=True)

for sample, ax_row in zip(samples[::int(len(samples)/rows)], axes):
    for img, ax in zip(sample[::int(len(sample)/cols)], ax_row):
        ax.imshow(img.reshape((28,28)), cmap='Greys_r')
        ax.xaxis.set_visible(False)
        ax.yaxis.set_visible(False)</pre><p><img class="alignnone size-full wp-image-253" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/201806271502.png" alt="201806271502" width="412" height="673" /></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>从生成器采样</h2>
<p>现在我们已经训练好了生成器，我们可以放入新的向量，得到新的图像</p><pre class="crayon-plain-tag">saver = tf.train.Saver(var_list=g_vars)
with tf.Session() as sess:
    # 用来加载我们从训练中保存的检查点，生成一些新的本征向量，将这些放入生成器
    # 并获得一些可以看到的新图像，这里有非常清晰的0、1、7
    saver.restore(sess, tf.train.latest_checkpoint('checkpoints'))
    sample_z = np.random.uniform(-1, 1, size=(16, z_size))
    gen_samples = sess.run(
                   generator(input_z, input_size, reuse=True),
                   feed_dict={input_z: sample_z})
_ = view_samples(0, [gen_samples])</pre><p><img class="alignnone size-full wp-image-254" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/201806271503.png" alt="201806271503" width="412" height="401" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.newlifeclan.com/ai/archives/240/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>解决 dlerror: cublasCreate_v2 not found</title>
		<link>http://www.newlifeclan.com/ai/archives/234</link>
		<comments>http://www.newlifeclan.com/ai/archives/234#comments</comments>
		<pubDate>Sun, 24 Jun 2018 13:31:49 +0000</pubDate>
		<dc:creator><![CDATA[napoleon]]></dc:creator>
				<category><![CDATA[深度学习]]></category>

		<guid isPermaLink="false">http://www.newlifeclan.com/ai/?p=234</guid>
		<description><![CDATA[在windows10使用tensorflow1.0.0和python3.5的环境下，我的cuda使用的9.0。 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>在windows10使用tensorflow1.0.0和python3.5的环境下，我的cuda使用的9.0。<span id="more-234"></span></p>
<p>在运行：</p><pre class="crayon-plain-tag">&gt;&gt;&gt; import tensorflow as tf</pre><p>出现以下错误</p><pre class="crayon-plain-tag">108] Couldn't open CUDA library cublas64_80.dll                               
102] Couldn't open CUDA library cudnn64_5.dll                        
108] Couldn't open CUDA library cufft64_80.dll                   
108] Couldn't open CUDA library curand64_80.dll</pre><p>这是因为tensorflow1.0.0只能支持到80，所以他会找***_80.dll,cudnn64_5.dll,但这些dll都不存在，怎么办呢？</p>
<p>其实很简单：</p>
<p>1.来到CUDA\v9.0\bin</p>
<p>2.复制cublas64_90.dll  cudnn64_7.dll   cufft64_90.dll  curand64_90.dll   将其分别复制成新的 cublas64_80.dll  cudnn64_5.dll   cufft64_80.dll  curand64_80.dll</p>
<p>&nbsp;</p>
<p>重启命令行工具</p>
<p>重新输入</p><pre class="crayon-plain-tag">&gt;&gt;&gt; import tensorflow as tf</pre><p>&nbsp;</p><pre class="crayon-plain-tag">108] successfully opened CUDA library cublas64_80.dll                               
102] successfully opened CUDA library cudnn64_5.dll                        
108] successfully opened CUDA library cufft64_80.dll                   
108] successfully opened CUDA library curand64_80.dll</pre><p>大功告成！！！！</p>
<p>&nbsp;</p>
<p>如果遇到更多tensorflow的gpu问题，请看：<a href="http://www.newlifeclan.com/ai/archives/232">http://www.newlifeclan.com/ai/archives/232</a></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.newlifeclan.com/ai/archives/234/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>如何理解tf.contrib.rnn.BasicLSTMCell(num_units)中的num_units</title>
		<link>http://www.newlifeclan.com/ai/archives/170</link>
		<comments>http://www.newlifeclan.com/ai/archives/170#comments</comments>
		<pubDate>Thu, 21 Jun 2018 14:12:30 +0000</pubDate>
		<dc:creator><![CDATA[napoleon]]></dc:creator>
				<category><![CDATA[深度学习]]></category>

		<guid isPermaLink="false">http://www.newlifeclan.com/ai/?p=170</guid>
		<description><![CDATA[基本的LSTM细胞单元在TensorFlow中声明为： tf.contrib.rnn.BasicLSTMCel [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>基本的LSTM细胞单元在TensorFlow中声明为：</p>
<p>tf.contrib.rnn.BasicLSTMCell(num_units)<span id="more-170"></span></p>
<p>这里的num_units指的是LSTM单元中的单位数。</p>
<p>num_units也可以解释为前馈神经网络隐藏层的类比。前馈神经网络隐层中的节点。</p>
<p>num_units数目等于LSTM网络每个时间步长的LSTM单元的数量。以下图片应该可以帮助你理解：</p>
<p><img class="alignnone size-full wp-image-171" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/5ca3b38110cd48ffb57cfe4a3afae787.jpeg" alt="5ca3b38110cd48ffb57cfe4a3afae787" width="772" height="484" /></p>
<p>&nbsp;</p>
<p>有时用 lstm_size 表示 ：这是 LSTM 网络的隐藏层中的单元数量，LSTM 细胞中实际上有四个不同的网络层，有三个 sigma 层和一个 TNH 层，这是每一层中的单元数。如果你将它设置成 256，那么这四层中的每一层就有 256 个单元。</p>
<p>num_units中的每一个：都可以将它看作LSTM网络中的一个标准的LSTM单元。</p>
<p><img class="alignnone size-full wp-image-172" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/7bcc403a610f45a5bd4dcbbec7ed650e.jpeg" alt="7bcc403a610f45a5bd4dcbbec7ed650e" width="363" height="312" /></p>
<p>&nbsp;</p>
<p>参见：https://www.sohu.com/a/191568823_642762</p>
]]></content:encoded>
			<wfw:commentRss>http://www.newlifeclan.com/ai/archives/170/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RNN下序列分批</title>
		<link>http://www.newlifeclan.com/ai/archives/168</link>
		<comments>http://www.newlifeclan.com/ai/archives/168#comments</comments>
		<pubDate>Thu, 21 Jun 2018 11:10:24 +0000</pubDate>
		<dc:creator><![CDATA[napoleon]]></dc:creator>
				<category><![CDATA[深度学习]]></category>

		<guid isPermaLink="false">http://www.newlifeclan.com/ai/?p=168</guid>
		<description><![CDATA[我们有一个【1 2 3 4 5 6 7 8 9 10 11 12】数字序列。 我们希望将他传递给RNN，但是为 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>我们有一个【1 2 3 4 5 6 7 8 9 10 11 12】数字序列。</p>
<p>我们希望将他传递给RNN，但是为了更好的训练，我们可以将它拆分为两个部分。<span id="more-168"></span></p>
<p>【1 2 3 4 5 6 】</p>
<p>【7 8 9 10 11 12】</p>
<p>那么批次大小就是我们的序列数，这个批次大小就是 2</p>
<p>【1 2 3 4 5 6 】    &#8212;&#8211;&gt; 1</p>
<p>【7 8 9 10 11 12】  &#8212;&#8212;&#8211;&gt; 2</p>
<p>&nbsp;</p>
<p>序列长度就是，我们每个批次我们使用多少数据。 比如我们设置为3</p>
<p>那么 我们传入网络第一批次数据将是</p>
<p>【1 2 3 4 5 6 】</p>
<p>【7 8 9 10 11 12】</p>
<p>中的</p>
<p>【1 2 3 】</p>
<p>【7 8 9 】</p>
<p>被传入。</p>
<p>下一批次，也就是第二批次，我们会依次，传入后面的三个值，</p>
<p>【4 5 6 】</p>
<p>【10 11 12】</p>
<p>依次类推，直到数据结束。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.newlifeclan.com/ai/archives/168/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>反向传播算法权重矩阵中W1的更新规则</title>
		<link>http://www.newlifeclan.com/ai/archives/151</link>
		<comments>http://www.newlifeclan.com/ai/archives/151#comments</comments>
		<pubDate>Thu, 14 Jun 2018 04:51:31 +0000</pubDate>
		<dc:creator><![CDATA[napoleon]]></dc:creator>
				<category><![CDATA[深度学习]]></category>

		<guid isPermaLink="false">http://www.newlifeclan.com/ai/?p=151</guid>
		<description><![CDATA[下图是一个前馈网络，包含 一个输入 x 两个隐藏层，每层包括两个神经元 一个输出 以下两个路径W1​有利于得到 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>下图是一个前馈网络，包含<span id="more-151"></span></p>
<ul>
<li>一个输入 x</li>
<li>两个隐藏层，每层包括两个神经元</li>
<li>一个输出</li>
</ul>
<p><img class="alignnone size-full wp-image-152" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/screen-shot-2017-12-04-at-12.31.11-pm.png" alt="screen-shot-2017-12-04-at-12.31.11-pm" width="1124" height="716" /></p>
<p>以下两个路径<span class="katex"><span class="katex-html"><span class="base"><span class="mord"><span class="mord mathit">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="sizing reset-size6 size3 mtight"><span class="mord mathrm mtight">1</span></span></span><span class="vlist-s">​</span></span></span></span></span></span></span></span>有利于得到输出：</p>
<ul>
<li>路径 A</li>
<li>路径 B</li>
</ul>
<p>(下图展示了这两个路径)</p>
<p><img class="alignnone size-full wp-image-156 aligncenter" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/screen-shot-2017-12-04-at-12.49.13-pm.png" alt="screen-shot-2017-12-04-at-12.49.13-pm" width="1194" height="492" /></p>
<p style="text-align: center">路径A</p>
<p><img class="alignnone size-full wp-image-157 aligncenter" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/screen-shot-2017-12-04-at-12.49.52-pm.png" alt="screen-shot-2017-12-04-at-12.49.52-pm" width="1162" height="466" /></p>
<p style="text-align: center">路径B</p>
<p>（应用链式法则时）路径 A 的数学导数是：</p>
<p><img class="alignnone size-full wp-image-153" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/screen-shot-2017-12-04-at-12.40.54-pm.png" alt="screen-shot-2017-12-04-at-12.40.54-pm" width="484" height="142" /></p>
<p>（应用链式法则时）路径 B 的数学导数是：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><a href="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/screen-shot-2017-12-04-at-12.42.42-pm.png"><img class="alignnone size-full wp-image-155" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/screen-shot-2017-12-04-at-12.42.55-pm.png" alt="screen-shot-2017-12-04-at-12.42.55-pm" width="475" height="135" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div>
<div class="index--container--2OwOl">
<div class="index--atom--lmAIo layout--content--3Smmq">
<div class="ltr">
<div class="index--markdown--3w8oF ureact-markdown ">
<p>为了完成计算，我们需要考虑有利于计算 y 的所有路径。在这种例子下，我们提到了两条路径。因此，最后的计算是每条路径计算得出的导数之和。</p>
</div>
</div>
</div>
<div class="index--instructor-notes-container--24U8Y shared--outer-container--3eppq"></div>
</div>
</div>
<div></div>
<p><a href="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/screen-shot-2017-12-04-at-12.42.42-pm.png"><img class="alignnone size-full wp-image-154" src="http://www.newlifeclan.com/ai/wp-content/uploads/sites/9/2018/06/screen-shot-2017-12-04-at-12.42.42-pm.png" alt="screen-shot-2017-12-04-at-12.42.42-pm" width="803" height="146" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.newlifeclan.com/ai/archives/151/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>卷积神经网络8：继续卷积</title>
		<link>http://www.newlifeclan.com/ai/archives/112</link>
		<comments>http://www.newlifeclan.com/ai/archives/112#comments</comments>
		<pubDate>Sun, 27 May 2018 13:51:27 +0000</pubDate>
		<dc:creator><![CDATA[napoleon]]></dc:creator>
				<category><![CDATA[深度学习]]></category>

		<guid isPermaLink="false">http://www.newlifeclan.com/ai/?p=112</guid>
		<description><![CDATA[]]></description>
				<content:encoded><![CDATA[<div style="width: 640px; height: 360px; " class="wp-video"><!--[if lt IE 9]><script>document.createElement('video');</script><![endif]-->
<video class="wp-video-shortcode" id="video-112-1" width="640" height="360" preload="metadata" controls="controls"><source type="video/mp4" src="http://www.newlifeclan.com/fileload/videolearn/8.继续卷积.mp4?_=1" /><a href="http://www.newlifeclan.com/fileload/videolearn/8.继续卷积.mp4">http://www.newlifeclan.com/fileload/videolearn/8.继续卷积.mp4</a></video></div>
]]></content:encoded>
			<wfw:commentRss>http://www.newlifeclan.com/ai/archives/112/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://www.newlifeclan.com/fileload/videolearn/8.继续卷积.mp4" length="0" type="video/mp4" />
		</item>
		<item>
		<title>卷积神经网络7：卷积网络</title>
		<link>http://www.newlifeclan.com/ai/archives/110</link>
		<comments>http://www.newlifeclan.com/ai/archives/110#comments</comments>
		<pubDate>Sun, 27 May 2018 13:50:33 +0000</pubDate>
		<dc:creator><![CDATA[napoleon]]></dc:creator>
				<category><![CDATA[深度学习]]></category>

		<guid isPermaLink="false">http://www.newlifeclan.com/ai/?p=110</guid>
		<description><![CDATA[问1：What are the width, height and depth for padding = &#038; [&#8230;]]]></description>
				<content:encoded><![CDATA[<div style="width: 640px; height: 360px; " class="wp-video"><video class="wp-video-shortcode" id="video-110-2" width="640" height="360" preload="metadata" controls="controls"><source type="video/mp4" src="http://www.newlifeclan.com/fileload/videolearn/7.特征图大小1.mp4?_=2" /><a href="http://www.newlifeclan.com/fileload/videolearn/7.特征图大小1.mp4">http://www.newlifeclan.com/fileload/videolearn/7.特征图大小1.mp4</a></video></div>
<p><span id="more-110"></span></p>
<p>问1：What are the width, height and depth for padding = &#8216;same&#8217;, stride = 1?</p>
<p>Enter your answers in the format &#8220;width, height, depth&#8221;</p>
<p>答1：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>问2：What are the width, height and depth for padding = &#8216;valid&#8217;, stride = 1?</p>
<p>Enter your answers in the format &#8220;width, height, depth&#8221;</p>
<p>答2：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div style="width: 640px; height: 360px; " class="wp-video"><video class="wp-video-shortcode" id="video-110-3" width="640" height="360" preload="metadata" controls="controls"><source type="video/mp4" src="http://www.newlifeclan.com/fileload/videolearn/7.特征图大小.mp4?_=3" /><a href="http://www.newlifeclan.com/fileload/videolearn/7.特征图大小.mp4">http://www.newlifeclan.com/fileload/videolearn/7.特征图大小.mp4</a></video></div>
]]></content:encoded>
			<wfw:commentRss>http://www.newlifeclan.com/ai/archives/110/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://www.newlifeclan.com/fileload/videolearn/7.特征图大小1.mp4" length="0" type="video/mp4" />
<enclosure url="http://www.newlifeclan.com/fileload/videolearn/7.特征图大小.mp4" length="0" type="video/mp4" />
		</item>
	</channel>
</rss>
