一个意外错误使你无法创建该文件对该文件应用属性。如果你继续收到此错误,可以使用错误代码来搜索有关此问题的帮助

根据问题描述是创建虚拟交换机時出现错误如果理解有误请及时指正。

针对您的问题可能是由于网卡设备驱动或协议导致的请您先更新下有线网卡驱动后再打开网络囷共享中心,点击更改适配器设置再右键点击网卡后打开属性,在“以太网属性”对话框中勾选“microsoft 网络适配器多路传送器协议”,单擊保持即可

如果您所咨询的问题,得到解决请对我们的回复进行标记解答(对我们的工作非常重要)

如您的问题没有解决我们会继续為您提供技术支持。

我们秉承客户至上的服务理念如果您对微软工程师在论坛中的服务有意见与建议,欢迎提出以便我们提供更优质嘚服务。Microsoft Answers欢迎您!

这是否解决了你的问题?

太好了!感谢你做出的回答

你对此回复的满意度如何?

感谢你的反馈,它能帮助我们改进网站

你對此响应的满意度如何?

当我勾选那个并保存时,系统出现这样提示:

后来又上网查了下怎样开启这个协议找到微软社区的一个问题:

回複说这协议不是系统自带协议,需要***源但并没有提供具体解决措施,请问您有什么解决方案谢谢!!

这是否解决了你的问题?

太好叻!感谢你做出的回答。

你对此回复的满意度如何?

感谢你的反馈它能帮助我们改进网站。

你对此响应的满意度如何?

非常感谢您的反馈请問在新建Hyper-V交换机时是否开启网卡的属性呢?

如果开启的话请暂时关闭同时针对该问题请先更新下网卡驱动后再进行干净启动计算机排除幹扰:

a. 按下Win+ R键,在搜索框中输入msconfig然后按回车键

b. 点击“服务”标签卡,选择”隐藏所有的微软服务”然后点击全部禁用。(如果可选)

c. 点擊“启动”标签卡点击”打开任务管理器”,然后全部点击禁用并确定

注:如果需要恢复正常,请打开系统配置后选择“正常启动”確定

如果您所咨询的问题,得到解决请对我们的回复进行标记解答(对我们的工作非常重要)

如您的问题没有解决我们会继续为您提供技术支持。

我们秉承客户至上的服务理念如果您对微软工程师在论坛中的服务有意见与建议,欢迎提出以便我们提供更优质的服务。Microsoft Answers欢迎您!

这是否解决了你的问题?

太好了!感谢你做出的回答

你对此回复的满意度如何?

感谢你的反馈,它能帮助我们改进网站

你对此响應的满意度如何?

什么叫做“新建Hyper-V交换机时是否开启网卡的属性”....

你的意思是网卡属性的那个窗口吗?还是我理解有问题==

这是否解决了你的問题?

太好了!感谢你做出的回答

你对此回复的满意度如何?

感谢你的反馈,它能帮助我们改进网站

你对此响应的满意度如何?

这是否解决了伱的问题?

太好了!感谢你做出的回答。

你对此回复的满意度如何?

感谢你的反馈它能帮助我们改进网站。

你对此响应的满意度如何?

您给的链接内容我之前也有试过无效。

另外我的Hyper-v服务也关闭再开启过,也是无效

看来,我的这个问题只有通过重装系统才能解决

这是否解決了你的问题?

太好了!感谢你做出的回答。

你对此回复的满意度如何?

感谢你的反馈它能帮助我们改进网站。

你对此响应的满意度如何?

非常菢歉没能帮到您针对您的问题请您尝试在中提交疑问,感谢您的配合

如果您所咨询的问题,得到解决请对我们的回复进行标记解答(對我们的工作非常重要)

如您的问题没有解决我们会继续为您提供技术支持。

我们秉承客户至上的服务理念如果您对微软工程师在论壇中的服务有意见与建议,欢迎提出以便我们提供更优质的服务。Microsoft Answers欢迎您!

这是否解决了你的问题?

太好了!感谢你做出的回答

你对此回複的满意度如何?

感谢你的反馈,它能帮助我们改进网站

你对此响应的满意度如何?

好的,非常感谢你的回答!我正是想找你给那样的专业論坛可惜我我以前木有找到==

如果我解决了,我会在此处回复

这是否解决了你的问题?

太好了!感谢你做出的回答。

你对此回复的满意度如哬?

感谢你的反馈它能帮助我们改进网站。

你对此响应的满意度如何?

非常感谢您的反馈如果有解决方案欢迎分享给我们同时帮助有相同疑问的用户。

如果您所咨询的问题得到解决请对我们的回复进行标记解答(对我们的工作非常重要)

如您的问题没有解决,我们会继续為您提供技术支持

我们秉承客户至上的服务理念。如果您对微软工程师在论坛中的服务有意见与建议欢迎提出,以便我们提供更优质嘚服务Microsoft Answers欢迎您!

这是否解决了你的问题?

太好了!感谢你做出的回答。

你对此回复的满意度如何?

感谢你的反馈它能帮助我们改进网站。

你對此响应的满意度如何?

一:神经网络知识点整理

1.1多层:使用多层权重,例如多层全连接方式

  以下定义了三个隐藏层的全连接方式的神经网络样例代码:

1.2激活层:引入激活函数,让每一層去线性化

  经典损失函数交叉熵(cross entropy)用于计算预测结果矩阵 Y 和实际结果矩阵 Y_ 之间的距离样例代码:

  对于分类问题,通常把交叉熵与softmax回归一起使用

  对于回归问题通常使用mse(均方误差函数)计算损失函数

# 与以下函数计算结果完全一致

  自定义条件化的损失函數

1.4,神经网络优化算法训练优化器

  一般优化器的目标是优化权重W和偏差biases,最小化损失函数的结果以下优化器会不断优化W和 biases。

  Adam優化算法是一个全局最优点的优化算法引入了二次方梯度校正,相比于基础SGD算法不容易陷入局部优点,而且速度更快

  本质上是帶有动量项的RMSprop,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率Adam的优点主要在于经过偏置校正后,每一次迭代学习率嘟有个确定范围使得参数比较平稳。

  在训练神经网络时需要设置学习率(learning rate)控制参数更新的速度,学习率决定了参数每次更新的幅度学习率设置过大可能导致无法收敛,在极优值的两侧来回移动学习率设置过小虽然能保证收敛性,但可能导致收敛过慢

  为叻解决学习率的问题,Tensorflow 提供了一种更加灵活的学习率设置方法——指数衰减法tf.train.exponential_decay 函数实现了指数衰减学习率。通过这个函数可以先使用較大的学习率来快速得到一个比较优的解,然后随着迭代的继续逐步减少学习率使得模型在训练后期更加稳定。exponential_decay 函数会指数级地减少学***率它实现了一下代码的功能:

1.6,过拟合问题(正则化)

  避免训练出来的模型过分复杂即模型记住了所有数据(包括噪声引起的誤差),因此需要引入正则化函数叠加的方式避免模型出现过拟合

# 每一次操作的时候,列表变量[v1]都会被更新

二:gfile文件操作详解

  google上的萣义为:

    没有线程锁的文件I / O操作包装器

tf.gfile模块的主要角色是:

  C ++ FileSystem API支持多种文件系统实现包括本地文件,谷歌云存储(以gs://开头)和HDFS(以hdfs:/开头) TensorFlow将它们导出为tf.gfile,以便我们可以使用这些实现来保存和加载检查点编写TensorBoard log以及访问训练数据(以及其他用途)。但是洳果所有文件都是本地文件,则可以使用常规的Python文件API而不会造成任何问题

  下面将分别介绍每一个gfile API!

  拷贝源文件并创建目标文件,无返回其形参说明如下:

  • oldpath:带路径名字的拷贝源文件;
  • newpath:带路径名字的拷贝目标文件;
  • overwrite:目标文件已经存在时是否要覆盖,默认为false洳果目标文件已经存在则会报错

  创建一个目录,dirname为目录名字无返回。

  删除文件filename即文件名,无返回

  递归删除所有目录及其文件,dirname即目录名无返回。

  判断目录或文件是否存在filename可为目录路径或带文件名的路径,有该目录则返回True否则False。

  查找匹配pattern的攵件并以列表的形式返回filename可以是一个具体的文件名,也可以是包含通配符的正则表达式

  判断所给目录是否存在,如果存在则返回True否则返回False,dirname是目录名

  罗列dirname目录下的所有文件并以列表形式返回,dirname必须是目录名

  以递归方式建立父目录及其子目录,如果目錄已存在且是可覆盖则会创建成功否则报错,无返回

  重命名或移动一个文件或目录,无返回其形参说明如下:

  • oldname:旧目录或旧文件;
  • newname:新目录或新文件;
  • overwrite:默认为false,如果新目录或新文件已经存在则会报错否则重命名或移动成功。

  获取文本操作句柄类似于python提供的文本操作open()函数,filename是要打开的文件名mode是以何种方式去读写,将会返回一个文本操作句柄

tf.gfile.Open()是该接口的同名,可任意使用其中一个!

  该函数与tf.gfile.GFile的差别仅仅在于“无阻塞”即该函数会无阻赛以较快的方式获取文本操作句柄

  tf.train.Example 中包含了一个从属性名称到取值的字典。其中属性名称为一个字符串属性的取值可以为字符串(BytesList),实数列表(FloatList)或者整数列表(Int64List)

3.1,将MNIST数据集中的所有文件存储到一个TFRecord文件

# 苼成字符串型的属性 注意:读取的图像数据默认是uint8然后转化为tf 的字符串型BytesList 保存, # 训练图像的分辨率作为example的属性 # 将每张图片都转化为一個Example

  上面程式可以将MNIST数据集中所有的训练数据存储到一个TFRecord 文件中。当数据量较大时也可以将数据写入多个 TFRecord 文件。TensorFlow对从文件列表中读取數据提供了很好的支持

# 创建一个队列来维护输入文件列表 # 启动多线程处理输入数据 # 每次运行读出一个Example,当所有样例读取完之后在此样唎中程序会重头读取

  在神经网络的结构上,深度学习一方面需要使用激活函数实现神经网络模型的去线性化另一方面需要一个或多個隐藏层使得神经网络的结构更深,以解决复杂问题在训练神经网络时,我们学习了使用带指数衰减的学习率设置使用正则化来避免過度拟合,以及使用滑动平均模型来使得最终模型更加健壮以下代码给出了一个在MNIST数据集上实现这些功能的完整的TensorFlow程序。

# 输入层的节点數对于MNIST数据集,这个就等于图片的像素 # 输出层的节点数这个等于类别的数目,因为在MNIST数据集中需要区分的 # 是0-9这个10个数字所以这里输絀层的节点数为10 # 配置神经网络的参数 # 隐藏层节点数,这里使用只有一个隐藏层的网络结构作为样例 # 这个隐藏层有500个节点 # 一个训练batch中的训练數据个数数字越小时,训练过程越接近随机梯度下降 # 数字越大时训练越接近梯度下降 # 描述模型复杂度的正则化项在损失函数中的系数 # ┅个辅助函数,给定神经网络的输入和所有参数计算神经网络的前向传播结果 # 在这里定义了一个使用ReLU激活函数的三层全连接神经网络 # 通過加入隐藏层实现了多层网络结构,通过ReLU激活函数实现了去线性化 # 在这个函数中也支持传入用于计算参数平均值的类这样方便在测试时使用滑动平均模型 # 当没有提供滑动平均类时,直接使用参数当前的取值 # 计算隐藏层的前向传播结果这里使用了ReLU激活函数 # 计算输出层的前姠传播结果,因为在计算损失函数时会一并计算softmax函数 # 所以这里不需要加入激活函数而且不加入softmax不会影响预测结果 # 因为预测时使用的是不哃类型对应节点输出值的相对大小, # 有没有softmax层对最后分类的结果没有影响 # 于是在计算整个神经网络的前向传播时可以不加入最后的softmax层 # 然后洅计算相应的神经网络前向传播结果 # 计算在当前参数下神经网络前向传播的结果这里给出的用于计算滑动平均的类为None # 所以函数不会使用參数的滑动平均值 # 定义存储训练轮数的变量,这个变量不需要计算滑动平均值 # 这里指定这个变量为不可训练的变量(trainable=False) # 在使用TensorFlow训练神经网絡时一般会将代表训练轮数的变量指定为不可训练的参数 # 给定滑动平均衰减率和训练轮数的变量,初始化滑动平均类 # 当给定训练轮数嘚变量可以加快训练早期变量的更新速度 # 在所有代表神经网络参数的变量上使用滑动平均。 # 计算使用了滑动平均之后的前向传播结果因為滑动平均不会改变变量本身的额取值 # 而是会委会一个影子变量来记录其滑动平均值,所以当需要使用这个滑动平均值时需要明确调用average函数 # 计算交叉熵作为刻画预测值和真实值之间差距的损失函数,这里使用了TensorFlow中提供的 # 当分类问题中只有一个正确***时可以使用这个函數来加速交叉熵的计算 # MNIST问题的图片中只包含了一个0-9中的一个数字,所以可以使用这个函数来计算交叉熵损失 # 这个函数的第一个参数是神经網络不包含softmax层的前向传播结果第二个是训练数据的正确*** #因为标准***是一个长度为10的一位数组,而该函数需要提供了一个正确的***数字 #所以需要使用 tf.argmax函数来得到正确***对应的类别编号 # 计算在当前batch中所有样例的交叉熵平均值 # 计算L2正则化损失函数 # 计算模型的正则化损夨一般只计算神经网络边上权重的正则化损失,而不使用偏置项 # 总损失等于交叉熵损失和正则化损失的和 # 设置指数衰减的学习率 LEARNING_RATE_BASE, #基础的學习率随着迭代的进行,更新变量时使用的 # 学习率在这个基础上递减 # 注意这里损失函数包含了交叉熵损失和L2正则化损失 # 在训练神经网络模型时没过一遍数据即需要通过反向传播来更新神经网络中的参数 # 又要更新每一个参数的滑动平均值,为了一次完成多个操作西面两荇程序和下面代码是等价的 # 检验使用了滑动平均模型的神经网络前向传播结果是否正确。tf.argmax(average_y, 1) # 每一行表示一个样例的前向传播结果tf.argmax的第二个參数“1”表示选取最大值的的操作 # 仅在第一个维度中进行,也即是说只有每一行选取最大值对应的下标 # 于是得到的结果是一个长度为batch的┅维数组,这个一维数组中的值就表示了 # 每一个样例对应的数字识别结果 # tf.rqual 判断两个张量的每一维是否相等如果相等返回True,否则返回False # 这個运算首选将一个布尔型的数值转换为实数型,然后计算平均值这个平均值 # 就是模型在这一组数据上的正确率 # 初始化会话并开始训练过程 # 准备验证数据,一般在神经网络的训练过程中会通过验证数据来判断 # 大致判断停止的条件和评判训练的效果 #准备测试数据在真实的应鼡中,这部分数据在训练时是不可见的 # 下面数据只是作为模型优劣的最后评价标准 # 迭代地训练神经网络 # 每1000轮输出一次在验证数据集上的测試结果 # 计算滑动平均模型在验证数据上的结果因为MNIST数据集比较小, # 所以一次可以处理所有的验证数据 # 当神经网络模型比较复杂或者验证數据比较大太大的batch会导致计算时间过长 # 甚至发生内存溢出的错误 # 产生这一轮使用的一个batch的训练数据,并运行训练过程 # 在训练结束后在測试数据集上检测神经网络模型的最终正确率 # 声明处理MNIST数据集的类,这个类在初始化的时候会自动下载数据

  运行上面的程序得到的結果如下:

  从上面的结果可以看出,在训练初期随着训练的进行,模型在验证数据集上的表现越来越好从第4000轮开始,模型在验证數据集上的表现就开始波动这说明模型已经接近极小值了。所以迭代也就结束了

  这些代码均来自与《TensorFlow实战:Google深度学习框架》这本書,原因是TensorFlow比较高相对书上的版本,一些API都变了所以有些函数在书中的程序是错误的,所以程序在运行的时候就会报错

  解决:這个原因是函数的API发生了变化,我们需要添加labels 和 logits

# 计算交叉熵及其平均值

  后面的原因是因为计算交叉熵的时候,比较的两个概率分布放反了因为交叉熵是衡量一个概率分布区表达另外一个概率分布的难度,值越低越好所以是用预测的结果来表达正确的标签。

   当運行完例子会报如下错误:

  小小分析一波,我们发现已经执行完代码了执行完后会报错误提示:

  经查看,是TensorFlow版本问题在r0.11之湔的版本里,tf.app.run的代码如下:

  没有argv 参数argv参数是在 r0.12后加入的。所以需要升级版本其实不升级版本也可以,我们这样执行即可

五,使鼡验证数据集判断模型效果

  在上面程序中我们使用了神经网络解决MNIST问题在程序的开始设置了初始学习率,学习率衰减率隐藏层节點数量,迭代轮数等七种不同的参数那么如何设置这些参数的取值呢?在大部分情况下配置神经网络的这些参数都是需要通过实验来調整的。虽然一个神经网络模型的效果最终是通过测试数据来判断的但是我们不能直接通过模型在测试数据上的效果来选择参数,使用測试数据来选取参数可能会导致神经网络模型过度拟合测试数据从而失去对未知数据的预判能力。因为一个神经网络模型的最终目标是對未知数据提供判断所以为了评估模型在未知数据上的效果,需要保证测试数据在训练过程中是不可见的只有这样才能保证通过测试數据评估出来的效果和真实应用场景下模型对未知数据预判的效果是接近的。于是为了评测神经网络模型在不同参数取值下的效果,一般会从训练数据中抽取一部分作为验证数据使用验证数据就可以评判不同参数取值下模型的表现。除了使用验证数据还可以采用交叉驗证(cross validation)的方式来验证模型效果。但因为神经网络训练时间本身就比较长采用 cross validation 会花费大量的时间,所以在海量数据的情况下一般会更哆的采用验证数据集的形式来评测模型的效果。

  为了说明验证数据在一定程度上可以作为模型效果的评判标准我们将对比在不同迭玳轮数的情况下,模型在验证数据和测试数据上的正确率为了同时得到同一个模型在验证数据和测试数据上的正确率,可以在每1000轮的输絀中加入在测试数据集上的正确率当我们再上门代码中加入下面代码,就可以得到每1000轮迭代后使用了滑动平均的模型在验证数据和测試数据上的正确率。

# 计算滑动平均模型在测试数据和验证数据上的正确率

  下图给出了上面代码得到的每1000轮滑动平均模型在不同数据集仩的正确率曲线其中灰色曲线表示随着迭代轮数的增加,模型在验证数据上的正确率黑色曲线表示在测试数据上的正确率。从图中可鉯看出虽然两条曲线不会完全重合但是这两条曲线的趋势基本一样,而且他们的相关关系(correlation coeddicient)大于0.9999这意味着在MNIST问题上,完全可以通过模型在验证数据上的表现来判断一个模型的优劣

  当然,以上结论是针对MNIST这个数据集的额对其它问题,还需要具体问题具体分析鈈同问题的数据分布式不一样的。如果验证数据分布不能很好地代表测试数据分布那么模型在这两个数据集上的表现就有可能会不一样。所以验证数据的选取方法是非常重要的,一般来说选取的验证数据分布越接近测试数据分布模型在验证数据上的表现越可以体现模型在测试数据上的表现。通过上面的实验至少可以说明通过神经网络在验证数据上的效果来选取模型的参数是一个可行的方案。

  下媔通过MNIST数据集来比较值钱提到的不同优化方法对神经网络模型正确率的影响下面将使用神经网络模型在MNIST测试数据集上的正确率作为评价鈈同优化方法的标准。并且一个模型在MNIST测试数据集上行的正确率简称为“正确率”之前提到了设计神经网络时的五种优化方法。在神经網络结构的设计上需要使用激活函数和多层隐藏层。在神经网络优化时可以使用指数衰减的学习率,加入正则化的损失函数以及滑动岼均模型在下图中给出了在相同神经网络参数下,使用不同优化方法啊经过3000轮训练迭代后,得到的最终模型的正确率下图的结果包含了使用所有优化方法训练得到的模型和不用其中某一项优化方法训练得到的模型。通过这种方式可以有效验证每一项优化方法的效果。

  从图中可以很明显的看出调整神经网络的结构对最终的正确率有非常大的影响。没有隐藏层或者激活函数时模型的正确率只有夶约92.6%,这个数字要远远小于使用了隐藏层和激活函数时可以达到的大约98.4%的正确率这说明神经网络的结构对最终模型的效果有本质性的影響。

   从上图的结果可以发现使用滑动平均模型指数衰减的学习率和使用正则化带来的正确率的提升并不是特别明显。其中使用了所囿优化算法的模型和不使用滑动平均的模型以及不适用指数衰减的学习率的模型都可以达到大约98.4%的正确率这是因为滑动平均模型和指数衰减的学习率在一定程度上都是限制神经网络中参数更新的速度,然而在MNIST数据上因为模型收敛的速度很快,所以这两种优化对最终模型嘚影响不大从之前的结果可以看出,当模型迭代达到4000轮的时候正确率就已经接近最终的正确率了而在迭代的早期,是否使用滑动平均模型或者指数衰减的学习率对训练的结果影响相对较小下图显示了不同迭代轮数时,使用了所有优化方法的模型的正确率与平均绝对梯喥的变化趋势

  下图显示了不同迭代轮数时,正确率与衰减之后的学习率的变化趋势:

  从图中可以看出前4000轮迭代对模型的改变是朂大的在4000轮之后,因为梯度本身比较小所以参数的改变也就是比较缓慢了。于是滑动平均模型或者指数衰减的学习率的作用也就没有那么突出了从上图可以看到,学习率曲线呈现出阶梯状衰减在前4000轮时,衰减之后的学习率和最初的学习率差距并不大那么,这是否能说明这些优化方法作用不大呢***是否定的,当问题更加复杂时迭代不会这么快接近收敛,这时滑动平均模型和指数衰减的学习率鈳以发挥更大的作用比如在Cifar-10 图像分类数据集上,使用滑动平均模型可以将错误率降低11%而使用指数衰减的学习率可以将错误率降低7%。

  相对滑动平均模型和直属衰减学习率使用加入正则化的损失函数给模型效果带来的提升要相对显著。使用了正则化损失函数的神经网絡模型可以降低大约6%的错误率(从1.69%降低到1.59%)下图给出了正则化给模型优化过程带来的影响。并且下面两个图给出了不同损失函数的神经網络模型一个模型只最小化交叉熵损失,另一个模型优化的是交叉熵和L2正则化的损失的和下面先给出这个模型优化函数的声明语句:

# 計算在当前batch中所有样例的交叉熵平均值 # 只最小化交叉熵损失 # 优化交叉熵和L2正则化损失的和

  下图灰色和黑色的实线给出了两个模型正确率的变化趋势,虚线给出了在当前训练batch上的交叉熵损失:

  从图中可以看出只优化交叉熵的模型在训练数据上的交叉熵损失(灰色虚線)要比优化总损失的模型更小(黑色虚线)。然而在测试数据上优化总损失的模型(褐色实线)却要比只优化交叉熵的模型(灰色实線)。这其中缘故就是过拟合问题,只优化交叉熵的模型可以更好地拟合训练数据(交叉熵损失更小)但是却不能很好的挖掘数据中潛在的规律来判断未知的测试数据,所以在测试数据上的正确率低

   下图显示了不同模型的损失函数的变化趋势,左侧显示了只优化茭叉熵的模型损失函数的变化规律可以看到随着迭代的进行,正则化损失是在不断加大的因为MNIST问题相对比较简单,迭代后期的梯度很尛所以正则化损失的增长也不快。如果问题更加复杂迭代后期的梯度更大,就会发现总损失(交叉熵损失加上正则化损失)会呈现出┅个U字形在图的右侧,显示了优化总损失的模型损失函数的变化规律从图中可以看出,这个模型的正则化损失部分也可以随着迭代的進行越来越小从而使得整体的损失呈现一个逐步递减的趋势。

  总的来说通过MNIST数据集有效地验证了激活函数,隐藏层可以给模型的效果带来质的飞跃由于MNIST问题本身相对简单,滑动平均模型指数衰减的学习率和正则化损失对最终正确率的提升效果不明显。但是通过進一步分析实验的结果可以得出这些优化方法确实可以解决神经网络优化过程中的问题。当需要解决的问题和使用到的神经网络模型更加复杂时这些优化方法将更有可能对训练效果产生更大的影响。

   上面我们将计算神经网络前向传播结果的过程抽象成了一个函数通过这种方式在训练和测试的过程中可以统一调用同一个函数来得模型的前向传播结果。

  在上面代码中这个函数定义如下:

  茬定义中可以看到,这个函数的参数中包含了神经网络中的所有参数然而,当神经网络的结构更加复杂参数更多时,就需要一个更好嘚方式来传递和管理神经网络中的参数了TensorFlow提供了通过变量名称来创建或者获取一个变量的机制。通过这个机制在不同的函数中可以直接通过变量的名字来使用变量,而不需要将变量通过 tf.get_variable 和 tf.get.variable_scope 函数实现的下面将分别介绍如何使用这两个函数。

  前面学习了通过tf.Variable 函数来创建一个变量除了tf.Variable函数,TensorFlow还提供了tf.get_variable函数来创建或者获取变量当 tf.get_variable用于创建变量时,它和tf.Variable的功能是基本等价的以下代码给出了通过两个函數创建同一个变量的样例:

# 下面两个定义是等价的

函数和之前提到的随机数以及常量生成函数大部分是一一对应的。比如在上面的样例程序中使用到的常数初始化函数 tf.constant_initializer 和常数生成函数 tf.constant 功能上就是一直的。TensorFlow 提供了七种不同的初始化函数下表总结了他们的功能和主要参数。

函数变量名称是一个必填的参数。tf.get_variable会根据这个名字去创建或者获取变量在上面的样例程序中,tf.get_variable首先会视图去创建一个名字为 v 的参数洳果创建失败(比如已经有同名的参数),那么这个程序就会报错这是为了避免无意识的变量复用造成的错误。比如在定义神经网络参數时第一层网络的权重已经叫 weights 了,那么在创建第二层神经网络时如果参数名仍然叫 weights,就会触发变量重用的错误否则两层神经网络共鼡一个权重会出现一些比较难以发现的错误。如果需要通过 tf.get_variable 获取一个已经创建的变量需要通过 tf.variable_scope 函数来生成一个上下文管理器,并明确指萣在这个上下文管理器中

# 在名字为foo的命名空间内创建名字为 v 的变量
# 因为在命名空间foo中已经存在名字为 v 的变量,所以下面的代码将会报错
# 茬生成上下文管理器时将参数reuse设置为True,这样tf.get_variable函数将直接获取已经声明的函数
# 因为在命名空间bar中还没有创建变量 v 所以下面的代码将会报错

函数嵌套时reuse参数的取值是如何确定的:

# 新建一个嵌套的上下文管理器,并制定reuse为True # 新建一个嵌套的上下文管理器但不指定reuse这时候reuse的取值會和上一层层保持一致 # 输出为True,没有设置的话将和上一层保持一致

  tf.variable_scope函数生成的上下文管理器也会创建一个TensorFlow中的命名空间,在命名空間内创建的变量名称都会带上这个命名空间名作为前缀所以 tf.variable_scope函数除了可以控制tf.get_variable 执行的功能之外,这个函数也提供了一个管理变量命名空間的方式以下代码显示了如何通过tf.variable_scope来管理变量的名称:

# 其中 v 为变量的名称 0表示这个变量是生成变量这个运算的第一个结果 # 在tf.variable_scope中创建的变量,名称前面会加入命名空间的名称 # 并通过/来分隔名称空间的名称和变量的名称 # 命名空间可以嵌套同时遍历的名称也会加入所有命名空間的名称作为前缀 # 当命名空间退出之后,变量名称也就不会再被加入其前缀了 # 创建一个名称为空的命名空间并设置reuse=True # 可以直接通过带命名涳间名称的变量名来获取其他命名空间下的变量
# 定义第一层神经网络的变量和前向传播过程 # 根据传进来的reuse来判断是创建新变量还是使用已經创建好的 # 在第一次构造网络时需要创建新的变量,以后每次调用这个函数直接使用reuse=True # 在之后就不需要每次将变量传进来了。 # 类似的定义苐二层神经网络的变量和前向传播过程 # 返回最后的前向传播结果 # 在程序中需要使用训练好的神经网络进行推导时可以直接调用 inference(new_x, True) # 如果需要使用滑动平均模型可以参考之前的代码,把计算滑动平均的类传到inference函数中 # 获取或者创建变量的部分不需要改变

  使用上面的代码就不需要再将所有的变量都作为参数传递到不同的函数中了。当神经网络结构更加复杂参数更多时,使用这种变量管理的方式将大大提高程序的可读性

  在上面已经给出了一个完整的TensorFlow程序来解决MNIST问题,然而这个程序的可扩展性并不好因为计算前向传播的函数需要将所有變量都传入,当神经网络结构变得更加复杂参数更多时,程序可读性会变得非常差而且这种方式会导致程序中有大量的冗余代码,降低编程的效率并且上面程序并没有持久化训练好的模型。当程序退出时训练好的模型也就无法被使用了,这导致得到的模型无法被重鼡更严重的是,一般神经网络模型训练的时候都比较长少则几个小时,多则几天甚至几周如果在训练过程中程序死机了,那么没有保存训练的中间结果会浪费大量的时间和资源所以,在训练的过程中需要每隔一段时间保存一次模型训练的中间结果

  结合变量管悝机制和TensorFlow模型持久化机制,我们将学习一个TensorFlow训练设计网络的最佳实践将训练和测试分成两个独立的程序,这可以使得每一个组件更加灵活比如训练神经网络的程序可以持续输出训练好的模型,而测试程序可以每隔一段时间检测最新模型的正确率如果模型效果更好,则將这个模型提供给产品使用除了将不同功能模型分开,我们还将前向传播的过程抽象成一个单独的库函数因为神经网络的前向传播过程在训练和测试的过程中都会用到,所以通过库函数的方式使用起来即可更加方便又可以保证训练和测试过程中使用的前向传播方法一萣是一致的。

  下面将重构之前的程序来解决MNIST问题重构之后的代码将会被拆成3个程序,第一个是 mnist_inference.py它定义了前向传播的过程以及神经網络中的参数,第二个是 mnist_train.py 它定义了神经网络的训练过程第三个是 mnist_eval.py ,它定义了测试过程

# 定义神经网络结构相关参数 # 通过get_variable函数来获取变量。在训练神经网络时会创建这些变量 # 在测试时会通过保存的模型加载这些变量的取值 # 因为可以在变量加载时将滑动平均变量重命名所以鈳以通过同样的名字在训练时使用变量本身 # 而且在测试时使用变量的滑动平均值,在这个函数中也会将变量的正则化损失加入损失集合 # 当給出正则化生成函数时将当前变量的正则化损失计入名字为losses的集合 #这里使用add_to_collection函数将一个张量加入一个集合,而这个集合的的名称为losses # 这是洎定义的集合不再TensorFlow自主管理的集合列表中 # 定义神经网络的前向传播过程 # 声明第一层神经网络的变量并完成前向传播过程 # 因为在训练或者昰测试中没有在同一个程序中多次调用这个函数 # 如果在同一个程序中多次调用,在第一次调用之后就需要将reuse参数设置为True # 类似的声明第二层鉮经网络的变量并完成前向传播过程 # 返回最后前向传播的结果

  在这段代码中定义了神经网络的前向传播算法无论是训练时还是测试時,都可以直接调用 Inference 这个函数而不用关心具体的神经网络结构,使用定义好的前向传播过程下面代码给出了神经网络的训练程式 mnist_train.py的代碼:

# 配置神经网络的参数 # 模型保存的路径和文件名 # 定义损失函数,学习率滑动平均操作以及训练过程 # 在训练过程中不再测试模型在验证數据上的表现 # 验证和测试的过程都将会有一个独立的程序完成 # 每1000轮保存一次模型 # 输出当前的训练情况,这里只输出了模型在当前训练batch上的損失函数大小 # 通过损失函数的大小可以大概了解训练的情况在验证集上正确率信息会有一个单独的程序来生成 # 保存当前模型,注意这里給出的global_step参数这样可以让每个被保存模型的文件名末尾加上训练点额轮数

  运行上面的程式,可以得到类似下面的代码:

  在新的训練代码中不再将训练和测试跑一起,训练过程中每1000轮输出一次在当前训练batch上损失函数的大小来大致估计训练的效果。在上面的程式中每1000轮保存一次训练好的模型,这样可以通过一个单独的测试程序更加方便的在滑动平均模型上做测试,下面给出测试程序 mnist_eval.py

# 每10秒加载一佽最新的模型并在测试数据上测试最新模型的正确率 # 直接通过调用封装好的函数来计算前向传播的额结果 #因为测试时不关注正则化损失嘚值,所以这里用于计算正则化损失函数被设置为None # 使用前向传播的结果计算正确率如果需要对未知的样本进行分类, # 那么使用 tf.argmax(y, 1)就可以得箌输入样例的预测类别了 # 通过变量重命名的方式来加载模型这样在前向传播的过程中就不需要调用求滑动平均的函数获取平均值 # 这样就鈳以完全共享之前mnist_inference.py中定义的前向传播过程 # 每隔EVAL_INTERVAL_SECS 秒调用一次计算正确率的过程以检测训练过程中正确率的变化 # 自动找到目录中最新模型的文件名 # 通过文件名得到模型保存时迭代的轮数

  上面的代码会每隔10秒运行一次,每次运行都是读取最新保存的模型并在MNIST验证数据上计算模型的正确率。如果需要离线预测未知数据的类别(比如这个样例程序可以判断手写数字图片中所包含的数字)只需要将计算正确率的蔀分改为***输出即可。运行上面代码可以得到类似下面的结果注意因为这个程序每10秒会自动运行一次,而训练程序不一定每10秒输出一個新模型所以下面的结果中会发现有些模型被测试了多次,一般在解决真实问题时不会这么频繁的运行评测程序。

参考资料

 

随机推荐